diff --git a/.gitignore b/.gitignore
index d209520..ad1b63e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -190,6 +190,7 @@
 /components/history_clusters/internal
 /components/leveldb_proto_test_support.xml
 /components/ntp_tiles/resources/internal
+/components/optimization_guide/internal
 /components/resources/default_100_percent/google_chrome
 /components/resources/default_200_percent/google_chrome
 /components/resources/default_300_percent/google_chrome
diff --git a/DEPS b/DEPS
index cf98143..691131b2 100644
--- a/DEPS
+++ b/DEPS
@@ -190,7 +190,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:f0a9c0d3581d7e0d1f6f0e4805e32e872237fb62',
+  'luci_go': 'git_revision:91a04914ac71b7b6fe7b95ce8691d45eeb69bf4f',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -222,11 +222,11 @@
   # 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': 'd421a286df317ee2fc781cadc60c036430eeab8a',
+  'skia_revision': '292a09da2baf1ed93d828e280c2ffe7500f36375',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'a14a4ec12bdca937587bb091ff114ffbe56d0465',
+  'v8_revision': 'd5b4514080a0b94f1c8df55b6cad8ccf231c29f5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -234,7 +234,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2534ee4c5b9da63cfc7a60b14ecd925116105ed4',
+  'angle_revision': '41980f05a0ba9032b1496cab969c2acb727b1a89',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -273,7 +273,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '59e95b014aa162393d6d569225cf713d71ffdc33',
+  'freetype_revision': '5d27b10f4c6c8e140bd48a001b98037ac0d54118',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -293,7 +293,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': 'a67592355de8bcf2f6ae916456f10fdfb2e0e997',
+  'catapult_revision': '066d46004fba4ea48646d1ee30e42e46b822e281',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -301,7 +301,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'f389adc13c107bf3a1c24b5bc5f7c20d517e5ab0',
+  'devtools_frontend_revision': '503b13feb0f8871c1d213dda2f76c612f9c3f467',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -341,11 +341,11 @@
   # 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': '052aad77582153e21854dae2bd7204655bcd9778',
+  'dawn_revision': 'b81021dc82016a0ab2e5a486b26b8eaae9423d10',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '51f584db29001036c20db3f72f09b00b875ae625',
+  'quiche_revision': '6f99b68e19950729c59b4f325db74c50361d3ce1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -365,7 +365,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libavif
   # and whatever else without interference from each other.
-  'libavif_revision': '45d58a5160ba2c33f5b341f3ba4b8ffe82928f87',
+  'libavif_revision': '3461524537728f487fabef580f32a6311cd492ff',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
@@ -385,11 +385,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libcxxabi_revision':    '6803464b0f46df0a51862347d39e0791b59cf568',
+  'libcxxabi_revision':    'bb278658aa0d4cc88dd4ca5bc5df428f92b85ddb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libunwind_revision':    'a5feaf61658af4453e282142a76aeb6f9c045311',
+  'libunwind_revision':    '333cca20381ead0d1baa7bcc38219e5bfd52f664',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -738,7 +738,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'PlxbY_1zdmHx9JtVYzJHudzfuY7EyHMpNvk-Qk2JlAcC',
+          'version': 'kwXj5TyfSiM-CXBynUhJkK6TTJMvcWbaA3aCQu9nE4UC',
       },
     ],
     'condition': 'checkout_android',
@@ -954,7 +954,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7a515fb8020d3dd83999cab59923a70b890d46b8',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8cb0c26f1b5edef8fd68211017fc891253a9bfd5',
       'condition': 'checkout_chromeos',
   },
 
@@ -1343,7 +1343,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + 'c493f7233e12569bbd6186c387b132e274a27d51',
+    Var('chromium_git') + '/openscreen' + '@' + 'bffb5c2247c5705401499ff13b686b119d9918b6',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245',
@@ -1360,7 +1360,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '7b7e355d04c3b5f759e8dfd3352b550a6ec1a0a7',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '97facadd961825cf2b6eb12398e0908a102d0c4a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1589,7 +1589,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '827cad9e402b63bbe38787456115bcb681a8a152',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'dd92c301f02301f1b01412f8070af02c518a2c59',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ed8964de52179ad80adb66c5b23347ac5870f4ba',
 
   'src/third_party/webrtc':
     Var('webrtc_git') + '/src.git' + '@' + '51969310ef432a9c340bb091eea1f1553ca01587',
@@ -1653,7 +1653,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0881a181d2a6533266a9d97eefa47cddd69ea2b5',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@904a422ba51f7d57fb3b1ceb170b322ab97b169c',
     'condition': 'checkout_src_internal',
   },
 
@@ -1672,7 +1672,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'X4D56rlbi2FQDHCzzxKgtUa7i2PpYfk8RGJjwUUmrEsC',
+        'version': '9nZk3G149odzs3UYfxp9NNNNeccCfb8UWqOl8poTJSwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1683,7 +1683,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '4-IHCJ0juqQPEOL75uZN5C4bzT97E1hEJUh8masGfAEC',
+        'version': 'zLyaMA4wGNqn0zmdixOgq06SE1id4oAGIv1fwJlYftkC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index b3eead39..3c9624e 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2356,12 +2356,10 @@
     'chromedriver': ['mathias@chromium.org'],
     'chromeos': ['oshima+watch@chromium.org'],
     'chromeos_attestation': ['dkrahn+watch@chromium.org'],
-    'chromeos_bluetooth': ['hansberry+watch-bluetooth@chromium.org',
-                           'vecore+watch-bluetooth@google.com'],
+    'chromeos_bluetooth': ['hansberry+watch-bluetooth@chromium.org'],
     'chromeos_cellular': ['azeemarshad+watch-cellular@chromium.org',
                           'benchan+watch-cellular@chromium.org',
-                          'ejcaruso+watch-cellular@chromium.org',
-                          'vecore+watch-cellular@google.com'],
+                          'ejcaruso+watch-cellular@chromium.org'],
     'chromeos_geolocation': ['alemate+watch@chromium.org'],
     'chromeos_lkgm': ['achuith+watch@chromium.org',
                       'bpastene+watch@chromium.org'],
@@ -2373,8 +2371,7 @@
                      'benchan+watch-network@chromium.org',
                      'ejcaruso+watch-network@chromium.org',
                      'jonmann+watch-network@chromium.org',
-                     'stevenjb+watch-network@chromium.org',
-                     'vecore+watch-network@google.com'],
+                     'stevenjb+watch-network@chromium.org'],
     'chromeos_tast_control': ['chromeos-engprod+watch@google.com',
                               'bpastene+watch@chromium.org',
                               'mukai+watch@chromium.org',
@@ -2382,8 +2379,7 @@
     'chromeos_timezone': ['alemate+watch@chromium.org'],
     'chromeos_webui': ['alemate+watch@chromium.org'],
     'chromeos_wifi_sync': ['jonmann+watch@chromium.org',
-                           'stevenjb+watch@chromium.org',
-                           'vecore+watch@google.com'],
+                           'stevenjb+watch@chromium.org'],
     'chromevox': ['akihiroota@chromium.org',
                   'anastasi+watch@google.com',
                   'dtseng+chromevox@chromium.org',
@@ -2602,8 +2598,7 @@
     'midi': ['toyoshim+midi@chromium.org'],
     'multidevice': ['hansberry+watch-multidevice@chromium.org',
                     'nohle+watch-multidevice@chromium.org',
-                    'themaxli+watch-multidevice@chromium.org',
-                    'vecore+watch-multidevice@google.com'],
+                    'themaxli+watch-multidevice@chromium.org'],
     'multipaste': ['andrewxu+watch-multipaste@google.com',
                    'dmblack+watch-multipaste@google.com',
                    'newcomer+watch-multipaste@google.com'],
@@ -2619,7 +2614,6 @@
                'hansenmichael+watch-nearby@google.com',
                'knollr+watch-nearby@chromium.org',
                'nohle+watch-nearby@chromium.org',
-               'vecore+watch-nearby@google.com',
                'xlythe+watch-nearby@google.com'],
     'net': ['net-reviews@chromium.org'],
     'net_base': ['bnc+watch@chromium.org',
@@ -2736,8 +2730,7 @@
     'site_instance': ['ajwong+watch@chromium.org',
                       'alexmos+watch@chromium.org',
                       'creis+watch@chromium.org'],
-    'smartlock': ['hansberry+watch-smartlock@chromium.org',
-                  'vecore+watch-smartlock@google.com'],
+    'smartlock': ['hansberry+watch-smartlock@chromium.org'],
     'smb': ['cros-enterprise-lax+smbwatch@chromium.org'],
     'source_idls': ['jmedley+watch@chromium.org'],
     'speed_metrics_changelog': ['igrigorik@chromium.org',
@@ -2787,8 +2780,7 @@
     'telemetry': ['telemetry-reviews@chromium.org'],
     'test_runner': ['einbinder+watch-test-runner@chromium.org'],
     'tests': [],
-    'tether': ['hansberry+watch-tether@chromium.org',
-               'vecore+watch-tether@google.com'],
+    'tether': ['hansberry+watch-tether@chromium.org'],
     'text_to_speech': ['dtseng+watch@chromium.org'],
     'textinput': ['keithlee+watch@chromium.org',
                   'nona+watch@chromium.org',
diff --git a/android_webview/browser/aw_pac_processor.h b/android_webview/browser/aw_pac_processor.h
index 1cb80eea..cf32041 100644
--- a/android_webview/browser/aw_pac_processor.h
+++ b/android_webview/browser/aw_pac_processor.h
@@ -8,7 +8,6 @@
 #include <android/multinetwork.h>
 
 #include "base/android/scoped_java_ref.h"
-#include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "net/log/net_log_with_source.h"
diff --git a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
index ec69d71..a8456b6 100644
--- a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
+++ b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
@@ -12,7 +12,6 @@
 #include "base/callback.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "base/observer_list.h"
 #include "base/sequence_checker.h"
 
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.cc b/android_webview/browser/metrics/aw_metrics_service_client.cc
index 7dfdd401..9b8cd4e 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.cc
+++ b/android_webview/browser/metrics/aw_metrics_service_client.cc
@@ -104,20 +104,29 @@
     return ::metrics::AndroidMetricsServiceClient::ShouldRecordPackageName();
   }
 
+  base::UmaHistogramEnumeration(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      package_name_record_status_);
   return cached_package_name_record_.has_value() &&
          cached_package_name_record_.value().IsAppPackageNameAllowed();
 }
 
 void AwMetricsServiceClient::SetAppPackageNameLoggingRule(
     absl::optional<AppPackageNameLoggingRule> record) {
-  if (!record.has_value())
-    return;
-
   absl::optional<AppPackageNameLoggingRule> cached_record =
       GetCachedAppPackageNameLoggingRule();
+  if (!record.has_value()) {
+    package_name_record_status_ =
+        cached_record.has_value()
+            ? AppPackageNameLoggingRuleStatus::kNewVersionFailedUseCache
+            : AppPackageNameLoggingRuleStatus::kNewVersionFailedNoCache;
+    return;
+  }
 
   if (cached_record.has_value() &&
       record.value().IsSameAs(cached_package_name_record_.value())) {
+    package_name_record_status_ =
+        AppPackageNameLoggingRuleStatus::kSameVersionAsCache;
     return;
   }
 
@@ -126,6 +135,8 @@
   local_state->Set(prefs::kMetricsAppPackageNameLoggingRule,
                    record.value().ToDictionary());
   cached_package_name_record_ = record;
+  package_name_record_status_ =
+      AppPackageNameLoggingRuleStatus::kNewVersionLoaded;
 
   UmaHistogramTimes(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay",
@@ -142,6 +153,10 @@
   DCHECK(local_state);
   cached_package_name_record_ = AppPackageNameLoggingRule::FromDictionary(
       *(local_state->Get(prefs::kMetricsAppPackageNameLoggingRule)));
+  if (cached_package_name_record_.has_value()) {
+    package_name_record_status_ =
+        AppPackageNameLoggingRuleStatus::kNotLoadedUseCache;
+  }
   return cached_package_name_record_;
 }
 
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.h b/android_webview/browser/metrics/aw_metrics_service_client.h
index 9563708..53d9b11 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.h
+++ b/android_webview/browser/metrics/aw_metrics_service_client.h
@@ -128,6 +128,19 @@
     virtual bool HasAwContentsEverCreated() const = 0;
   };
 
+  // An enum to track the status of AppPackageNameLoggingRule used in
+  // ShouldRecordPackageName. These values are persisted to logs. Entries should
+  // not be renumbered and numeric values should never be reused.
+  enum class AppPackageNameLoggingRuleStatus {
+    kNotLoadedNoCache = 0,
+    kNotLoadedUseCache = 1,
+    kNewVersionFailedNoCache = 2,
+    kNewVersionFailedUseCache = 3,
+    kNewVersionLoaded = 4,
+    kSameVersionAsCache = 5,
+    kMaxValue = kSameVersionAsCache,
+  };
+
   static AwMetricsServiceClient* GetInstance();
   static void SetInstance(
       std::unique_ptr<AwMetricsServiceClient> aw_metrics_service_client);
@@ -187,6 +200,8 @@
   std::unique_ptr<Delegate> delegate_;
 
   absl::optional<AppPackageNameLoggingRule> cached_package_name_record_;
+  AppPackageNameLoggingRuleStatus package_name_record_status_ =
+      AppPackageNameLoggingRuleStatus::kNotLoadedNoCache;
 
   DISALLOW_COPY_AND_ASSIGN(AwMetricsServiceClient);
 };
diff --git a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
index b835e1a..3ab0bff 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
+++ b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
@@ -19,6 +19,9 @@
 
 namespace android_webview {
 
+using AppPackageNameLoggingRuleStatus =
+    AwMetricsServiceClient::AppPackageNameLoggingRuleStatus;
+
 namespace {
 
 constexpr char kTestAllowlistVersion[] = "123.456.789.10";
@@ -72,6 +75,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNotLoadedNoCache, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_WithCache) {
@@ -97,6 +105,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNotLoadedUseCache, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest,
@@ -119,6 +132,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNewVersionLoaded, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest,
@@ -143,6 +161,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNewVersionLoaded, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest,
@@ -169,6 +192,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNewVersionFailedUseCache, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_FailedResult) {
@@ -185,6 +213,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kNewVersionFailedNoCache, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_SameAsCache) {
@@ -206,6 +239,11 @@
 
   histogram_tester.ExpectTotalCount(
       "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0);
+  histogram_tester.ExpectBucketCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus",
+      AppPackageNameLoggingRuleStatus::kSameVersionAsCache, 1);
+  histogram_tester.ExpectTotalCount(
+      "Android.WebView.Metrics.PackagesAllowList.RecordStatus", 1);
 }
 
 }  // namespace android_webview
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
index eb81376..73f59a02 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
@@ -31,6 +31,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.components.metrics.ChromeUserMetricsExtensionProtos.ChromeUserMetricsExtension;
 import org.chromium.components.metrics.MetricsSwitches;
+import org.chromium.components.metrics.StabilityEventType;
 import org.chromium.components.metrics.SystemProfileProtos.SystemProfileProto;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -288,6 +289,55 @@
     @Test
     @MediumTest
     @Feature({"AndroidWebView"})
+    public void testMetadata_stability_pageLoad() throws Throwable {
+        EmbeddedTestServer embeddedTestServer = EmbeddedTestServer.createAndStartServer(
+                InstrumentationRegistry.getInstrumentation().getContext());
+        try {
+            // Load a page to ensure the renderer process is created.
+            mRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
+                    embeddedTestServer.getURL("/android_webview/test/data/hello_world.html"));
+
+            Assert.assertEquals("Should have correct stability histogram kPageLoad count", 1,
+                    RecordHistogram.getHistogramValueCountForTesting(
+                            "Stability.Counts2", StabilityEventType.PAGE_LOAD));
+        } finally {
+            embeddedTestServer.stopAndDestroyServer();
+        }
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testMetadata_stability_rendererLaunchCount() throws Throwable {
+        EmbeddedTestServer embeddedTestServer = EmbeddedTestServer.createAndStartServer(
+                InstrumentationRegistry.getInstrumentation().getContext());
+        try {
+            // Load a page to ensure the renderer process is created.
+            mRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
+                    embeddedTestServer.getURL("/android_webview/test/data/hello_world.html"));
+
+            Assert.assertEquals("Should have correct stability histogram kRendererLaunch count", 1,
+                    RecordHistogram.getHistogramValueCountForTesting(
+                            "Stability.Counts2", StabilityEventType.RENDERER_LAUNCH));
+        } finally {
+            embeddedTestServer.stopAndDestroyServer();
+        }
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testMetadata_stability_browserLaunchCount() throws Throwable {
+        // This should be triggered simply by initializing the MetricsService. This should be logged
+        // (and persisted) even before we start collecting the first metrics log.
+        Assert.assertEquals("Should have correct stability histogram kLaunch count", 1,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        "Stability.Counts2", StabilityEventType.LAUNCH));
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"AndroidWebView"})
     public void testMetadata_androidHistograms() throws Throwable {
         // Wait for a metrics log, since AndroidMetricsProvider only logs this histogram during log
         // collection. Do not assert anything about this histogram before this point (ex. do not
diff --git a/android_webview/renderer/aw_render_thread_observer.cc b/android_webview/renderer/aw_render_thread_observer.cc
index 0f8da27..c1a07c7 100644
--- a/android_webview/renderer/aw_render_thread_observer.cc
+++ b/android_webview/renderer/aw_render_thread_observer.cc
@@ -51,8 +51,10 @@
 }
 
 void AwRenderThreadObserver::EnableIdleThrottling() {
-  power_scheduler::PowerScheduler::GetInstance()->SetPolicy(
-      power_scheduler::SchedulingPolicy::kThrottleIdle);
+  power_scheduler::SchedulingPolicyParams params{
+      power_scheduler::SchedulingPolicy::kThrottleIdleAndNopAnimation,
+      base::TimeDelta::FromMilliseconds(500), 0.5f};
+  power_scheduler::PowerScheduler::GetInstance()->SetPolicy(params);
 }
 
 }  // namespace android_webview
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc
index f3bf35f..55e0e914 100644
--- a/ash/accelerators/debug_commands.cc
+++ b/ash/accelerators/debug_commands.cc
@@ -34,6 +34,24 @@
 namespace debug {
 namespace {
 
+void HandlePrintLayerHierarchy() {
+  std::ostringstream out;
+  PrintLayerHierarchy(&out);
+  LOG(ERROR) << out.str();
+}
+
+void HandlePrintViewHierarchy() {
+  std::ostringstream out;
+  PrintViewHierarchy(&out);
+  LOG(ERROR) << out.str();
+}
+
+void HandlePrintWindowHierarchy() {
+  std::ostringstream out;
+  PrintWindowHierarchy(&out, /*scrub_data=*/false);
+  LOG(ERROR) << out.str();
+}
+
 gfx::ImageSkia CreateWallpaperImage(SkColor fill, SkColor rect) {
   // TODO(oshima): Consider adding a command line option to control wallpaper
   // images for testing. The size is randomly picked.
@@ -109,24 +127,6 @@
 
 }  // namespace
 
-void HandlePrintLayerHierarchy() {
-  std::ostringstream out;
-  PrintLayerHierarchy(&out);
-  LOG(ERROR) << out.str();
-}
-
-void HandlePrintViewHierarchy() {
-  std::ostringstream out;
-  PrintViewHierarchy(&out);
-  LOG(ERROR) << out.str();
-}
-
-void HandlePrintWindowHierarchy() {
-  std::ostringstream out;
-  PrintWindowHierarchy(&out, /*scrub_data=*/false);
-  LOG(ERROR) << out.str();
-}
-
 void PrintUIHierarchies() {
   // This is a separate command so the user only has to hit one key to generate
   // all the logs. Developers use the individual dumps repeatedly, so keep
diff --git a/ash/app_list/bubble/app_list_bubble_apps_page.cc b/ash/app_list/bubble/app_list_bubble_apps_page.cc
index 951e7775..9107e84b 100644
--- a/ash/app_list/bubble/app_list_bubble_apps_page.cc
+++ b/ash/app_list/bubble/app_list_bubble_apps_page.cc
@@ -40,8 +40,10 @@
 }  // namespace
 
 AppListBubbleAppsPage::AppListBubbleAppsPage(
-    AppListViewDelegate* view_delegate) {
+    AppListViewDelegate* view_delegate,
+    ApplicationDragAndDropHost* drag_and_drop_host) {
   DCHECK(view_delegate);
+  DCHECK(drag_and_drop_host);
 
   SetUseDefaultFillLayout(true);
 
@@ -95,6 +97,8 @@
       scroll_contents->AddChildView(std::make_unique<ScrollableAppsGridView>(
           a11y_announcer_.get(), view_delegate,
           /*folder_delegate=*/nullptr));
+  scrollable_apps_grid_view_->SetDragAndDropHostOfCurrentAppList(
+      drag_and_drop_host);
   scrollable_apps_grid_view_->Init();
   AppListModel* model = view_delegate->GetModel();
   scrollable_apps_grid_view_->SetModel(model);
diff --git a/ash/app_list/bubble/app_list_bubble_apps_page.h b/ash/app_list/bubble/app_list_bubble_apps_page.h
index e80e857..4b7672f 100644
--- a/ash/app_list/bubble/app_list_bubble_apps_page.h
+++ b/ash/app_list/bubble/app_list_bubble_apps_page.h
@@ -14,6 +14,7 @@
 
 namespace ash {
 
+class ApplicationDragAndDropHost;
 class AppListA11yAnnouncer;
 class AppListViewDelegate;
 class RecentAppsView;
@@ -28,7 +29,8 @@
  public:
   METADATA_HEADER(AppListBubbleAppsPage);
 
-  explicit AppListBubbleAppsPage(AppListViewDelegate* view_delegate);
+  AppListBubbleAppsPage(AppListViewDelegate* view_delegate,
+                        ApplicationDragAndDropHost* drag_and_drop_host);
   AppListBubbleAppsPage(const AppListBubbleAppsPage&) = delete;
   AppListBubbleAppsPage& operator=(const AppListBubbleAppsPage&) = delete;
   ~AppListBubbleAppsPage() override;
diff --git a/ash/app_list/bubble/app_list_bubble_view.cc b/ash/app_list/bubble/app_list_bubble_view.cc
index b5e9e5e..ed9db755 100644
--- a/ash/app_list/bubble/app_list_bubble_view.cc
+++ b/ash/app_list/bubble/app_list_bubble_view.cc
@@ -15,6 +15,7 @@
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shelf/shelf.h"
+#include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
@@ -130,8 +131,13 @@
   search_box_view_->set_show_close_button_when_active(false);
   search_box_view_->Init();
 
-  apps_page_ =
-      AddChildView(std::make_unique<AppListBubbleAppsPage>(view_delegate));
+  // NOTE: Passing drag and drop host from a specific shelf instance assumes
+  // that the `apps_page_` will not get reused for showing the app list in
+  // another root window.
+  apps_page_ = AddChildView(std::make_unique<AppListBubbleAppsPage>(
+      view_delegate, Shelf::ForWindow(root_window)
+                         ->shelf_widget()
+                         ->GetDragAndDropHostForAppList()));
 
   search_page_ = AddChildView(std::make_unique<AppListBubbleSearchPage>(
       view_delegate, search_box_view_));
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index 684945c..36f708b 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -3002,6 +3002,156 @@
   EndDrag(apps_grid_view_, false /*cancel*/);
 }
 
+TEST_P(AppsGridViewCardifiedStateTest, BackgroundCardBounds) {
+  model_->PopulateApps(30);
+
+  gfx::NativeView parent = GetContext();
+  parent->SetBounds(gfx::Rect(gfx::Point(0, 0), gfx::Size(1024, 768)));
+  app_list_view_->OnParentWindowBoundsChanged();
+  apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
+
+  // Enter cardified state.
+  const gfx::Point from = GetItemRectOnCurrentPageAt(0, 0).CenterPoint();
+  InitiateDrag(AppsGridView::MOUSE, from, apps_grid_view_);
+  ASSERT_TRUE(apps_grid_view_->cardified_state_for_testing());
+  ASSERT_EQ(3, apps_grid_view_->BackgroundCardCountForTesting());
+
+  // Verify that all items in the current page fit within the background card.
+  gfx::Rect background_card_bounds =
+      apps_grid_view_->GetBackgroundCardBoundsForTesting(0);
+  gfx::Rect clip_rect = apps_grid_view_->layer()->clip_rect();
+  gfx::Rect first_item_bounds = GetItemRectOnCurrentPageAt(0, 0);
+
+  EXPECT_TRUE(background_card_bounds.Contains(first_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << first_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(first_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << first_item_bounds.ToString();
+
+  gfx::Rect last_item_bounds = GetItemRectOnCurrentPageAt(3, 4);
+  EXPECT_TRUE(background_card_bounds.Contains(last_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << last_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(last_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << last_item_bounds.ToString();
+
+  // Simulate rotation by updating the bounds of the widget in which the app
+  // list was shown.
+  parent->SetBounds(gfx::Rect(gfx::Point(0, 0), gfx::Size(768, 1024)));
+  app_list_view_->OnParentWindowBoundsChanged();
+  apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
+
+  ASSERT_TRUE(apps_grid_view_->cardified_state_for_testing());
+  ASSERT_EQ(3, apps_grid_view_->BackgroundCardCountForTesting());
+
+  // Verify that all items in the current page fit within the background card.
+  background_card_bounds =
+      apps_grid_view_->GetBackgroundCardBoundsForTesting(0);
+  clip_rect = apps_grid_view_->layer()->clip_rect();
+  first_item_bounds = GetItemRectOnCurrentPageAt(0, 0);
+
+  EXPECT_TRUE(background_card_bounds.Contains(first_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << first_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(first_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << first_item_bounds.ToString();
+
+  last_item_bounds = GetItemRectOnCurrentPageAt(4, 3);
+  EXPECT_TRUE(background_card_bounds.Contains(last_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << last_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(last_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << last_item_bounds.ToString();
+
+  EndDrag(apps_grid_view_, false /*cancel*/);
+  EXPECT_EQ(gfx::Rect(), apps_grid_view_->layer()->clip_rect());
+  EXPECT_FALSE(apps_grid_view_->cardified_state_for_testing());
+  EXPECT_EQ(0, apps_grid_view_->BackgroundCardCountForTesting());
+}
+
+TEST_P(AppsGridViewCardifiedStateTest, BackgroundCardBoundsOnSecondPage) {
+  model_->PopulateApps(30);
+
+  gfx::NativeView parent = GetContext();
+  parent->SetBounds(gfx::Rect(gfx::Point(0, 0), gfx::Size(1024, 768)));
+  app_list_view_->OnParentWindowBoundsChanged();
+  apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
+
+  // Enter cardified state, and drag the item to the second apps grid page.
+  const gfx::Point from = GetItemRectOnCurrentPageAt(0, 0).CenterPoint();
+  InitiateDrag(AppsGridView::MOUSE, from, apps_grid_view_);
+  const gfx::Point to_in_next_page =
+      test_api_->GetItemTileRectAtVisualIndex(1, 0).CenterPoint();
+  // Drag the first item to the next page to create another page.
+  UpdateDragToNeighborPage(true /* next_page */, to_in_next_page);
+
+  // Trigger cardified state again.
+  InitiateDrag(AppsGridView::MOUSE, from, apps_grid_view_);
+
+  ASSERT_TRUE(apps_grid_view_->cardified_state_for_testing());
+  ASSERT_EQ(3, apps_grid_view_->BackgroundCardCountForTesting());
+
+  // Verify that all items in the current page fit within the background card.
+  gfx::Rect background_card_bounds =
+      apps_grid_view_->GetBackgroundCardBoundsForTesting(1);
+  gfx::Rect clip_rect = apps_grid_view_->layer()->clip_rect();
+  gfx::Rect first_item_bounds = GetItemRectOnCurrentPageAt(0, 0);
+
+  EXPECT_TRUE(background_card_bounds.Contains(first_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << first_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(first_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << first_item_bounds.ToString();
+
+  gfx::Rect last_item_bounds = GetItemRectOnCurrentPageAt(3, 4);
+  EXPECT_TRUE(background_card_bounds.Contains(last_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << last_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(last_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << last_item_bounds.ToString();
+
+  // Simulate rotation by updating the bounds of the widget in which the app
+  // list was shown.
+  parent->SetBounds(gfx::Rect(gfx::Point(0, 0), gfx::Size(768, 1024)));
+  app_list_view_->OnParentWindowBoundsChanged();
+  apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
+
+  ASSERT_TRUE(apps_grid_view_->cardified_state_for_testing());
+  ASSERT_EQ(3, apps_grid_view_->BackgroundCardCountForTesting());
+
+  // Verify that all items in the current page fit within the background card.
+  background_card_bounds =
+      apps_grid_view_->GetBackgroundCardBoundsForTesting(1);
+  clip_rect = apps_grid_view_->layer()->clip_rect();
+  first_item_bounds = GetItemRectOnCurrentPageAt(0, 0);
+
+  EXPECT_TRUE(background_card_bounds.Contains(first_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << first_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(first_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << first_item_bounds.ToString();
+
+  last_item_bounds = GetItemRectOnCurrentPageAt(4, 3);
+  EXPECT_TRUE(background_card_bounds.Contains(last_item_bounds))
+      << " background card bounds " << background_card_bounds.ToString()
+      << " item bounds " << last_item_bounds.ToString();
+  EXPECT_TRUE(clip_rect.Contains(last_item_bounds))
+      << " clip rect " << clip_rect.ToString() << " item bounds "
+      << last_item_bounds.ToString();
+
+  EndDrag(apps_grid_view_, false /*cancel*/);
+  EXPECT_EQ(gfx::Rect(), apps_grid_view_->layer()->clip_rect());
+  EXPECT_FALSE(apps_grid_view_->cardified_state_for_testing());
+  EXPECT_EQ(0, apps_grid_view_->BackgroundCardCountForTesting());
+}
+
 TEST_P(AppsGridViewCardifiedStateTest,
        PeekingCardOnLastPageAfterCreatingNewPage) {
   // Create only one page with two apps.
diff --git a/ash/app_list/views/paged_apps_grid_view.cc b/ash/app_list/views/paged_apps_grid_view.cc
index 772c9ee..bf833d3f 100644
--- a/ash/app_list/views/paged_apps_grid_view.cc
+++ b/ash/app_list/views/paged_apps_grid_view.cc
@@ -468,11 +468,15 @@
   }
   if (cardified_state_) {
     DCHECK(!background_cards_.empty());
-    MaybeCreateGradientMask();
     // Make sure that the background cards render behind everything
     // else in the items container.
-    for (auto& background_card : background_cards_)
-      items_container()->layer()->StackAtBottom(background_card.get());
+    for (size_t i = 0; i < background_cards_.size(); ++i) {
+      ui::Layer* const background_card = background_cards_[i].get();
+      background_card->SetBounds(BackgroundCardBounds(i));
+      items_container()->layer()->StackAtBottom(background_card);
+    }
+    MaskContainerToBackgroundBounds();
+    MaybeCreateGradientMask();
   }
   views::ViewModelUtils::SetViewBoundsToIdealBounds(pulsing_blocks_model());
 }
@@ -744,6 +748,16 @@
   return true;
 }
 
+gfx::Rect PagedAppsGridView::GetBackgroundCardBoundsForTesting(
+    size_t card_index) {
+  DCHECK_LT(card_index, background_cards_.size());
+  gfx::Rect bounds_in_items_container = background_cards_[card_index]->bounds();
+  gfx::Point origin_in_apps_grid = bounds_in_items_container.origin();
+  views::View::ConvertPointToTarget(items_container(), this,
+                                    &origin_in_apps_grid);
+  return gfx::Rect(origin_in_apps_grid, bounds_in_items_container.size());
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // private:
 
diff --git a/ash/app_list/views/paged_apps_grid_view.h b/ash/app_list/views/paged_apps_grid_view.h
index 531183a..9d9b2705 100644
--- a/ash/app_list/views/paged_apps_grid_view.h
+++ b/ash/app_list/views/paged_apps_grid_view.h
@@ -100,6 +100,9 @@
   bool FirePageFlipTimerForTest();
   bool cardified_state_for_testing() const { return cardified_state_; }
   int BackgroundCardCountForTesting() const { return background_cards_.size(); }
+  // Returns bounds within the apps grid view for the background card layer
+  // with provided card index.
+  gfx::Rect GetBackgroundCardBoundsForTesting(size_t card_index);
   void set_page_flip_delay_for_testing(base::TimeDelta page_flip_delay) {
     page_flip_delay_ = page_flip_delay;
   }
diff --git a/ash/clipboard/clipboard_history_menu_model_adapter.cc b/ash/clipboard/clipboard_history_menu_model_adapter.cc
index cb21bb6..605caa9b 100644
--- a/ash/clipboard/clipboard_history_menu_model_adapter.cc
+++ b/ash/clipboard/clipboard_history_menu_model_adapter.cc
@@ -107,7 +107,7 @@
                       views::MenuRunner::FIXED_ANCHOR);
   menu_runner_->RunMenuAt(
       /*widget_owner=*/nullptr, /*menu_button_controller=*/nullptr, anchor_rect,
-      views::MenuAnchorPosition::kBubbleBelow, source_type);
+      views::MenuAnchorPosition::kBubbleBottomRight, source_type);
 }
 
 bool ClipboardHistoryMenuModelAdapter::IsRunning() const {
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index c471a1b..e77b8b3 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -726,7 +726,7 @@
 // also making the Nearby Connections WebRTC defaults longer.
 const base::Feature kNearbyKeepAliveFix{"NearbyKeepAliveFix",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
-                                        
+
 // Controls whether new Lockscreen reauth layout is shown or not.
 const base::Feature kNewLockScreenReauthLayout{
     "NewLockScreenReauthLayout", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -997,7 +997,7 @@
 
 // Enables battery indicator for styluses in the palette tray
 const base::Feature kStylusBatteryStatus{"StylusBatteryStatus",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
+                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables or disables using the system input engine for physical typing in
 // languages based on latin script.
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 786593c91d..b75e8a60 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -158,6 +158,8 @@
     "keyboard/keyboard_switches.cc",
     "keyboard/keyboard_switches.h",
     "keyboard/keyboard_types.h",
+    "keyboard_shortcut_item.cc",
+    "keyboard_shortcut_item.h",
     "keyboard_shortcut_viewer.h",
     "kiosk_app_menu.cc",
     "kiosk_app_menu.h",
diff --git a/ash/shortcut_viewer/keyboard_shortcut_item.cc b/ash/public/cpp/keyboard_shortcut_item.cc
similarity index 88%
rename from ash/shortcut_viewer/keyboard_shortcut_item.cc
rename to ash/public/cpp/keyboard_shortcut_item.cc
index 1c3c8a7c..1bdc369 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_item.cc
+++ b/ash/public/cpp/keyboard_shortcut_item.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/shortcut_viewer/keyboard_shortcut_item.h"
+#include "ash/public/cpp/keyboard_shortcut_item.h"
 
 #include <tuple>
 
 #include "base/check.h"
 
-namespace keyboard_shortcut_viewer {
+namespace ash {
 
 bool AcceleratorId::operator<(const AcceleratorId& other) const {
   return std::tie(keycode, modifiers) <
@@ -34,4 +34,4 @@
 
 KeyboardShortcutItem::~KeyboardShortcutItem() = default;
 
-}  // namespace keyboard_shortcut_viewer
+}  // namespace ash
diff --git a/ash/shortcut_viewer/keyboard_shortcut_item.h b/ash/public/cpp/keyboard_shortcut_item.h
similarity index 92%
rename from ash/shortcut_viewer/keyboard_shortcut_item.h
rename to ash/public/cpp/keyboard_shortcut_item.h
index ad76e6b4..dcfd5b1a 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_item.h
+++ b/ash/public/cpp/keyboard_shortcut_item.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_SHORTCUT_VIEWER_KEYBOARD_SHORTCUT_ITEM_H_
-#define ASH_SHORTCUT_VIEWER_KEYBOARD_SHORTCUT_ITEM_H_
+#ifndef ASH_PUBLIC_CPP_KEYBOARD_SHORTCUT_ITEM_H_
+#define ASH_PUBLIC_CPP_KEYBOARD_SHORTCUT_ITEM_H_
 
 #include <vector>
 
-#include "ash/shortcut_viewer/ksv_export.h"
+#include "ash/public/cpp/ash_public_export.h"
 #include "base/macros.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
-namespace keyboard_shortcut_viewer {
+namespace ash {
 
 // The categories the shortcut belongs to. Used to group shortcuts in the
 // viewer. This order is significant as it determines the order in which the
@@ -32,7 +32,7 @@
 // we cannot depend on them here. The key + modifiers are also used to populate
 // the values of |shortcut_key_codes| field in KeyboardShortcutItem, in order to
 // show the key and modifiers in the viewer with different styles.
-struct KSV_EXPORT AcceleratorId {
+struct ASH_PUBLIC_EXPORT AcceleratorId {
   bool operator<(const AcceleratorId& other) const;
 
   ui::KeyboardCode keycode = ui::VKEY_UNKNOWN;
@@ -53,7 +53,7 @@
 // (key) will be replaced by text "left arrow" so that users can search by
 // "left" and/or "arrow". But the UI representation of the key is an icon of
 // "left arrow".
-struct KSV_EXPORT KeyboardShortcutItem {
+struct ASH_PUBLIC_EXPORT KeyboardShortcutItem {
   KeyboardShortcutItem(
       const std::vector<ShortcutCategory>& categories,
       int description_message_id,
@@ -105,6 +105,6 @@
   std::vector<ui::KeyboardCode> shortcut_key_codes;
 };
 
-}  // namespace keyboard_shortcut_viewer
+}  // namespace ash
 
-#endif  // ASH_SHORTCUT_VIEWER_KEYBOARD_SHORTCUT_ITEM_H_
+#endif  // ASH_PUBLIC_CPP_KEYBOARD_SHORTCUT_ITEM_H_
diff --git a/ash/quick_pair/common/BUILD.gn b/ash/quick_pair/common/BUILD.gn
index 0ba32d2..58767e2 100644
--- a/ash/quick_pair/common/BUILD.gn
+++ b/ash/quick_pair/common/BUILD.gn
@@ -13,6 +13,7 @@
   defines = [ "IS_QUICK_PAIR_COMMON_IMPL" ]
 
   sources = [
+    "constants.h",
     "device.cc",
     "device.h",
     "fast_pair/fast_pair_decoder.cc",
diff --git a/ash/quick_pair/common/constants.h b/ash/quick_pair/common/constants.h
new file mode 100644
index 0000000..9a84eeb
--- /dev/null
+++ b/ash/quick_pair/common/constants.h
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_QUICK_PAIR_COMMON_CONSTANTS_H_
+#define ASH_QUICK_PAIR_COMMON_CONSTANTS_H_
+
+#include "base/component_export.h"
+
+namespace ash {
+namespace quick_pair {
+
+COMPONENT_EXPORT(QUICK_PAIR_COMMON)
+const device::BluetoothUUID kFastPairBluetoothUuid("0xFE2C");
+
+}  // namespace quick_pair
+}  // namespace ash
+
+#endif  // ASH_QUICK_PAIR_COMMON_CONSTANTS_H_
diff --git a/ash/quick_pair/common/device.h b/ash/quick_pair/common/device.h
index ea6ca83..619d415 100644
--- a/ash/quick_pair/common/device.h
+++ b/ash/quick_pair/common/device.h
@@ -18,7 +18,7 @@
 // fetch objects which contain more information. E.g. A Fast Pair component
 // can use |metadata_id| to query the Service to receive a full metadata
 // object.
-struct Device {
+struct COMPONENT_EXPORT(QUICK_PAIR_COMMON) Device {
   Device(std::string metadata_id, std::string address, Protocol protocol);
   Device(const Device&) = delete;
   Device(Device&&) = default;
diff --git a/ash/quick_pair/keyed_service/BUILD.gn b/ash/quick_pair/keyed_service/BUILD.gn
index df4db0c..ad7b676 100644
--- a/ash/quick_pair/keyed_service/BUILD.gn
+++ b/ash/quick_pair/keyed_service/BUILD.gn
@@ -19,6 +19,7 @@
     "//ash/quick_pair/common",
     "//ash/quick_pair/feature_status_tracker",
     "//ash/quick_pair/scanning",
+    "//ash/quick_pair/ui",
     "//base",
     "//components/keyed_service/core",
   ]
@@ -31,8 +32,10 @@
 
   deps = [
     ":keyed_service",
+    "//ash/quick_pair/common",
     "//ash/quick_pair/feature_status_tracker:test_support",
     "//ash/quick_pair/scanning:test_support",
+    "//ash/quick_pair/ui:test_support",
     "//base/test:test_support",
     "//testing/gtest",
   ]
diff --git a/ash/quick_pair/keyed_service/quick_pair_mediator.cc b/ash/quick_pair/keyed_service/quick_pair_mediator.cc
index 782ed20..1e17717 100644
--- a/ash/quick_pair/keyed_service/quick_pair_mediator.cc
+++ b/ash/quick_pair/keyed_service/quick_pair_mediator.cc
@@ -11,6 +11,8 @@
 #include "ash/quick_pair/feature_status_tracker/quick_pair_feature_status_tracker.h"
 #include "ash/quick_pair/feature_status_tracker/quick_pair_feature_status_tracker_impl.h"
 #include "ash/quick_pair/scanning/scanner_broker_impl.h"
+#include "ash/quick_pair/ui/actions.h"
+#include "ash/quick_pair/ui/ui_broker_impl.h"
 
 namespace ash {
 namespace quick_pair {
@@ -28,7 +30,7 @@
 
   return std::make_unique<Mediator>(
       std::make_unique<FeatureStatusTrackerImpl>(),
-      std::make_unique<ScannerBrokerImpl>());
+      std::make_unique<ScannerBrokerImpl>(), std::make_unique<UIBrokerImpl>());
 }
 
 // static
@@ -37,11 +39,14 @@
 }
 
 Mediator::Mediator(std::unique_ptr<FeatureStatusTracker> feature_status_tracker,
-                   std::unique_ptr<ScannerBroker> scanner_broker)
+                   std::unique_ptr<ScannerBroker> scanner_broker,
+                   std::unique_ptr<UIBroker> ui_broker)
     : feature_status_tracker_(std::move(feature_status_tracker)),
-      scanner_broker_(std::move(scanner_broker)) {
+      scanner_broker_(std::move(scanner_broker)),
+      ui_broker_(std::move(ui_broker)) {
   feature_status_tracker_observation_.Observe(feature_status_tracker_.get());
   scanner_broker_observation_.Observe(scanner_broker_.get());
+  ui_broker_observation_.Observe(ui_broker_.get());
 
   SetFastPairState(feature_status_tracker_->IsFastPairEnabled());
 }
@@ -54,6 +59,7 @@
 
 void Mediator::OnDeviceFound(const Device& device) {
   QP_LOG(INFO) << __func__ << ": " << device;
+  ui_broker_->ShowDiscovery(device);
 }
 
 void Mediator::OnDeviceLost(const Device& device) {
@@ -69,5 +75,33 @@
     scanner_broker_->StopScanning(Protocol::kFastPair);
 }
 
+void Mediator::OnDiscoveryAction(const Device& device, DiscoveryAction action) {
+  QP_LOG(INFO) << __func__ << ": Device=" << device << ", Action=" << action;
+
+  switch (action) {
+    case DiscoveryAction::kPairToDevice:
+      ui_broker_->ShowPairing(device);
+      break;
+    case DiscoveryAction::kDismissedByUser:
+    case DiscoveryAction::kDismissed:
+      break;
+  }
+}
+
+void Mediator::OnPairingFailureAction(const Device& device,
+                                      PairingFailedAction action) {
+  QP_LOG(INFO) << __func__ << ": Device=" << device << ", Action=" << action;
+}
+
+void Mediator::OnCompanionAppAction(const Device& device,
+                                    CompanionAppAction action) {
+  QP_LOG(INFO) << __func__ << ": Device=" << device << ", Action=" << action;
+}
+
+void Mediator::OnAssociateAccountAction(const Device& device,
+                                        AssociateAccountAction action) {
+  QP_LOG(INFO) << __func__ << ": Device=" << device << ", Action=" << action;
+}
+
 }  // namespace quick_pair
 }  // namespace ash
diff --git a/ash/quick_pair/keyed_service/quick_pair_mediator.h b/ash/quick_pair/keyed_service/quick_pair_mediator.h
index 20bb08e..60256822 100644
--- a/ash/quick_pair/keyed_service/quick_pair_mediator.h
+++ b/ash/quick_pair/keyed_service/quick_pair_mediator.h
@@ -10,6 +10,7 @@
 #include "ash/quick_pair/common/device.h"
 #include "ash/quick_pair/feature_status_tracker/quick_pair_feature_status_tracker.h"
 #include "ash/quick_pair/scanning/scanner_broker.h"
+#include "ash/quick_pair/ui/ui_broker.h"
 #include "base/scoped_observation.h"
 
 namespace ash {
@@ -18,7 +19,8 @@
 // Implements the Mediator design pattern for the components in the Quick Pair
 // system, e.g. the UI Broker, Scanning Broker and Pairing Broker.
 class Mediator : public FeatureStatusTracker::Observer,
-                 public ScannerBroker::Observer {
+                 public ScannerBroker::Observer,
+                 public UIBroker::Observer {
  public:
   class Factory {
    public:
@@ -31,7 +33,8 @@
   };
 
   Mediator(std::unique_ptr<FeatureStatusTracker> feature_status_tracker,
-           std::unique_ptr<ScannerBroker> scanner_broker);
+           std::unique_ptr<ScannerBroker> scanner_broker,
+           std::unique_ptr<UIBroker> ui_broker);
   Mediator(const Mediator&) = delete;
   Mediator& operator=(const Mediator&) = delete;
   ~Mediator() final;
@@ -43,16 +46,28 @@
   void OnDeviceFound(const Device& device) override;
   void OnDeviceLost(const Device& device) override;
 
+  // UIBroker::Observer
+  void OnDiscoveryAction(const Device& device, DiscoveryAction action) override;
+  void OnPairingFailureAction(const Device& device,
+                              PairingFailedAction action) override;
+  void OnCompanionAppAction(const Device& device,
+                            CompanionAppAction action) override;
+  void OnAssociateAccountAction(const Device& device,
+                                AssociateAccountAction action) override;
+
  private:
   void SetFastPairState(bool is_enabled);
 
   std::unique_ptr<FeatureStatusTracker> feature_status_tracker_;
   std::unique_ptr<ScannerBroker> scanner_broker_;
+  std::unique_ptr<UIBroker> ui_broker_;
 
   base::ScopedObservation<FeatureStatusTracker, FeatureStatusTracker::Observer>
       feature_status_tracker_observation_{this};
   base::ScopedObservation<ScannerBroker, ScannerBroker::Observer>
       scanner_broker_observation_{this};
+  base::ScopedObservation<UIBroker, UIBroker::Observer> ui_broker_observation_{
+      this};
 };
 
 }  // namespace quick_pair
diff --git a/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc b/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc
index 4c426e39..5dc52e5 100644
--- a/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc
+++ b/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc
@@ -6,11 +6,15 @@
 
 #include <memory>
 
+#include "ash/quick_pair/common/device.h"
+#include "ash/quick_pair/common/protocol.h"
 #include "ash/quick_pair/feature_status_tracker/fake_feature_status_tracker.h"
 #include "ash/quick_pair/feature_status_tracker/mock_quick_pair_feature_status_tracker.h"
 #include "ash/quick_pair/feature_status_tracker/quick_pair_feature_status_tracker.h"
 #include "ash/quick_pair/scanning/mock_scanner_broker.h"
 #include "ash/quick_pair/scanning/scanner_broker.h"
+#include "ash/quick_pair/ui/mock_ui_broker.h"
+#include "ash/quick_pair/ui/ui_broker.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -29,13 +33,18 @@
     mock_scanner_broker_ =
         static_cast<MockScannerBroker*>(scanner_broker.get());
 
-    mediator_ = std::make_unique<Mediator>(std::move(tracker),
-                                           std::move(scanner_broker));
+    std::unique_ptr<UIBroker> ui_broker = std::make_unique<MockUIBroker>();
+    mock_ui_broker_ = static_cast<MockUIBroker*>(ui_broker.get());
+
+    mediator_ = std::make_unique<Mediator>(
+        std::move(tracker), std::move(scanner_broker), std::move(ui_broker));
   }
 
  protected:
+  Device device_{"test_metadata_id", "test_address", Protocol::kFastPair};
   FakeFeatureStatusTracker* feature_status_tracker_;
   MockScannerBroker* mock_scanner_broker_;
+  MockUIBroker* mock_ui_broker_;
   std::unique_ptr<Mediator> mediator_;
 };
 
@@ -50,5 +59,18 @@
   feature_status_tracker_->SetIsFastPairEnabled(false);
 }
 
+TEST_F(MediatorTest, InvokesShowDiscoveryWhenDeviceFound) {
+  feature_status_tracker_->SetIsFastPairEnabled(true);
+  EXPECT_CALL(*mock_ui_broker_, ShowDiscovery);
+  mock_scanner_broker_->NotifyDeviceFound(device_);
+}
+
+TEST_F(MediatorTest, InvokesShowPairingOnAppropriateAction) {
+  feature_status_tracker_->SetIsFastPairEnabled(true);
+  EXPECT_CALL(*mock_ui_broker_, ShowPairing);
+  mock_ui_broker_->NotifyDiscoveryAction(device_,
+                                         DiscoveryAction::kPairToDevice);
+}
+
 }  // namespace quick_pair
 }  // namespace ash
diff --git a/ash/quick_pair/repository/BUILD.gn b/ash/quick_pair/repository/BUILD.gn
index de88f01..4a68910 100644
--- a/ash/quick_pair/repository/BUILD.gn
+++ b/ash/quick_pair/repository/BUILD.gn
@@ -9,8 +9,8 @@
 
 source_set("repository") {
   sources = [
-    "fast_pair_device_metadata_service.cc",
-    "fast_pair_device_metadata_service.h",
+    "fast_pair_repository.cc",
+    "fast_pair_repository.h",
   ]
 
   deps = [
diff --git a/ash/quick_pair/repository/fast_pair_device_metadata_service.cc b/ash/quick_pair/repository/fast_pair_repository.cc
similarity index 64%
rename from ash/quick_pair/repository/fast_pair_device_metadata_service.cc
rename to ash/quick_pair/repository/fast_pair_repository.cc
index 0df7fe3..034fc90 100644
--- a/ash/quick_pair/repository/fast_pair_device_metadata_service.cc
+++ b/ash/quick_pair/repository/fast_pair_repository.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/quick_pair/repository/fast_pair_device_metadata_service.h"
+#include "ash/quick_pair/repository/fast_pair_repository.h"
 
 #include "ash/quick_pair/common/logging.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -10,10 +10,10 @@
 namespace ash {
 namespace quick_pair {
 
-FastPairDeviceMetadataService::FastPairDeviceMetadataService() = default;
-FastPairDeviceMetadataService::~FastPairDeviceMetadataService() = default;
+FastPairRepository::FastPairRepository() = default;
+FastPairRepository::~FastPairRepository() = default;
 
-void FastPairDeviceMetadataService::GetDeviceMetadata(
+void FastPairRepository::GetDeviceMetadata(
     const std::string& hex_model_id,
     base::OnceCallback<void(absl::optional<nearby::fastpair::Device>)>
         callback) {
@@ -21,14 +21,14 @@
   std::move(callback).Run(absl::nullopt);
 }
 
-void FastPairDeviceMetadataService::IsValidModelId(
+void FastPairRepository::IsValidModelId(
     const std::string& hex_model_id,
     base::OnceCallback<void(bool)> callback) {
   QP_LOG(INFO) << __func__;
   std::move(callback).Run(false);
 }
 
-void FastPairDeviceMetadataService::GetAssociatedAccountKey(
+void FastPairRepository::GetAssociatedAccountKey(
     const std::string& address,
     const std::string& account_key_filter,
     base::OnceCallback<void(absl::optional<std::string>)> callback) {
@@ -36,13 +36,12 @@
   std::move(callback).Run(absl::nullopt);
 }
 
-void FastPairDeviceMetadataService::AssociateAccountKey(
-    const Device& device,
-    const std::string& account_key) {
+void FastPairRepository::AssociateAccountKey(const Device& device,
+                                             const std::string& account_key) {
   QP_LOG(INFO) << __func__;
 }
 
-void FastPairDeviceMetadataService::DeleteAssociatedDevice(
+void FastPairRepository::DeleteAssociatedDevice(
     const device::BluetoothDevice* device) {
   QP_LOG(INFO) << __func__;
 }
diff --git a/ash/quick_pair/repository/fast_pair_device_metadata_service.h b/ash/quick_pair/repository/fast_pair_repository.h
similarity index 78%
rename from ash/quick_pair/repository/fast_pair_device_metadata_service.h
rename to ash/quick_pair/repository/fast_pair_repository.h
index b1c079f..21dcc3b 100644
--- a/ash/quick_pair/repository/fast_pair_device_metadata_service.h
+++ b/ash/quick_pair/repository/fast_pair_repository.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 ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_DEVICE_METADATA_SERVICE_H_
-#define ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_DEVICE_METADATA_SERVICE_H_
+#ifndef ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_REPOSITORY_H_
+#define ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_REPOSITORY_H_
 
 #include "ash/quick_pair/common/device.h"
 #include "ash/quick_pair/proto/fastpair.pb.h"
@@ -19,13 +19,12 @@
 
 // The entry point for the Repository component in the Quick Pair system,
 // responsible for connecting to back-end services.
-class FastPairDeviceMetadataService {
+class FastPairRepository {
  public:
-  FastPairDeviceMetadataService();
-  FastPairDeviceMetadataService(const FastPairDeviceMetadataService&) = delete;
-  FastPairDeviceMetadataService& operator=(
-      const FastPairDeviceMetadataService&) = delete;
-  virtual ~FastPairDeviceMetadataService();
+  FastPairRepository();
+  FastPairRepository(const FastPairRepository&) = delete;
+  FastPairRepository& operator=(const FastPairRepository&) = delete;
+  virtual ~FastPairRepository();
 
   // Returns the DeviceMetadata for a given |hex_model_id| to the provided
   // |callback|, if available.
@@ -59,4 +58,4 @@
 }  // namespace quick_pair
 }  // namespace ash
 
-#endif  // ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_DEVICE_METADATA_SERVICE_H_
+#endif  // ASH_QUICK_PAIR_REPOSITORY_FAST_PAIR_REPOSITORY_H_
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.cc b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.cc
index 3c0e135b..453e2c5 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.cc
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.cc
@@ -4,22 +4,61 @@
 
 #include "ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.h"
 
+#include "ash/quick_pair/common/constants.h"
+#include "ash/quick_pair/common/logging.h"
+#include "base/containers/contains.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
 
-using device::BluetoothAdapter;
-using device::BluetoothAdapterFactory;
-using device::BluetoothDevice;
+namespace {
+
+constexpr int16_t kFilterDeviceFoundThreshold = -80;
+constexpr uint16_t kFilterDeviceFoundTimeout = 1;
+constexpr int16_t kFilterDeviceLostThreshold = -100;
+constexpr uint16_t kFilterDeviceLostTimeout = 5;
+constexpr uint8_t kFilterPatternStartPosition = 0;
+const std::vector<uint8_t> kFastPairFilterPatternValue = {0x2c, 0xfe};
+
+std::ostream& operator<<(
+    std::ostream& out,
+    const device::BluetoothLowEnergyScanSession::ErrorCode& error_code) {
+  switch (error_code) {
+    case device::BluetoothLowEnergyScanSession::ErrorCode::kFailed:
+      out << "[Failed]";
+      break;
+  }
+  return out;
+}
+}  // namespace
 
 namespace ash {
 namespace quick_pair {
 
 FastPairScannerImpl::FastPairScannerImpl() {
-  BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce(
+  device::BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce(
       &FastPairScannerImpl::OnGetAdapter, weak_ptr_factory_.GetWeakPtr()));
 }
 
 FastPairScannerImpl::~FastPairScannerImpl() = default;
 
+void FastPairScannerImpl::OnGetAdapter(
+    scoped_refptr<device::BluetoothAdapter> adapter) {
+  adapter_ = adapter;
+  adapter_observation_.Observe(adapter_.get());
+
+  auto filter = std::make_unique<device::BluetoothLowEnergyScanFilter>(
+      kFilterDeviceFoundThreshold, kFilterDeviceFoundTimeout,
+      kFilterDeviceLostThreshold, kFilterDeviceLostTimeout);
+
+  filter->AddPattern(
+      kFilterPatternStartPosition,
+      device::BluetoothLowEnergyScanFilter::AdvertisementDataType::kServiceData,
+      kFastPairFilterPatternValue);
+
+  background_scan_session_ = adapter_->StartLowEnergyScanSession(
+      std::move(filter), weak_ptr_factory_.GetWeakPtr());
+}
+
 void FastPairScannerImpl::AddObserver(FastPairScanner::Observer* observer) {
   observers_.AddObserver(observer);
 }
@@ -28,23 +67,73 @@
   observers_.RemoveObserver(observer);
 }
 
-void FastPairScannerImpl::DeviceAdded(BluetoothAdapter* adapter,
-                                      BluetoothDevice* device) {
+void FastPairScannerImpl::OnSessionStarted(
+    device::BluetoothLowEnergyScanSession* scan_session,
+    absl::optional<device::BluetoothLowEnergyScanSession::ErrorCode>
+        error_code) {
+  if (error_code) {
+    QP_LOG(ERROR) << "Bluetooth Low Energy Scan Session failed to start with "
+                     "the following error: "
+                  << error_code.value();
+    return;
+  }
+}
+
+void FastPairScannerImpl::OnSessionInvalidated(
+    device::BluetoothLowEnergyScanSession* scan_session) {
+  // TODO(crbug.com/1227519) Handle Session Invalidation by adding exponential
+  // retry to restart the scanner.
+  background_scan_session_.reset();
+  device_address_advertisement_data_map_.clear();
+}
+
+void FastPairScannerImpl::OnDeviceFound(
+    device::BluetoothLowEnergyScanSession* scan_session,
+    device::BluetoothDevice* device) {
+  const std::vector<uint8_t>* service_data =
+      device->GetServiceDataForUUID(kFastPairBluetoothUuid);
+  if (!service_data) {
+    QP_LOG(WARNING) << "No Fast Pair service data found on device";
+    return;
+  }
+
+  device_address_advertisement_data_map_[device->GetAddress()].insert(
+      *service_data);
+  NotifyDeviceFound(device);
+}
+
+void FastPairScannerImpl::DeviceChanged(device::BluetoothAdapter* adapter,
+                                        device::BluetoothDevice* device) {
+  std::string device_address = device->GetAddress();
+  const std::vector<uint8_t>* service_data =
+      device->GetServiceDataForUUID(kFastPairBluetoothUuid);
+
+  // If the advertisement data we have received does not pertain to a device
+  // we have seen already from the scanner, or if the advertisement data for
+  // a device we have already seen is not new, then early return and do not
+  // notify observers or add data to the device address advertisement data map.
+  if (!base::Contains(device_address_advertisement_data_map_, device_address) ||
+      base::Contains(device_address_advertisement_data_map_[device_address],
+                     *service_data)) {
+    return;
+  }
+
+  device_address_advertisement_data_map_[device_address].insert(*service_data);
+  NotifyDeviceFound(device);
+}
+
+void FastPairScannerImpl::NotifyDeviceFound(device::BluetoothDevice* device) {
   for (auto& observer : observers_)
     observer.OnDeviceFound(device);
 }
 
-void FastPairScannerImpl::DeviceRemoved(BluetoothAdapter* adapter,
-                                        BluetoothDevice* device) {
+void FastPairScannerImpl::OnDeviceLost(
+    device::BluetoothLowEnergyScanSession* scan_session,
+    device::BluetoothDevice* device) {
+  device_address_advertisement_data_map_.erase(device->GetAddress());
   for (auto& observer : observers_)
     observer.OnDeviceLost(device);
 }
 
-void FastPairScannerImpl::OnGetAdapter(
-    scoped_refptr<device::BluetoothAdapter> adapter) {
-  adapter_ = adapter;
-  adapter_observation_.Observe(adapter_.get());
-}
-
 }  // namespace quick_pair
 }  // namespace ash
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.h b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.h
index ae0888d8..9d43f23 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.h
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_impl.h
@@ -5,20 +5,27 @@
 #ifndef ASH_QUICK_PAIR_SCANNING_FAST_PAIR_FAST_PAIR_SCANNER_IMPL_H_
 #define ASH_QUICK_PAIR_SCANNING_FAST_PAIR_FAST_PAIR_SCANNER_IMPL_H_
 
+#include <map>
+#include <set>
+#include <string>
+
 #include "ash/quick_pair/scanning/fast_pair/fast_pair_scanner.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/scoped_observation.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/bluetooth_low_energy_scan_session.h"
 
 namespace ash {
 namespace quick_pair {
 
 // This registers a BluetoothLowEnergyScanner with the Advertisement Monitoring
 // API and exposes the Fast Pair devices found/lost events to its observers.
-class FastPairScannerImpl : public FastPairScanner,
-                            public device::BluetoothAdapter::Observer {
+class FastPairScannerImpl
+    : public FastPairScanner,
+      public device::BluetoothAdapter::Observer,
+      public device::BluetoothLowEnergyScanSession::Delegate {
  public:
   FastPairScannerImpl();
   ~FastPairScannerImpl() override;
@@ -31,15 +38,34 @@
 
  private:
   // device::BluetoothAdapter::Observer
-  void DeviceAdded(device::BluetoothAdapter* adapter,
-                   device::BluetoothDevice* device) override;
-  void DeviceRemoved(device::BluetoothAdapter* adapter,
+  void DeviceChanged(device::BluetoothAdapter* adapter,
                      device::BluetoothDevice* device) override;
 
+  // device::BluetoothLowEnergyScanSession::Delegate
+  void OnDeviceFound(device::BluetoothLowEnergyScanSession* scan_session,
+                     device::BluetoothDevice* device) override;
+  void OnDeviceLost(device::BluetoothLowEnergyScanSession* scan_session,
+                    device::BluetoothDevice* device) override;
+  void OnSessionStarted(
+      device::BluetoothLowEnergyScanSession* scan_session,
+      absl::optional<device::BluetoothLowEnergyScanSession::ErrorCode>
+          error_code) override;
+  void OnSessionInvalidated(
+      device::BluetoothLowEnergyScanSession* scan_session) override;
+
   // Internal method called by BluetoothAdapterFactory to provide the adapter
   // object.
   void OnGetAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
 
+  void NotifyDeviceFound(device::BluetoothDevice* device);
+
+  // Map of a Bluetooth device address to a set of advertisement data we have
+  // seen.
+  std::map<std::string, std::set<std::vector<uint8_t>>>
+      device_address_advertisement_data_map_;
+
+  std::unique_ptr<device::BluetoothLowEnergyScanSession>
+      background_scan_session_;
   scoped_refptr<device::BluetoothAdapter> adapter_;
   base::ObserverList<FastPairScanner::Observer> observers_;
 
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_unittest.cc b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_unittest.cc
index 9cbc566..73268e7 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_unittest.cc
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_scanner_unittest.cc
@@ -24,6 +24,11 @@
       kTestBleDeviceAddress, /*paired=*/true, /*connected=*/true);
 }
 
+}  // namespace
+
+namespace ash {
+namespace quick_pair {
+
 class FakeBluetoothAdapter
     : public testing::NiceMock<device::MockBluetoothAdapter> {
  public:
@@ -46,11 +51,6 @@
   ~FakeBluetoothAdapter() override = default;
 };
 
-}  // namespace
-
-namespace ash {
-namespace quick_pair {
-
 class FastPairScannerObserver : public FastPairScanner::Observer {
  public:
   // FastPairScanner::Observer overrides
@@ -82,6 +82,10 @@
     scanner_ = std::make_unique<FastPairScannerImpl>();
     scanner_observer_ = std::make_unique<FastPairScannerObserver>();
     scanner().AddObserver(scanner_observer_.get());
+
+    // TODO(crbug.com/1227522) Add support for the Bluetooth LE Scanner here
+    // when available, as well as new tests to check for the correct behavior
+    // when a device is found and removed.
   }
 
   void TearDown() override {
@@ -103,23 +107,5 @@
   std::unique_ptr<FastPairScannerObserver> scanner_observer_;
 };
 
-TEST_F(FastPairScannerTest, DeviceAddedNotifiesObservers) {
-  adapter().AddDevice();
-  EXPECT_TRUE(scanner_observer().DoesDeviceListContainTestDevice());
-}
-
-TEST_F(FastPairScannerTest, DeviceRemovedNotifiesObservers) {
-  adapter().AddDevice();
-  EXPECT_TRUE(scanner_observer().DoesDeviceListContainTestDevice());
-  adapter().RemoveDevice();
-  EXPECT_FALSE(scanner_observer().DoesDeviceListContainTestDevice());
-}
-
-TEST_F(FastPairScannerTest, RemovedObserverReceivesNoNewEvents) {
-  scanner().RemoveObserver(&scanner_observer());
-  adapter().AddDevice();
-  EXPECT_FALSE(scanner_observer().DoesDeviceListContainTestDevice());
-}
-
 }  // namespace quick_pair
 }  // namespace ash
diff --git a/ash/quick_pair/ui/actions.h b/ash/quick_pair/ui/actions.h
index 7a72a10..91c6ace 100644
--- a/ash/quick_pair/ui/actions.h
+++ b/ash/quick_pair/ui/actions.h
@@ -6,38 +6,46 @@
 #define ASH_QUICK_PAIR_UI_ACTIONS_H_
 
 #include <ostream>
+#include "base/component_export.h"
 
 namespace ash {
 namespace quick_pair {
 
-enum class DiscoveryAction {
+enum class COMPONENT_EXPORT(QUICK_PAIR_UI) DiscoveryAction {
   kPairToDevice = 0,
   kDismissedByUser = 1,
   kDismissed = 2
 };
 
-enum class AssociateAccountAction {
+enum class COMPONENT_EXPORT(QUICK_PAIR_UI) AssociateAccountAction {
   kAssoicateAccount = 0,
   kDismissedByUser = 1,
   kDismissed = 2
 };
 
-enum class CompanionAppAction {
+enum class COMPONENT_EXPORT(QUICK_PAIR_UI) CompanionAppAction {
   kDownloadAndLaunchApp = 0,
   kLaunchApp = 1,
   kDismissedByUser = 2,
   kDismissed = 3
 };
 
-enum class PairingFailedAction {
+enum class COMPONENT_EXPORT(QUICK_PAIR_UI) PairingFailedAction {
   kNavigateToSettings = 0,
   kDismissedByUser = 1,
   kDismissed = 2
 };
 
+COMPONENT_EXPORT(QUICK_PAIR_UI)
 std::ostream& operator<<(std::ostream& stream, DiscoveryAction protocol);
+
+COMPONENT_EXPORT(QUICK_PAIR_UI)
 std::ostream& operator<<(std::ostream& stream, AssociateAccountAction protocol);
+
+COMPONENT_EXPORT(QUICK_PAIR_UI)
 std::ostream& operator<<(std::ostream& stream, CompanionAppAction protocol);
+
+COMPONENT_EXPORT(QUICK_PAIR_UI)
 std::ostream& operator<<(std::ostream& stream, PairingFailedAction protocol);
 
 }  // namespace quick_pair
diff --git a/ash/quick_pair/ui/ui_broker.h b/ash/quick_pair/ui/ui_broker.h
index 0222d61..b1cec42 100644
--- a/ash/quick_pair/ui/ui_broker.h
+++ b/ash/quick_pair/ui/ui_broker.h
@@ -15,7 +15,7 @@
 // The UIBroker is the entry point for the UI component in the Quick Pair
 // system. It is responsible for brokering the 'show UI' calls to the correct
 // Presenter implementation, and exposing user actions taken on that UI.
-class UIBroker {
+class COMPONENT_EXPORT(QUICK_PAIR_UI) UIBroker {
  public:
   class Observer : public base::CheckedObserver {
    public:
diff --git a/ash/quick_pair/ui/ui_broker_impl.h b/ash/quick_pair/ui/ui_broker_impl.h
index e96c263..a599868 100644
--- a/ash/quick_pair/ui/ui_broker_impl.h
+++ b/ash/quick_pair/ui/ui_broker_impl.h
@@ -17,7 +17,7 @@
 
 class FastPairPresenter;
 
-class UIBrokerImpl : public UIBroker {
+class COMPONENT_EXPORT(QUICK_PAIR_UI) UIBrokerImpl : public UIBroker {
  public:
   UIBrokerImpl();
   UIBrokerImpl(const UIBrokerImpl&) = delete;
diff --git a/ash/shell.cc b/ash/shell.cc
index 0d7e4820..ab7d53e 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -616,10 +616,6 @@
   if (window_modality_controller_)
     window_modality_controller_.reset();
 
-  // We may shutdown while a capture session is active, which is an event
-  // handler that depends on this shell and some of its members. Destroy early.
-  capture_mode_controller_.reset();
-
   RemovePreTargetHandler(shell_tab_handler_.get());
   shell_tab_handler_.reset();
 
@@ -746,6 +742,7 @@
   // Close all widgets (including the shelf) and destroy all window containers.
   CloseAllRootWindowChildWindows();
 
+  capture_mode_controller_.reset();
   tablet_mode_controller_.reset();
   login_screen_controller_.reset();
   system_notification_controller_.reset();
diff --git a/ash/shortcut_viewer/BUILD.gn b/ash/shortcut_viewer/BUILD.gn
index f9b2d57..54d8e6c 100644
--- a/ash/shortcut_viewer/BUILD.gn
+++ b/ash/shortcut_viewer/BUILD.gn
@@ -5,8 +5,6 @@
 # KSV: Keyboard Shortcut Viewer
 source_set("shortcut_viewer") {
   sources = [
-    "keyboard_shortcut_item.cc",
-    "keyboard_shortcut_item.h",
     "keyboard_shortcut_viewer_metadata.cc",
     "keyboard_shortcut_viewer_metadata.h",
     "ksv_export.h",
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index e6ffac1..dd04dda 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -5,7 +5,7 @@
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 
 #include "ash/constants/ash_features.h"
-#include "ash/shortcut_viewer/keyboard_shortcut_item.h"
+#include "ash/public/cpp/keyboard_shortcut_item.h"
 #include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
 #include "base/check.h"
@@ -31,6 +31,8 @@
 
 namespace keyboard_shortcut_viewer {
 
+using ash::ShortcutCategory;
+
 namespace {
 
 // Gets the keyboard codes for modifiers.
@@ -282,8 +284,8 @@
   }
 }
 
-const std::vector<KeyboardShortcutItem>& GetKeyboardShortcutItemList() {
-  static base::NoDestructor<std::vector<KeyboardShortcutItem>> item_list({
+const std::vector<ash::KeyboardShortcutItem>& GetKeyboardShortcutItemList() {
+  static base::NoDestructor<std::vector<ash::KeyboardShortcutItem>> item_list({
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_TOGGLE_DOCKED_MAGNIFIER,
@@ -1541,7 +1543,7 @@
 
     // Include diagnostics shortcuts only when experiment flag is enabled.
     if (base::FeatureList::IsEnabled(chromeos::features::kDiagnosticsApp)) {
-      const KeyboardShortcutItem diagnostics_shortcut = {
+      const ash::KeyboardShortcutItem diagnostics_shortcut = {
           // |categories|
           {ShortcutCategory::kSystemAndDisplay},
           IDS_KSV_DESCRIPTION_OPEN_DIAGNOSTICS,
@@ -1575,7 +1577,7 @@
       if (item.shortcut_key_codes.empty() && !item.accelerator_ids.empty()) {
         // Only use the first |accelerator_id| because the modifiers are the
         // same even if it is a grouped accelerators.
-        const AcceleratorId& accelerator_id = item.accelerator_ids[0];
+        const ash::AcceleratorId& accelerator_id = item.accelerator_ids[0];
         // Insert |shortcut_key_codes| by the order of CTRL, ALT, SHIFT, SEARCH,
         // and then key, to be consistent with how we describe it in the
         // |shortcut_message_id| associated string template.
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
index 7ed35ab3..a0e215b 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
@@ -16,16 +16,20 @@
 struct VectorIcon;
 }  // namespace gfx
 
-namespace keyboard_shortcut_viewer {
+namespace ash {
 
 struct KeyboardShortcutItem;
 enum class ShortcutCategory;
 
+}  // namespace ash
+
+namespace keyboard_shortcut_viewer {
+
 // Returns a list of Ash and Chrome keyboard shortcuts metadata.
-KSV_EXPORT const std::vector<KeyboardShortcutItem>&
+KSV_EXPORT const std::vector<ash::KeyboardShortcutItem>&
 GetKeyboardShortcutItemList();
 
-std::u16string GetStringForCategory(ShortcutCategory category);
+std::u16string GetStringForCategory(ash::ShortcutCategory category);
 
 // Returns the string of a DomKey for a given VKEY. VKEY needs to be mapped to
 // a physical key |dom_code| and then the |dom_code| needs to be mapped to a
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
index 34e84d76..2fb408ad 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -7,7 +7,7 @@
 #include <memory>
 #include <vector>
 
-#include "ash/shortcut_viewer/keyboard_shortcut_item.h"
+#include "ash/public/cpp/keyboard_shortcut_item.h"
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 #include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
@@ -57,8 +57,8 @@
 }  // namespace
 
 KeyboardShortcutItemView::KeyboardShortcutItemView(
-    const KeyboardShortcutItem& item,
-    ShortcutCategory category)
+    const ash::KeyboardShortcutItem& item,
+    ash::ShortcutCategory category)
     : shortcut_item_(&item), category_(category) {
   description_label_view_ =
       AddChildView(std::make_unique<views::StyledLabel>());
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.h b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.h
index d1a838d..012a3dc 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.h
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.h
@@ -5,7 +5,7 @@
 #ifndef ASH_SHORTCUT_VIEWER_VIEWS_KEYBOARD_SHORTCUT_ITEM_VIEW_H_
 #define ASH_SHORTCUT_VIEWER_VIEWS_KEYBOARD_SHORTCUT_ITEM_VIEW_H_
 
-#include "ash/shortcut_viewer/keyboard_shortcut_item.h"
+#include "ash/public/cpp/keyboard_shortcut_item.h"
 #include "ui/views/view.h"
 
 namespace views {
@@ -14,14 +14,11 @@
 
 namespace keyboard_shortcut_viewer {
 
-struct KeyboardShortcutItem;
-enum class ShortcutCategory;
-
 // A view that displays a shortcut metadata.
 class KeyboardShortcutItemView : public views::View {
  public:
-  KeyboardShortcutItemView(const KeyboardShortcutItem& item,
-                           ShortcutCategory category);
+  KeyboardShortcutItemView(const ash::KeyboardShortcutItem& item,
+                           ash::ShortcutCategory category);
   ~KeyboardShortcutItemView() override = default;
 
   // views::View:
@@ -35,9 +32,11 @@
 
   views::StyledLabel* shortcut_label_view() { return shortcut_label_view_; }
 
-  ShortcutCategory category() const { return category_; }
+  ash::ShortcutCategory category() const { return category_; }
 
-  const KeyboardShortcutItem* shortcut_item() const { return shortcut_item_; }
+  const ash::KeyboardShortcutItem* shortcut_item() const {
+    return shortcut_item_;
+  }
 
   // Clear the cache.
   static void ClearKeycodeToString16Cache();
@@ -56,9 +55,9 @@
   void CalculateLayout(int width) const;
 
   // Not owned. Pointer to the keyboard shortcut item.
-  const KeyboardShortcutItem* shortcut_item_;
+  const ash::KeyboardShortcutItem* shortcut_item_;
 
-  const ShortcutCategory category_;
+  const ash::ShortcutCategory category_;
 
   // View of the text describing what action the shortcut performs.
   views::StyledLabel* description_label_view_;
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
index d128c89..2a56e3b 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -141,7 +141,7 @@
 // Returns true if the given |item| should be excluded from the view, since
 // certain shortcuts can be associated with a disabled feature behind a flag,
 // or specific device property, e.g. keyboard layout.
-bool ShouldExcludeItem(const KeyboardShortcutItem& item) {
+bool ShouldExcludeItem(const ash::KeyboardShortcutItem& item) {
   switch (item.description_message_id) {
     case IDS_KSV_DESCRIPTION_OPEN_GOOGLE_ASSISTANT:
       return ui::DeviceKeyboardHasAssistantKey();
@@ -420,26 +420,26 @@
   // the startup time, we only initialize the first category pane, which is
   // visible to user, and defer initialization of other categories in the
   // background.
-  InitCategoriesTabbedPane(ShortcutCategory::kPopular);
+  InitCategoriesTabbedPane(ash::ShortcutCategory::kPopular);
 }
 
 void KeyboardShortcutView::InitCategoriesTabbedPane(
-    absl::optional<ShortcutCategory> initial_category) {
+    absl::optional<ash::ShortcutCategory> initial_category) {
   active_tab_index_ = categories_tabbed_pane_->GetSelectedTabIndex();
   // If the tab count is 0, GetSelectedTabIndex() will return kNoSelectedTab,
   // which we do not want to cache.
   if (active_tab_index_ == views::TabStrip::kNoSelectedTab)
     active_tab_index_ = 0;
 
-  ShortcutCategory current_category = ShortcutCategory::kUnknown;
+  ash::ShortcutCategory current_category = ash::ShortcutCategory::kUnknown;
   KeyboardShortcutItemListView* item_list_view = nullptr;
   std::vector<KeyboardShortcutItemView*> shortcut_items;
   const bool already_has_tabs = categories_tabbed_pane_->GetTabCount() > 0;
   size_t tab_index = 0;
   views::View* const tab_contents = categories_tabbed_pane_->children()[1];
   for (const auto& item_view : shortcut_views_) {
-    const ShortcutCategory category = item_view->category();
-    DCHECK_NE(ShortcutCategory::kUnknown, category);
+    const ash::ShortcutCategory category = item_view->category();
+    DCHECK_NE(ash::ShortcutCategory::kUnknown, category);
     if (current_category != category) {
       current_category = category;
       std::unique_ptr<views::View> content_view;
@@ -530,7 +530,7 @@
   auto found_items_list_view = std::make_unique<KeyboardShortcutItemListView>();
   base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents finder(
       search_query);
-  ShortcutCategory current_category = ShortcutCategory::kUnknown;
+  ash::ShortcutCategory current_category = ash::ShortcutCategory::kUnknown;
   bool has_category_item = false;
   found_shortcut_items_.clear();
 
@@ -547,7 +547,7 @@
     // |shortcut_label_view_|.
     if (finder.Search(description_text, &match_index, &match_length) ||
         finder.Search(shortcut_text, nullptr, nullptr)) {
-      const ShortcutCategory category = item_view->category();
+      const ash::ShortcutCategory category = item_view->category();
       if (current_category != category) {
         current_category = category;
         has_category_item = false;
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_view.h b/ash/shortcut_viewer/views/keyboard_shortcut_view.h
index 57563c0..695a3127 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_view.h
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_view.h
@@ -24,11 +24,14 @@
 class Widget;
 }  // namespace views
 
+namespace ash {
+enum class ShortcutCategory;
+}  // namespace ash
+
 namespace keyboard_shortcut_viewer {
 
 class KeyboardShortcutItemView;
 class KSVSearchBoxView;
-enum class ShortcutCategory;
 
 // The UI container for Ash and Chrome keyboard shortcuts.
 class KeyboardShortcutView : public views::WidgetDelegateView,
@@ -74,7 +77,7 @@
   // If |initial_category| has value, we will initialize the specified category,
   // otherwise all the categories will be intialized.
   void InitCategoriesTabbedPane(
-      absl::optional<ShortcutCategory> initial_category);
+      absl::optional<ash::ShortcutCategory> initial_category);
 
   // Update views' layout based on search box status.
   void UpdateViewsLayout(bool is_search_box_active);
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc b/ash/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
index 1b1cd7e1..f9acc65 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
@@ -132,9 +132,9 @@
   views::Widget* widget = Toggle();
 
   size_t category_number = 0;
-  ShortcutCategory current_category = ShortcutCategory::kUnknown;
+  ash::ShortcutCategory current_category = ash::ShortcutCategory::kUnknown;
   for (const auto& item_view : GetShortcutViews()) {
-    const ShortcutCategory category = item_view->category();
+    const ash::ShortcutCategory category = item_view->category();
     if (current_category != category) {
       DCHECK(current_category < category);
       ++category_number;
@@ -155,7 +155,7 @@
   for (const auto& item_view : GetShortcutViews()) {
     // We only initialize the first visible category and other non-visible panes
     // are deferred initialized.
-    if (item_view->category() != ShortcutCategory::kPopular)
+    if (item_view->category() != ash::ShortcutCategory::kPopular)
       continue;
 
     ASSERT_EQ(2u, item_view->children().size());
diff --git a/ash/system/holding_space/holding_space_view_delegate.cc b/ash/system/holding_space/holding_space_view_delegate.cc
index e6a58ce..5357fd1 100644
--- a/ash/system/holding_space/holding_space_view_delegate.cc
+++ b/ash/system/holding_space/holding_space_view_delegate.cc
@@ -437,8 +437,8 @@
 
   context_menu_runner_->RunMenuAt(
       source->GetWidget(), nullptr /*button_controller*/,
-      source->GetBoundsInScreen(), views::MenuAnchorPosition::kBubbleBelow,
-      source_type);
+      source->GetBoundsInScreen(),
+      views::MenuAnchorPosition::kBubbleBottomRight, source_type);
 }
 
 bool HoldingSpaceViewDelegate::CanStartDragForView(
diff --git a/ash/system/message_center/session_state_notification_blocker.cc b/ash/system/message_center/session_state_notification_blocker.cc
index fb7acd9..9b4a827 100644
--- a/ash/system/message_center/session_state_notification_blocker.cc
+++ b/ash/system/message_center/session_state_notification_blocker.cc
@@ -112,6 +112,14 @@
   if (session_controller->IsRunningInAppMode())
     return false;
 
+  // Do not show non system notifications for `kLoginNotificationsDelay`
+  // duration.
+  if (notification.notifier_id().type !=
+          message_center::NotifierType::SYSTEM_COMPONENT &&
+      login_delay_timer_.IsRunning()) {
+    return false;
+  }
+
   if (notification.id() == BatteryNotification::kNotificationId)
     return true;
 
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc
index 9c9749e..8c7e4c5 100644
--- a/ash/system/palette/palette_tray.cc
+++ b/ash/system/palette/palette_tray.cc
@@ -126,6 +126,7 @@
 
     icon_->SetImage(stylus_battery_delegate_.GetBatteryImage());
     label_->SetVisible(stylus_battery_delegate_.IsBatteryLevelLow() &&
+                       stylus_battery_delegate_.IsBatteryStatusEligible() &&
                        !stylus_battery_delegate_.IsBatteryStatusStale() &&
                        !stylus_battery_delegate_.IsBatteryCharging());
   }
diff --git a/ash/system/palette/stylus_battery_delegate.cc b/ash/system/palette/stylus_battery_delegate.cc
index 671fea5..79b1fc585 100644
--- a/ash/system/palette/stylus_battery_delegate.cc
+++ b/ash/system/palette/stylus_battery_delegate.cc
@@ -89,7 +89,7 @@
 }
 
 bool StylusBatteryDelegate::ShouldShowBatteryStatus() const {
-  return last_update_timestamp_.has_value();
+  return last_update_timestamp_.has_value() && last_update_eligible_;
 }
 
 bool StylusBatteryDelegate::IsBatteryStatusStale() const {
@@ -100,6 +100,10 @@
          kStylusBatteryStatusStaleThreshold;
 }
 
+bool StylusBatteryDelegate::IsBatteryStatusEligible() const {
+  return last_update_eligible_;
+}
+
 bool StylusBatteryDelegate::IsBatteryInfoValid(
     const PeripheralBatteryListener::BatteryInfo& battery) const {
   if (battery.type != PeripheralBatteryListener::BatteryInfo::PeripheralType::
@@ -136,6 +140,7 @@
   battery_level_ = battery.level;
   battery_charge_status_ = battery.charge_status;
   last_update_timestamp_ = battery.last_active_update_timestamp;
+  last_update_eligible_ = battery.battery_report_eligible;
   if (battery_update_callback_)
     battery_update_callback_.Run();
 }
diff --git a/ash/system/palette/stylus_battery_delegate.h b/ash/system/palette/stylus_battery_delegate.h
index e5eece9..f42f41a 100644
--- a/ash/system/palette/stylus_battery_delegate.h
+++ b/ash/system/palette/stylus_battery_delegate.h
@@ -31,6 +31,7 @@
   bool IsBatteryCharging() const;
   bool IsBatteryLevelLow() const;
   bool IsBatteryStatusStale() const;
+  bool IsBatteryStatusEligible() const;
   bool ShouldShowBatteryStatus() const;
 
   absl::optional<uint8_t> battery_level() const { return battery_level_; }
@@ -51,6 +52,7 @@
       PeripheralBatteryListener::BatteryInfo::ChargeStatus::kUnknown;
   absl::optional<uint8_t> battery_level_;
   absl::optional<base::TimeTicks> last_update_timestamp_;
+  bool last_update_eligible_ = false;
 
   Callback battery_update_callback_;
   base::ScopedObservation<PeripheralBatteryListener,
diff --git a/ash/system/power/peripheral_battery_notifier.cc b/ash/system/power/peripheral_battery_notifier.cc
index 1efcd12..8c330a2 100644
--- a/ash/system/power/peripheral_battery_notifier.cc
+++ b/ash/system/power/peripheral_battery_notifier.cc
@@ -154,7 +154,7 @@
 
 void PeripheralBatteryNotifier::UpdateBattery(
     const PeripheralBatteryListener::BatteryInfo& battery_info) {
-  if (!battery_info.level) {
+  if (!battery_info.level || !battery_info.battery_report_eligible) {
     CancelNotification(battery_info);
     return;
   }
diff --git a/ash/wm/collision_detection/collision_detection_utils_unittest.cc b/ash/wm/collision_detection/collision_detection_utils_unittest.cc
index 9238215..4f98951 100644
--- a/ash/wm/collision_detection/collision_detection_utils_unittest.cc
+++ b/ash/wm/collision_detection/collision_detection_utils_unittest.cc
@@ -60,7 +60,7 @@
 }
 
 TEST_F(CollisionDetectionUtilsTest, AvoidObstaclesAvoidsUnifiedSystemTray) {
-  UpdateDisplay("1000x1000");
+  UpdateDisplay("1000x900");
   auto* unified_system_tray = GetPrimaryUnifiedSystemTray();
   unified_system_tray->ShowBubble();
 
@@ -108,6 +108,21 @@
  protected:
   display::Display GetDisplay() { return GetDisplayForWindow(root_window_); }
 
+  gfx::Rect GetKeyboardBounds(int keyboard_height) {
+    gfx::Rect keyboard_bounds(GetDisplay().bounds().size());
+    keyboard_bounds.set_y(keyboard_bounds.bottom() - keyboard_height);
+    keyboard_bounds.set_height(100);
+    return keyboard_bounds;
+  }
+
+  void TransposeIfPortrait(gfx::Rect* rect) {
+    bool landscape =
+        GetDisplay().bounds().width() > GetDisplay().bounds().height();
+    if (!landscape) {
+      rect->SetRect(rect->y(), rect->x(), rect->height(), rect->width());
+    }
+  }
+
   aura::Window* root_window() { return root_window_; }
 
   gfx::Rect ConvertToScreen(const gfx::Rect& bounds) {
@@ -135,7 +150,9 @@
 
 TEST_P(CollisionDetectionUtilsDisplayTest, MovementAreaIsInset) {
   gfx::Rect area = CollisionDetectionUtils::GetMovementArea(GetDisplay());
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(8, 8, 384, 384)), area);
+  gfx::Rect expected(8, 8, 484, 384);
+  TransposeIfPortrait(&expected);
+  EXPECT_EQ(ConvertToScreen(expected), area);
 }
 
 TEST_P(CollisionDetectionUtilsDisplayTest,
@@ -144,14 +161,23 @@
   keyboard_controller->ShowKeyboardInDisplay(GetDisplay());
   ASSERT_TRUE(keyboard::WaitUntilShown());
   aura::Window* keyboard_window = keyboard_controller->GetKeyboardWindow();
-  keyboard_window->SetBounds(gfx::Rect(0, 300, 400, 100));
+
+  constexpr int keyboard_height = 100;
+  gfx::Rect keyboard_bounds = GetKeyboardBounds(keyboard_height);
+  keyboard_window->SetBounds(keyboard_bounds);
+
+  gfx::Rect expected = gfx::Rect(GetDisplay().bounds().size());
+  expected.Inset(0, 0, 0, keyboard_height);
+  expected.Inset(8, 8);
 
   gfx::Rect area = CollisionDetectionUtils::GetMovementArea(GetDisplay());
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(8, 8, 384, 284)), area);
+  EXPECT_EQ(ConvertToScreen(expected), area);
 }
 
 TEST_P(CollisionDetectionUtilsDisplayTest, RestingPositionSnapsToClosestEdge) {
   auto display = GetDisplay();
+  int right = display.bounds().width();
+  int bottom = display.bounds().height();
 
   // Snap near top edge to top.
   EXPECT_EQ(ConvertToScreen(gfx::Rect(100, 8, 100, 100)),
@@ -160,9 +186,9 @@
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near bottom edge to bottom.
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(100, 292, 100, 100)),
+  EXPECT_EQ(ConvertToScreen(gfx::Rect(100, bottom - 108, 100, 100)),
             CollisionDetectionUtils::GetRestingPosition(
-                display, ConvertToScreen(gfx::Rect(100, 250, 100, 100)),
+                display, ConvertToScreen(gfx::Rect(100, bottom - 50, 100, 100)),
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near left edge to left.
@@ -172,14 +198,16 @@
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near right edge to right.
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(292, 100, 100, 100)),
+  EXPECT_EQ(ConvertToScreen(gfx::Rect(right - 108, 100, 100, 100)),
             CollisionDetectionUtils::GetRestingPosition(
-                display, ConvertToScreen(gfx::Rect(250, 100, 100, 100)),
+                display, ConvertToScreen(gfx::Rect(right - 50, 100, 100, 100)),
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 }
 
 TEST_P(CollisionDetectionUtilsDisplayTest, RestingPositionSnapsInsideDisplay) {
   auto display = GetDisplay();
+  int right = display.bounds().width();
+  int bottom = display.bounds().height();
 
   // Snap near top edge outside movement area to top.
   EXPECT_EQ(ConvertToScreen(gfx::Rect(100, 8, 100, 100)),
@@ -188,9 +216,9 @@
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near bottom edge outside movement area to bottom.
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(100, 292, 100, 100)),
+  EXPECT_EQ(ConvertToScreen(gfx::Rect(100, bottom - 108, 100, 100)),
             CollisionDetectionUtils::GetRestingPosition(
-                display, ConvertToScreen(gfx::Rect(100, 450, 100, 100)),
+                display, ConvertToScreen(gfx::Rect(100, 1000, 100, 100)),
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near left edge outside movement area to left.
@@ -200,9 +228,9 @@
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 
   // Snap near right edge outside movement area to right.
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(292, 100, 100, 100)),
+  EXPECT_EQ(ConvertToScreen(gfx::Rect(right - 108, 100, 100, 100)),
             CollisionDetectionUtils::GetRestingPosition(
-                display, ConvertToScreen(gfx::Rect(450, 100, 100, 100)),
+                display, ConvertToScreen(gfx::Rect(1000, 100, 100, 100)),
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 }
 
@@ -330,11 +358,16 @@
   keyboard_controller->ShowKeyboardInDisplay(display);
   ASSERT_TRUE(keyboard::WaitUntilShown());
   aura::Window* keyboard_window = keyboard_controller->GetKeyboardWindow();
-  keyboard_window->SetBounds(gfx::Rect(0, 300, 400, 100));
 
-  EXPECT_EQ(ConvertToScreen(gfx::Rect(8, 192, 100, 100)),
+  constexpr int keyboard_height = 100;
+  gfx::Rect keyboard_bounds = GetKeyboardBounds(keyboard_height);
+  keyboard_window->SetBounds(keyboard_bounds);
+
+  gfx::Rect expected =
+      gfx::Rect(8, display.bounds().height() - 100 - 108, 100, 100);
+  EXPECT_EQ(ConvertToScreen(expected),
             CollisionDetectionUtils::GetRestingPosition(
-                display, ConvertToScreen(gfx::Rect(8, 300, 100, 100)),
+                display, ConvertToScreen(gfx::Rect(8, 500, 100, 100)),
                 CollisionDetectionUtils::RelativePriority::kPictureInPicture));
 }
 
@@ -355,13 +388,13 @@
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     CollisionDetectionUtilsDisplayTest,
-    testing::Values(std::make_tuple("400x400", 0u),
-                    std::make_tuple("400x400/r", 0u),
-                    std::make_tuple("400x400/u", 0u),
-                    std::make_tuple("400x400/l", 0u),
-                    std::make_tuple("800x800*2", 0u),
-                    std::make_tuple("400x400,400x400", 0u),
-                    std::make_tuple("400x400,400x400", 1u)));
+    testing::Values(std::make_tuple("500x400", 0u),
+                    std::make_tuple("500x400/r", 0u),
+                    std::make_tuple("500x400/u", 0u),
+                    std::make_tuple("500x400/l", 0u),
+                    std::make_tuple("1000x800*2", 0u),
+                    std::make_tuple("500x400,500x400", 0u),
+                    std::make_tuple("500x400,500x400", 1u)));
 
 class CollisionDetectionUtilsLogicTest : public ::testing::Test {
  public:
diff --git a/ash/wm/desks/persistent_desks_bar_context_menu.cc b/ash/wm/desks/persistent_desks_bar_context_menu.cc
index 07ac766b..ef69730 100644
--- a/ash/wm/desks/persistent_desks_bar_context_menu.cc
+++ b/ash/wm/desks/persistent_desks_bar_context_menu.cc
@@ -34,7 +34,7 @@
   context_menu_runner_->RunMenuAt(
       source->GetWidget(), /*button_controller=*/nullptr,
       gfx::Rect(source->GetBoundsInScreen().bottom_right(), gfx::Size()),
-      views::MenuAnchorPosition::kBubbleBelow, source_type);
+      views::MenuAnchorPosition::kBubbleBottomRight, source_type);
 }
 
 void PersistentDesksBarContextMenu::ExecuteCommand(int command_id,
diff --git a/base/files/memory_mapped_file.h b/base/files/memory_mapped_file.h
index 08ace8c..386355f 100644
--- a/base/files/memory_mapped_file.h
+++ b/base/files/memory_mapped_file.h
@@ -15,7 +15,7 @@
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
-#include <windows.h>
+#include "base/win/scoped_handle.h"
 #endif
 
 namespace base {
diff --git a/base/process/launch.h b/base/process/launch.h
index 26f4a53c..58f1e3b 100644
--- a/base/process/launch.h
+++ b/base/process/launch.h
@@ -26,7 +26,7 @@
 #include "build/chromeos_buildflags.h"
 
 #if defined(OS_WIN)
-#include <windows.h>
+#include "base/win/windows_types.h"
 #elif defined(OS_FUCHSIA)
 #include <lib/fdio/spawn.h>
 #include <zircon/types.h>
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 84fa883..345a4af 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -75,6 +75,9 @@
 #include "base/win/windows_version.h"
 
 #include <windows.h>
+
+// To avoid conflicts with the macro from the Windows SDK...
+#undef GetCommandLine
 #endif
 
 #if defined(OS_FUCHSIA)
diff --git a/base/win/message_window.cc b/base/win/message_window.cc
index 4525f79e..8296377 100644
--- a/base/win/message_window.cc
+++ b/base/win/message_window.cc
@@ -13,6 +13,9 @@
 
 #include <windows.h>
 
+// To avoid conflicts with the macro from the Windows SDK...
+#undef FindWindow
+
 const wchar_t kMessageWindowClassName[] = L"Chrome_MessageWindow";
 
 namespace base {
diff --git a/base/win/message_window.h b/base/win/message_window.h
index 335aecb..5cccc231 100644
--- a/base/win/message_window.h
+++ b/base/win/message_window.h
@@ -5,8 +5,6 @@
 #ifndef BASE_WIN_MESSAGE_WINDOW_H_
 #define BASE_WIN_MESSAGE_WINDOW_H_
 
-#include <windows.h>
-
 #include <string>
 
 #include "base/base_export.h"
@@ -14,6 +12,10 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
+#include "base/win/windows_types.h"
+
+// Protect against windows.h being included before this header.
+#undef FindWindow
 
 namespace base {
 namespace win {
diff --git a/base/win/message_window_unittest.cc b/base/win/message_window_unittest.cc
index 0193b42..4217707 100644
--- a/base/win/message_window_unittest.cc
+++ b/base/win/message_window_unittest.cc
@@ -11,6 +11,9 @@
 
 #include <windows.h>
 
+// To avoid conflicts with the macro from the Windows SDK...
+#undef FindWindow
+
 namespace base {
 
 namespace {
diff --git a/base/win/variant_vector.h b/base/win/variant_vector.h
index a65e39d..896f3894 100644
--- a/base/win/variant_vector.h
+++ b/base/win/variant_vector.h
@@ -15,7 +15,6 @@
 #include "base/base_export.h"
 #include "base/check.h"
 #include "base/logging.h"
-#include "base/no_destructor.h"
 #include "base/win/scoped_variant.h"
 #include "base/win/variant_util.h"
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 8958c5c..3ed306a 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -3441,6 +3441,15 @@
                         invoker.type == "java_library"
       _build_device_jar =
           invoker.type != "system_java_library" && _supports_android
+
+      _jacoco_instrument =
+          use_jacoco_coverage && _chromium_code && _java_files != [] &&
+          _build_device_jar && (!defined(invoker.testonly) || !invoker.testonly)
+      if (defined(invoker.jacoco_never_instrument)) {
+        _jacoco_instrument =
+            !invoker.jacoco_never_instrument && _jacoco_instrument
+      }
+
       if (_build_host_jar) {
         # Jar files can be needed at runtime (by Robolectric tests or java binaries),
         # so do not put them under obj/.
@@ -3451,13 +3460,25 @@
             "$root_out_dir/lib.java$_target_dir_name/$_output_name.jar"
       }
       if (_build_device_jar) {
-        _device_processed_jar_path =
-            "$target_out_dir/$_output_name.processed.jar"
         _dex_path = "$target_out_dir/$_main_target_name.dex.jar"
         _enable_desugar =
             !defined(invoker.enable_desugar) || invoker.enable_desugar
         _use_classic_desugar =
             defined(invoker.use_classic_desugar) && invoker.use_classic_desugar
+
+        # Build speed optimization: Skip "process device" step if the step
+        # would be just a copy and avoid the copy.
+        _process_device_jar =
+            defined(invoker.bytecode_rewriter_target) || _jacoco_instrument ||
+            (_enable_desugar && _use_classic_desugar) ||
+            defined(invoker.jar_excluded_patterns) ||
+            defined(invoker.jar_included_patterns)
+        if (!_process_device_jar && _is_prebuilt) {
+          _device_processed_jar_path = invoker.jar_path
+        } else {
+          _device_processed_jar_path =
+              "$target_out_dir/$_output_name.processed.jar"
+        }
       }
 
       # For static libraries, the javac jar output is created at the intermediate
@@ -3472,7 +3493,11 @@
       }
 
       if (_has_sources) {
-        _javac_jar_path = "$target_out_dir/$_main_target_name.javac.jar"
+        if (_build_device_jar && !_process_device_jar) {
+          _javac_jar_path = _device_processed_jar_path
+        } else {
+          _javac_jar_path = "$target_out_dir/$_main_target_name.javac.jar"
+        }
         _generated_jar_path =
             "$target_gen_dir/$_main_target_name.generated.srcjar"
       }
@@ -3518,13 +3543,6 @@
       }
 
       _extra_java_deps = []
-      _jacoco_instrument =
-          use_jacoco_coverage && _chromium_code && _java_files != [] &&
-          _build_device_jar && (!defined(invoker.testonly) || !invoker.testonly)
-      if (defined(invoker.jacoco_never_instrument)) {
-        _jacoco_instrument =
-            !invoker.jacoco_never_instrument && _jacoco_instrument
-      }
       if (_jacoco_instrument) {
         _extra_java_deps += [ "//third_party/jacoco:jacocoagent_java" ]
       }
@@ -3940,30 +3958,37 @@
       }
 
       if (_build_device_jar) {
-        _process_device_jar_target_name = "${target_name}__process_device"
-        process_java_library(_process_device_jar_target_name) {
-          forward_variables_from(invoker,
-                                 [
-                                   "jar_excluded_patterns",
-                                   "jar_included_patterns",
-                                 ])
-          input_jar_path = _unprocessed_jar_path
-          jar_deps = _unprocessed_jar_deps + _full_classpath_deps
-          is_device_jar = true
-          output_jar_path = _device_processed_jar_path
-          jacoco_instrument = _jacoco_instrument
-          if (_jacoco_instrument) {
-            java_files = _java_files
-            java_sources_file = _java_sources_file
+        if (_process_device_jar) {
+          _process_device_jar_target_name = "${target_name}__process_device"
+          process_java_library(_process_device_jar_target_name) {
+            forward_variables_from(invoker,
+                                   [
+                                     "jar_excluded_patterns",
+                                     "jar_included_patterns",
+                                   ])
+            input_jar_path = _unprocessed_jar_path
+            jar_deps = _unprocessed_jar_deps + _full_classpath_deps
+            is_device_jar = true
+            output_jar_path = _device_processed_jar_path
+            jacoco_instrument = _jacoco_instrument
+            if (_jacoco_instrument) {
+              java_files = _java_files
+              java_sources_file = _java_sources_file
+            }
+            enable_desugar = _enable_desugar && _use_classic_desugar
+            if (enable_desugar) {
+              build_config = _build_config
+              classpath_deps = _classpath_deps
+              forward_variables_from(invoker, [ "desugar_jars_paths" ])
+            }
           }
-          enable_desugar = _enable_desugar && _use_classic_desugar
-          if (enable_desugar) {
-            build_config = _build_config
-            classpath_deps = _classpath_deps
-            forward_variables_from(invoker, [ "desugar_jars_paths" ])
-          }
+          _process_device_jar_deps = [ ":${_process_device_jar_target_name}" ]
+          _public_deps += _process_device_jar_deps
+        } else {
+          assert(_unprocessed_jar_path == _device_processed_jar_path)
+          _process_device_jar_deps =
+              _unprocessed_jar_deps + _full_classpath_deps
         }
-        _public_deps += [ ":${_process_device_jar_target_name}" ]
 
         dex("${target_name}__dex") {
           forward_variables_from(invoker,
@@ -3980,7 +4005,7 @@
           # change just one class at a time.
           disable_incremental = _is_prebuilt
           output = _dex_path
-          deps = [ ":${_process_device_jar_target_name}" ]
+          deps = _process_device_jar_deps
 
           if (enable_desugar && !_use_classic_desugar) {
             # Desugaring with D8 requires full classpath.
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index e157ee9..97508d03 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1609,9 +1609,6 @@
           # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662
           "-Wno-ignored-pragma-optimize",
 
-          # TODO(https://crbug.com/989932): Evaluate and possibly enable.
-          "-Wno-implicit-int-float-conversion",
-
           # TODO(https://crbug.com/999886): Clean up, enable.
           "-Wno-final-dtor-non-final-class",
 
diff --git a/build/config/ios/BUILD.gn b/build/config/ios/BUILD.gn
index b631590..5309e82 100644
--- a/build/config/ios/BUILD.gn
+++ b/build/config/ios/BUILD.gn
@@ -163,9 +163,6 @@
   ldflags = [
     # Always load Objective-C categories and class.
     "-Wl,-ObjC",
-
-    # Uses version 2 of Objective-C ABI.
-    "-Wl,-objc_abi_version,2",
   ]
 
   # The path to the Swift compatibility libraries (required to run code built
diff --git a/cc/animation/BUILD.gn b/cc/animation/BUILD.gn
index 466d3f1..ea30f94c 100644
--- a/cc/animation/BUILD.gn
+++ b/cc/animation/BUILD.gn
@@ -27,6 +27,8 @@
     "keyframe_effect.h",
     "keyframe_model.cc",
     "keyframe_model.h",
+    "scoped_compound_transform_resolver.cc",
+    "scoped_compound_transform_resolver.h",
     "scroll_offset_animation_curve.cc",
     "scroll_offset_animation_curve.h",
     "scroll_offset_animation_curve_factory.cc",
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 091f17b..552ee1d 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -21,6 +21,7 @@
 #include "cc/animation/animation_timeline.h"
 #include "cc/animation/element_animations.h"
 #include "cc/animation/keyframe_effect.h"
+#include "cc/animation/scoped_compound_transform_resolver.h"
 #include "cc/animation/scroll_offset_animation_curve.h"
 #include "cc/animation/scroll_offset_animations.h"
 #include "cc/animation/scroll_offset_animations_impl.h"
@@ -452,6 +453,8 @@
 
   TRACE_EVENT_INSTANT0("cc", "NeedsTickAnimations", TRACE_EVENT_SCOPE_THREAD);
 
+  ScopedCompoundTransformResolver scoped_compound_transform_resolver(this);
+
   bool animated = false;
   for (auto& kv : id_to_timeline_map_) {
     AnimationTimeline* timeline = kv.second.get();
@@ -484,9 +487,20 @@
 }
 
 void AnimationHost::TickWorkletAnimations() {
+  bool has_worklet_animation = false;
   for (auto& animation : ticking_animations_) {
-    if (!animation->IsWorkletAnimation())
-      continue;
+    if (animation->IsWorkletAnimation()) {
+      has_worklet_animation = true;
+      break;
+    }
+  }
+  if (!has_worklet_animation)
+    return;
+
+  ScopedCompoundTransformResolver scoped_compound_transform_resolver(this);
+  for (auto& animation : ticking_animations_) {
+    // TODO(crbug.com/1228417): Only need to tick non-worklet animations that
+    // are potentially affected by a worklet animation.
     animation->Tick(base::TimeTicks());
   }
 }
@@ -606,10 +620,11 @@
     ElementId element_id,
     ElementListType list_type) const {
   auto element_animations = GetElementAnimationsForElementId(element_id);
-  return element_animations
-             ? element_animations->IsCurrentlyAnimatingProperty(
-                   TargetProperty::TRANSFORM, list_type)
-             : false;
+  if (!element_animations)
+    return false;
+
+  return element_animations->IsCurrentlyAnimatingTransformRelatedProperty(
+      list_type);
 }
 
 bool AnimationHost::HasPotentiallyRunningFilterAnimation(
@@ -647,8 +662,7 @@
     ElementListType list_type) const {
   auto element_animations = GetElementAnimationsForElementId(element_id);
   return element_animations
-             ? element_animations->IsPotentiallyAnimatingProperty(
-                   TargetProperty::TRANSFORM, list_type)
+             ? element_animations->IsPotentiallyAnimatingTransform(list_type)
              : false;
 }
 
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 224d411..3615ceb 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -29,6 +29,7 @@
 class AnimationTimeline;
 class ElementAnimations;
 class LayerTreeHost;
+class ScopedCompoundTransformResolver;
 class ScrollOffsetAnimations;
 class ScrollOffsetAnimationsImpl;
 class WorkletAnimation;
@@ -222,6 +223,10 @@
   void SetCurrentFrameHadRaf(bool current_frame_had_raf);
   void SetNextFrameHasPendingRaf(bool next_frame_has_pending_raf);
 
+  ScopedCompoundTransformResolver* compound_transform_resolver() {
+    return compound_transform_resolver_;
+  }
+
  private:
   explicit AnimationHost(ThreadInstance thread_instance);
 
@@ -246,6 +251,12 @@
   // if there is no match.
   WorkletAnimation* FindWorkletAnimation(WorkletAnimationId id);
 
+  friend class ScopedCompoundTransformResolver;
+  void set_compound_transform_resolver(
+      ScopedCompoundTransformResolver* resolver) {
+    compound_transform_resolver_ = resolver;
+  }
+
   ElementToAnimationsMap element_to_animations_map_;
   AnimationsList ticking_animations_;
 
@@ -278,6 +289,8 @@
 
   PendingThroughputTrackerInfos pending_throughput_tracker_infos_;
 
+  ScopedCompoundTransformResolver* compound_transform_resolver_ = nullptr;
+
   base::WeakPtrFactory<AnimationHost> weak_factory_{this};
 };
 
diff --git a/cc/animation/animation_unittest.cc b/cc/animation/animation_unittest.cc
index 15fe896..55f5447 100644
--- a/cc/animation/animation_unittest.cc
+++ b/cc/animation/animation_unittest.cc
@@ -459,15 +459,15 @@
   animation_->AddKeyframeModel(KeyframeModel::Create(
       std::make_unique<FakeFloatAnimationCurve>(15), 42, 73,
       KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)));
-  EXPECT_EQ(
-      base::StringPrintf("Animation{id=%d, element_id=%s, "
-                         "keyframe_models=[KeyframeModel{id=42, "
-                         "group=73, target_property_type=1, "
-                         "custom_property_name=, native_property_type=1, "
-                         "run_state=WAITING_FOR_TARGET_AVAILABILITY, "
-                         "element_id=(0)}]}",
-                         animation_->id(), element_id_.ToString().c_str()),
-      animation_->ToString());
+  EXPECT_EQ(base::StringPrintf("Animation{id=%d, element_id=%s, "
+                               "keyframe_models=[KeyframeModel{id=42, "
+                               "group=73, target_property_type=%d, "
+                               "custom_property_name=, native_property_type=1, "
+                               "run_state=WAITING_FOR_TARGET_AVAILABILITY, "
+                               "element_id=(0)}]}",
+                               animation_->id(), element_id_.ToString().c_str(),
+                               TargetProperty::OPACITY),
+            animation_->ToString());
 
   animation_->AddKeyframeModel(KeyframeModel::Create(
       std::make_unique<FakeFloatAnimationCurve>(18), 45, 76,
@@ -475,13 +475,14 @@
   EXPECT_EQ(base::StringPrintf(
                 "Animation{id=%d, element_id=%s, "
                 "keyframe_models=[KeyframeModel{id=42, "
-                "group=73, target_property_type=1, custom_property_name=, "
+                "group=73, target_property_type=%d, custom_property_name=, "
                 "native_property_type=1, "
                 "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}, "
-                "KeyframeModel{id=45, group=76, target_property_type=5, "
+                "KeyframeModel{id=45, group=76, target_property_type=%d, "
                 "custom_property_name=, native_property_type=1, "
                 "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}]}",
-                animation_->id(), element_id_.ToString().c_str()),
+                animation_->id(), element_id_.ToString().c_str(),
+                TargetProperty::OPACITY, TargetProperty::BOUNDS),
             animation_->ToString());
 }
 
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index bb4fad0..d6969ae 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <utility>
+#include <vector>
 
 #include "base/numerics/ranges.h"
 #include "cc/animation/animation_delegate.h"
@@ -15,6 +16,7 @@
 #include "cc/animation/animation_host.h"
 #include "cc/animation/keyframe_effect.h"
 #include "cc/animation/keyframe_model.h"
+#include "cc/animation/scoped_compound_transform_resolver.h"
 #include "cc/paint/filter_operations.h"
 #include "cc/trees/mutator_host_client.h"
 #include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
@@ -273,11 +275,23 @@
     const gfx::TransformOperations& operations,
     int target_property_id,
     gfx::KeyframeModel* keyframe_model) {
-  gfx::Transform transform = operations.Apply();
-  if (KeyframeModelAffectsActiveElements(keyframe_model))
-    OnTransformAnimated(ElementListType::ACTIVE, transform, keyframe_model);
-  if (KeyframeModelAffectsPendingElements(keyframe_model))
-    OnTransformAnimated(ElementListType::PENDING, transform, keyframe_model);
+  bool apply_active = KeyframeModelAffectsActiveElements(keyframe_model);
+  bool apply_pending = KeyframeModelAffectsPendingElements(keyframe_model);
+
+  if (apply_active || apply_pending) {
+    gfx::Transform transform = operations.Apply();
+    ElementId target_element_id =
+        CalculateTargetElementId(this, keyframe_model);
+    DCHECK(target_element_id);
+    DCHECK(animation_host_);
+    ScopedCompoundTransformResolver* compound_transform_resolver =
+        animation_host_->compound_transform_resolver();
+    DCHECK(compound_transform_resolver);
+    compound_transform_resolver->AddTransform(
+        target_element_id, transform,
+        static_cast<TargetProperty::Type>(target_property_id), apply_active,
+        apply_pending);
+  }
 }
 
 void ElementAnimations::OnScrollOffsetAnimated(
@@ -430,6 +444,9 @@
 bool ElementAnimations::IsPotentiallyAnimatingProperty(
     TargetProperty::Type target_property,
     ElementListType list_type) const {
+  // For transform related properties, call IsPotentiallyAnimatingTransform.
+  DCHECK(target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+         target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY);
   for (auto& keyframe_effect : keyframe_effects_list_) {
     if (keyframe_effect.IsPotentiallyAnimatingProperty(target_property,
                                                        list_type))
@@ -439,9 +456,23 @@
   return false;
 }
 
+bool ElementAnimations::IsPotentiallyAnimatingTransform(
+    ElementListType list_type) const {
+  for (auto& keyframe_effect : keyframe_effects_list_) {
+    if (keyframe_effect.IsPotentiallyAnimatingTransformRelatedProperty(
+            list_type))
+      return true;
+  }
+  return false;
+}
+
 bool ElementAnimations::IsCurrentlyAnimatingProperty(
     TargetProperty::Type target_property,
     ElementListType list_type) const {
+  // For transform related properties, call
+  // IsCurrentlyAnimatingTransformRelatedProperty.
+  DCHECK(target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+         target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY);
   for (auto& keyframe_effect : keyframe_effects_list_) {
     if (keyframe_effect.IsCurrentlyAnimatingProperty(target_property,
                                                      list_type))
@@ -451,6 +482,16 @@
   return false;
 }
 
+bool ElementAnimations::IsCurrentlyAnimatingTransformRelatedProperty(
+    ElementListType list_type) const {
+  for (auto& keyframe_effect : keyframe_effects_list_) {
+    if (keyframe_effect.IsCurrentlyAnimatingTransformRelatedProperty(list_type))
+      return true;
+  }
+
+  return false;
+}
+
 void ElementAnimations::OnFilterAnimated(ElementListType list_type,
                                          const FilterOperations& filters,
                                          gfx::KeyframeModel* keyframe_model) {
@@ -507,18 +548,6 @@
       std::move(property_key), std::move(property_value));
 }
 
-void ElementAnimations::OnTransformAnimated(
-    ElementListType list_type,
-    const gfx::Transform& transform,
-    gfx::KeyframeModel* keyframe_model) {
-  ElementId target_element_id = CalculateTargetElementId(this, keyframe_model);
-  DCHECK(target_element_id);
-  DCHECK(animation_host_);
-  DCHECK(animation_host_->mutator_host_client());
-  animation_host_->mutator_host_client()->SetElementTransformMutated(
-      target_element_id, list_type, transform);
-}
-
 void ElementAnimations::OnScrollOffsetAnimated(
     ElementListType list_type,
     const gfx::ScrollOffset& scroll_offset,
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 8430489..e97dca1 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -91,11 +91,23 @@
   bool IsPotentiallyAnimatingProperty(TargetProperty::Type target_property,
                                       ElementListType list_type) const;
 
+  // Returns true if there is an animation that is either currently animating
+  // a transform related property (TRANSLATE, ROTATE, SCALE, TRANSFORM) or
+  // scheduled to animate this property in the future, and that affects the
+  // given tree type.
+  bool IsPotentiallyAnimatingTransform(ElementListType list_type) const;
+
   // Returns true if there is an animation that is currently animating the given
   // property and that affects the given tree type.
   bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property,
                                     ElementListType list_type) const;
 
+  // Returns true if there is an animation that is currently animating a
+  // transform related property (TRANSLATE, ROTOTATE, SCALE, TRANSFROM) and that
+  // affects the given tree type.
+  bool IsCurrentlyAnimatingTransformRelatedProperty(
+      ElementListType list_type) const;
+
   bool has_element_in_active_list() const {
     return has_element_in_active_list_;
   }
@@ -198,9 +210,6 @@
   void OnCustomPropertyAnimated(PaintWorkletInput::PropertyValue property_value,
                                 KeyframeModel* keyframe_model,
                                 int target_property_id);
-  void OnTransformAnimated(ElementListType list_type,
-                           const gfx::Transform& transform,
-                           gfx::KeyframeModel* keyframe_model);
   void OnScrollOffsetAnimated(ElementListType list_type,
                               const gfx::ScrollOffset& scroll_offset,
                               gfx::KeyframeModel* keyframe_model);
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc
index e151dc3..0e44243 100644
--- a/cc/animation/element_animations_unittest.cc
+++ b/cc/animation/element_animations_unittest.cc
@@ -5,6 +5,7 @@
 #include "cc/animation/element_animations.h"
 
 #include <limits>
+#include <memory>
 #include <utility>
 
 #include "base/memory/ptr_util.h"
@@ -15,10 +16,12 @@
 #include "cc/animation/animation_id_provider.h"
 #include "cc/animation/animation_timeline.h"
 #include "cc/animation/keyframe_effect.h"
+#include "cc/animation/scoped_compound_transform_resolver.h"
 #include "cc/animation/scroll_offset_animation_curve.h"
 #include "cc/animation/scroll_offset_animation_curve_factory.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/animation_timelines_test_common.h"
+#include "cc/trees/property_tree.h"
 #include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
 #include "ui/gfx/geometry/box_f.h"
 #include "ui/gfx/transform_operations.h"
@@ -54,6 +57,12 @@
     return base::WrapUnique(
         static_cast<AnimationEvents*>(mutator_events.release()));
   }
+
+  void TickAnimations(TimeTicks time) {
+    ScrollTree scroll_tree;
+    host_->TickAnimations(time, scroll_tree, true);
+    host_impl_->TickAnimations(time, scroll_tree, true);
+  }
 };
 
 // See animation_unittest.cc for integration with Animation.
@@ -470,7 +479,7 @@
                 ->start_time());
 }
 
-// Tests that animationss activate and deactivate as expected.
+// Tests that animations activate and deactivate as expected.
 TEST_F(ElementAnimationsTest, Activation) {
   CreateTestLayer(true, false);
   AttachTimelineAnimationLayer();
@@ -1500,17 +1509,19 @@
                               new FakeFloatTransition(1.0, 0.f, 1.f)),
                           2, TargetProperty::OPACITY));
 
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, events.get());
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
+
   // The float animation should have started at time 1 and should be done.
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_->UpdateState(true, events.get());
   EXPECT_EQ(1.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
   EXPECT_FALSE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -1538,14 +1549,14 @@
                           2, TargetProperty::OPACITY));
 
   // Animations with id 1 should both start now.
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, events.get());
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
   // The opacity animation should have finished at time 1, but the group
   // of animations with id 1 don't finish until time 2 because of the length
   // of the transform animation.
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_->UpdateState(true, events.get());
   // Should not have started the float transition yet.
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -1553,7 +1564,7 @@
 
   // The second opacity animation should start at time 2 and should be done by
   // time 3.
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   animation_->UpdateState(true, events.get());
   EXPECT_EQ(0.5f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
   EXPECT_FALSE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -1716,11 +1727,11 @@
           new FakeFloatTransition(1.0, 1.f, 0.75f)),
       3, 2, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)));
 
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, events.get());
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, events.get());
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.5f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
@@ -1731,11 +1742,11 @@
       ->GetKeyframeModelById(keyframe_model_id)
       ->SetRunState(KeyframeModel::ABORTED,
                     kInitialTickTime + TimeDelta::FromMilliseconds(1000));
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, events.get());
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(1.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_->UpdateState(true, events.get());
   EXPECT_TRUE(!animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.75f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
@@ -1787,7 +1798,7 @@
   first_keyframe_model->set_is_controlling_instance_for_test(true);
   animation_->AddKeyframeModel(std::move(first_keyframe_model));
 
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, events.get());
 
   std::unique_ptr<KeyframeModel> second_keyframe_model(
@@ -1798,9 +1809,9 @@
   animation_->AddKeyframeModel(std::move(second_keyframe_model));
 
   // Animate but don't UpdateState.
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
 
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   events = CreateEventsForTesting();
   animation_->UpdateState(true, events.get());
 
@@ -1812,7 +1823,7 @@
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
 
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(3000));
   animation_->UpdateState(true, events.get());
 
   // The float tranisition should now be done.
@@ -1921,9 +1932,9 @@
           new FakeFloatTransition(1.0, 0.f, 1.f)),
       5, 5, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)));
 
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, nullptr);
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, nullptr);
 
   EXPECT_EQ(
@@ -2159,7 +2170,7 @@
   second_keyframe_model->set_is_controlling_instance_for_test(true);
   animation_impl_->AddKeyframeModel(std::move(second_keyframe_model));
 
-  animation_impl_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
   // Both animations should have started.
@@ -2168,7 +2179,7 @@
   EXPECT_EQ(AnimationEvent::STARTED, events->events_[1].type);
 
   events = CreateEventsForTesting();
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_impl_->UpdateState(true, events.get());
 
   // The opacity animation should be finished, but should not have generated
@@ -2181,7 +2192,7 @@
       KeyframeModel::RUNNING,
       animation_impl_->keyframe_effect()->GetKeyframeModelById(1)->run_state());
 
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
   // Both animations should have generated FINISHED events.
@@ -2214,7 +2225,7 @@
   second_keyframe_model->set_is_controlling_instance_for_test(true);
   animation_impl_->AddKeyframeModel(std::move(second_keyframe_model));
 
-  animation_impl_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
   // Both animations should have started.
@@ -2226,7 +2237,7 @@
                                                    false);
 
   events = CreateEventsForTesting();
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_impl_->UpdateState(true, events.get());
 
   // We should have exactly 2 events: a FINISHED event for the tranform
@@ -2703,14 +2714,14 @@
   EXPECT_TRUE(client_impl_.GetTransformIsCurrentlyAnimating(
       element_id_, ElementListType::ACTIVE));
 
-  animation_impl_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
   animation_->DispatchAndDelegateAnimationEvent(events->events_[0]);
   events->events_.clear();
 
   // Finish the animation.
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, nullptr);
   EXPECT_FALSE(client_.GetHasPotentialTransformAnimation(
       element_id_, ElementListType::ACTIVE));
@@ -2730,7 +2741,7 @@
   EXPECT_TRUE(client_impl_.GetTransformIsCurrentlyAnimating(
       element_id_, ElementListType::ACTIVE));
 
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_impl_->UpdateState(true, events.get());
   EXPECT_FALSE(client_impl_.GetHasPotentialTransformAnimation(
       element_id_, ElementListType::PENDING));
@@ -2776,7 +2787,7 @@
   EXPECT_TRUE(client_impl_.GetTransformIsCurrentlyAnimating(
       element_id_, ElementListType::ACTIVE));
 
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
   animation_->DispatchAndDelegateAnimationEvent(events->events_[0]);
@@ -2829,7 +2840,7 @@
   EXPECT_TRUE(client_impl_.GetTransformIsCurrentlyAnimating(
       element_id_, ElementListType::ACTIVE));
 
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
   animation_->DispatchAndDelegateAnimationEvent(events->events_[0]);
@@ -2846,7 +2857,7 @@
   EXPECT_FALSE(client_impl_.GetTransformIsCurrentlyAnimating(
       element_id_, ElementListType::ACTIVE));
 
-  animation_impl_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(4000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(4000));
   animation_impl_->UpdateState(true, events.get());
 
   animation_->DispatchAndDelegateAnimationEvent(events->events_[0]);
@@ -3946,9 +3957,9 @@
       2, 2, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)));
 
   // Finish the first keyframe model.
-  animation_->Tick(kInitialTickTime);
+  TickAnimations(kInitialTickTime);
   animation_->UpdateState(true, nullptr);
-  animation_->Tick(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
+  TickAnimations(kInitialTickTime + TimeDelta::FromMilliseconds(1000));
   animation_->UpdateState(true, nullptr);
 
   EXPECT_EQ(
diff --git a/cc/animation/keyframe_effect.cc b/cc/animation/keyframe_effect.cc
index 99beca1..4f59e98 100644
--- a/cc/animation/keyframe_effect.cc
+++ b/cc/animation/keyframe_effect.cc
@@ -458,6 +458,10 @@
 bool KeyframeEffect::IsPotentiallyAnimatingProperty(
     TargetProperty::Type target_property,
     ElementListType list_type) const {
+  // For transform related properties, call
+  // IsPotentiallyAnimatingTransformRelatedProperty instead.
+  DCHECK(target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+         target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY);
   for (const auto& keyframe_model : keyframe_models()) {
     if (!keyframe_model->is_finished() &&
         keyframe_model->TargetProperty() == target_property) {
@@ -473,9 +477,36 @@
   return false;
 }
 
+bool KeyframeEffect::IsPotentiallyAnimatingTransformRelatedProperty(
+    ElementListType list_type) const {
+  for (const auto& keyframe_model : keyframe_models()) {
+    if (keyframe_model->is_finished())
+      continue;
+
+    int target_property = keyframe_model->TargetProperty();
+
+    if (target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+        target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY)
+      continue;
+
+    auto* cc_keyframe_model =
+        KeyframeModel::ToCcKeyframeModel(keyframe_model.get());
+    if ((list_type == ElementListType::ACTIVE &&
+         cc_keyframe_model->affects_active_elements()) ||
+        (list_type == ElementListType::PENDING &&
+         cc_keyframe_model->affects_pending_elements()))
+      return true;
+  }
+  return false;
+}
+
 bool KeyframeEffect::IsCurrentlyAnimatingProperty(
     TargetProperty::Type target_property,
     ElementListType list_type) const {
+  // For transform related properties, call
+  // IsCurrentlyAnimatingTransformRelatedProperty instead.
+  DCHECK(target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+         target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY);
   for (const auto& keyframe_model : keyframe_models()) {
     auto* cc_keyframe_model =
         KeyframeModel::ToCcKeyframeModel(keyframe_model.get());
@@ -493,6 +524,30 @@
   return false;
 }
 
+bool KeyframeEffect::IsCurrentlyAnimatingTransformRelatedProperty(
+    ElementListType list_type) const {
+  for (const auto& keyframe_model : keyframe_models()) {
+    auto* cc_keyframe_model =
+        KeyframeModel::ToCcKeyframeModel(keyframe_model.get());
+    if (keyframe_model->is_finished() ||
+        !cc_keyframe_model->InEffect(
+            last_tick_time_.value_or(base::TimeTicks())))
+      continue;
+
+    int target_property = keyframe_model->TargetProperty();
+    if (target_property < TargetProperty::Type::FIRST_TRANSFORM_PROPERTY ||
+        target_property > TargetProperty::Type::LAST_TRANSFORM_PROPERTY)
+      continue;
+
+    if ((list_type == ElementListType::ACTIVE &&
+         cc_keyframe_model->affects_active_elements()) ||
+        (list_type == ElementListType::PENDING &&
+         cc_keyframe_model->affects_pending_elements()))
+      return true;
+  }
+  return false;
+}
+
 void KeyframeEffect::GetPropertyAnimationState(
     PropertyAnimationState* pending_state,
     PropertyAnimationState* active_state) const {
diff --git a/cc/animation/keyframe_effect.h b/cc/animation/keyframe_effect.h
index f0a26d7..9139f2e 100644
--- a/cc/animation/keyframe_effect.h
+++ b/cc/animation/keyframe_effect.h
@@ -126,11 +126,24 @@
   bool IsPotentiallyAnimatingProperty(TargetProperty::Type target_property,
                                       ElementListType list_type) const;
 
+  // Returns true if there is a keyframe_model that is either currently
+  // animating a transform related property (TRANSLATE, ROTATE, SCALE,
+  // TRANSFORM) or scheduled to animate such a property in the future, and that
+  // affects the given tree type.
+  bool IsPotentiallyAnimatingTransformRelatedProperty(
+      ElementListType list_type) const;
+
   // Returns true if there is a keyframe_model that is currently animating the
   // given property and that affects the given tree type.
   bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property,
                                     ElementListType list_type) const;
 
+  // Returns true if there is a keyframe_model that is currently animating a
+  // transform related property (TRANSLATE, ROTATE, SCALE, TRANSFROM) and that
+  // affects the given tree type.
+  bool IsCurrentlyAnimatingTransformRelatedProperty(
+      ElementListType list_type) const;
+
   void GetPropertyAnimationState(PropertyAnimationState* pending_state,
                                  PropertyAnimationState* active_state) const;
 
diff --git a/cc/animation/keyframe_model_unittest.cc b/cc/animation/keyframe_model_unittest.cc
index 1e01ad2a..c186a1fc 100644
--- a/cc/animation/keyframe_model_unittest.cc
+++ b/cc/animation/keyframe_model_unittest.cc
@@ -1387,10 +1387,10 @@
       std::make_unique<FakeFloatAnimationCurve>(15), 42, 73,
       KeyframeModel::TargetPropertyId(TargetProperty::OPACITY));
   EXPECT_EQ(base::StringPrintf(
-                "KeyframeModel{id=%d, group=73, target_property_type=1, "
+                "KeyframeModel{id=%d, group=73, target_property_type=%d, "
                 "custom_property_name=, native_property_type=1, "
                 "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}",
-                keyframe_model->id()),
+                keyframe_model->id(), TargetProperty::OPACITY),
             keyframe_model->ToString());
 }
 
diff --git a/cc/animation/scoped_compound_transform_resolver.cc b/cc/animation/scoped_compound_transform_resolver.cc
new file mode 100644
index 0000000..3c9eac32
--- /dev/null
+++ b/cc/animation/scoped_compound_transform_resolver.cc
@@ -0,0 +1,67 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/animation/scoped_compound_transform_resolver.h"
+
+#include "base/notreached.h"
+
+namespace cc {
+
+ScopedCompoundTransformResolver::ScopedCompoundTransformResolver(
+    AnimationHost* animation_host)
+    : animation_host_(animation_host) {
+  DCHECK(animation_host_);
+  animation_host_->set_compound_transform_resolver(this);
+}
+
+ScopedCompoundTransformResolver::~ScopedCompoundTransformResolver() {
+  for (auto& it : transform_map_) {
+    const ElementId element_id = it.first;
+    const auto& compound_transform = it.second;
+    ApplyCompoundTransforms(element_id, ElementListType::ACTIVE,
+                            compound_transform.active_transforms);
+    ApplyCompoundTransforms(element_id, ElementListType::PENDING,
+                            compound_transform.pending_transforms);
+  }
+  animation_host_->set_compound_transform_resolver(nullptr);
+}
+
+void ScopedCompoundTransformResolver::ApplyCompoundTransforms(
+    ElementId element_id,
+    ElementListType list_type,
+    const gfx::Transform* transforms) {
+  DCHECK(animation_host_);
+  DCHECK(animation_host_->mutator_host_client());
+
+  gfx::Transform result;
+  for (size_t i = 0; i < kNumTransforms; i++) {
+    const gfx::Transform& transform = transforms[i];
+    if (!transform.IsIdentity())
+      result.PreconcatTransform(transform);
+  }
+  if (!result.IsIdentity()) {
+    animation_host_->mutator_host_client()->SetElementTransformMutated(
+        element_id, list_type, result);
+  }
+}
+
+void ScopedCompoundTransformResolver::AddTransform(
+    ElementId element_id,
+    const gfx::Transform& transform,
+    TargetProperty::Type target_property_type,
+    bool apply_active,
+    bool apply_pending) {
+  DCHECK(target_property_type >=
+         TargetProperty::Type::FIRST_TRANSFORM_PROPERTY);
+  DCHECK(target_property_type <= TargetProperty::Type::LAST_TRANSFORM_PROPERTY);
+  size_t index =
+      target_property_type - TargetProperty::Type::FIRST_TRANSFORM_PROPERTY;
+  CompoundTransform& compound_transform = transform_map_[element_id];
+  if (apply_active)
+    compound_transform.active_transforms[index] = transform;
+  if (apply_pending)
+    compound_transform.pending_transforms[index] = transform;
+}
+
+}  // namespace cc
diff --git a/cc/animation/scoped_compound_transform_resolver.h b/cc/animation/scoped_compound_transform_resolver.h
new file mode 100644
index 0000000..2e6968d
--- /dev/null
+++ b/cc/animation/scoped_compound_transform_resolver.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_ANIMATION_SCOPED_COMPOUND_TRANSFORM_RESOLVER_H_
+#define CC_ANIMATION_SCOPED_COMPOUND_TRANSFORM_RESOLVER_H_
+
+#include <map>
+
+#include "cc/animation/animation_host.h"
+#include "cc/trees/target_property.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+
+class CompoundTransform;
+
+class CC_ANIMATION_EXPORT ScopedCompoundTransformResolver {
+ public:
+  explicit ScopedCompoundTransformResolver(AnimationHost* host);
+  ~ScopedCompoundTransformResolver();
+  ScopedCompoundTransformResolver(const ScopedCompoundTransformResolver&) =
+      delete;
+  ScopedCompoundTransformResolver& operator=(
+      const ScopedCompoundTransformResolver&) = delete;
+
+  void AddTransform(ElementId element_id,
+                    const gfx::Transform& transform,
+                    TargetProperty::Type target_property_type,
+                    bool apply_active,
+                    bool apply_pending);
+
+ private:
+  void ApplyCompoundTransforms(ElementId element_id,
+                               ElementListType list_type,
+                               const gfx::Transform* transforms);
+
+  static constexpr size_t kNumTransforms =
+      TargetProperty::LAST_TRANSFORM_PROPERTY -
+      TargetProperty::FIRST_TRANSFORM_PROPERTY + 1;
+
+  struct CompoundTransform {
+    gfx::Transform active_transforms[kNumTransforms];
+    gfx::Transform pending_transforms[kNumTransforms];
+  };
+
+  AnimationHost* animation_host_;
+  std::map<ElementId, CompoundTransform> transform_map_;
+};
+
+}  // namespace cc
+
+#endif  //  CC_ANIMATION_SCOPED_COMPOUND_TRANSFORM_RESOLVER_H_
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc
index b1f5df0..0a73b51 100644
--- a/cc/paint/paint_flags.cc
+++ b/cc/paint/paint_flags.cc
@@ -142,7 +142,6 @@
   paint.setStrokeCap(static_cast<SkPaint::Cap>(getStrokeCap()));
   paint.setStrokeJoin(static_cast<SkPaint::Join>(getStrokeJoin()));
   paint.setStyle(static_cast<SkPaint::Style>(getStyle()));
-  paint.setFilterQuality(getFilterQuality());
   return paint;
 }
 
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc
index 768e6a5..6ca20dd 100644
--- a/cc/test/layer_tree_json_parser.cc
+++ b/cc/test/layer_tree_json_parser.cc
@@ -24,120 +24,175 @@
 
 scoped_refptr<Layer> ParseTreeFromValue(const base::Value& val,
                                         ContentLayerClient* content_client) {
-  const base::DictionaryValue* dict;
-  bool success = true;
-  success &= val.GetAsDictionary(&dict);
-  std::string layer_type;
-  success &= dict->GetString("LayerType", &layer_type);
-  const base::ListValue* list;
-  success &= dict->GetList("Bounds", &list);
-  int width, height;
-  success &= list->GetInteger(0, &width);
-  success &= list->GetInteger(1, &height);
+  if (!val.is_dict())
+    return nullptr;
 
-  bool draws_content;
-  success &= dict->GetBoolean("DrawsContent", &draws_content);
+  const std::string* layer_type = val.FindStringKey("LayerType");
+  if (!layer_type)
+    return nullptr;
 
-  bool hit_testable;
+  const base::Value* bounds_list_value = val.FindListKey("Bounds");
+  if (!bounds_list_value)
+    return nullptr;
+  base::Value::ConstListView bounds_list = bounds_list_value->GetList();
+  if (bounds_list.size() < 2)
+    return nullptr;
+
+  absl::optional<int> width = bounds_list[0].GetIfInt();
+  absl::optional<int> height = bounds_list[1].GetIfInt();
+  if (!width.has_value() || !height.has_value())
+    return nullptr;
+
+  absl::optional<bool> draws_content = val.FindBoolKey("DrawsContent");
+  if (!draws_content.has_value())
+    return nullptr;
+
+  absl::optional<bool> hit_testable = val.FindBoolKey("HitTestable");
   // If we cannot load hit_testable, we may try loading the old version, since
   // we do not record |hit_testable_without_draws_content| in the past, we use
   // |draws_content| as the value of |hit_testable|.
-  if (!dict->GetBoolean("HitTestable", &hit_testable)) {
-    hit_testable = draws_content;
+  if (!hit_testable.has_value()) {
+    hit_testable = *draws_content;
   }
 
   scoped_refptr<Layer> new_layer;
-  if (layer_type == "SolidColorLayer") {
+  if (*layer_type == "SolidColorLayer") {
     new_layer = SolidColorLayer::Create();
-  } else if (layer_type == "NinePatchLayer") {
-    success &= dict->GetList("ImageAperture", &list);
-    int aperture_x, aperture_y, aperture_width, aperture_height;
-    success &= list->GetInteger(0, &aperture_x);
-    success &= list->GetInteger(1, &aperture_y);
-    success &= list->GetInteger(2, &aperture_width);
-    success &= list->GetInteger(3, &aperture_height);
+  } else if (*layer_type == "NinePatchLayer") {
+    const base::Value* aperture_list_value = val.FindListKey("ImageAperture");
+    if (!aperture_list_value)
+      return nullptr;
+    base::Value::ConstListView aperture_list = aperture_list_value->GetList();
+    if (aperture_list.size() < 4)
+      return nullptr;
 
-    const base::ListValue* bounds;
-    success &= dict->GetList("ImageBounds", &bounds);
-    double image_width, image_height;
-    success &= bounds->GetDouble(0, &image_width);
-    success &= bounds->GetDouble(1, &image_height);
+    absl::optional<int> aperture_x = aperture_list[0].GetIfInt();
+    absl::optional<int> aperture_y = aperture_list[1].GetIfInt();
+    absl::optional<int> aperture_width = aperture_list[2].GetIfInt();
+    absl::optional<int> aperture_height = aperture_list[3].GetIfInt();
+    if (!(aperture_x.has_value() && aperture_y.has_value() &&
+          aperture_width.has_value() && aperture_height.has_value()))
+      return nullptr;
 
-    success &= dict->GetList("Border", &list);
-    int border_x, border_y, border_width, border_height;
-    success &= list->GetInteger(0, &border_x);
-    success &= list->GetInteger(1, &border_y);
-    success &= list->GetInteger(2, &border_width);
-    success &= list->GetInteger(3, &border_height);
+    const base::Value* image_bounds_list_value = val.FindListKey("ImageBounds");
+    if (!image_bounds_list_value)
+      return nullptr;
+    base::Value::ConstListView image_bounds_list =
+        image_bounds_list_value->GetList();
+    if (image_bounds_list.size() < 2)
+      return nullptr;
 
-    bool fill_center;
-    success &= dict->GetBoolean("FillCenter", &fill_center);
+    absl::optional<double> image_width = image_bounds_list[0].GetIfDouble();
+    absl::optional<double> image_height = image_bounds_list[1].GetIfDouble();
+    if (!(image_width.has_value() && image_height.has_value()))
+      return nullptr;
+
+    const base::Value* border_list_value = val.FindListKey("Border");
+    if (!border_list_value)
+      return nullptr;
+    base::Value::ConstListView border_list = border_list_value->GetList();
+    if (border_list.size() < 4)
+      return nullptr;
+
+    absl::optional<int> border_x = border_list[0].GetIfInt();
+    absl::optional<int> border_y = border_list[1].GetIfInt();
+    absl::optional<int> border_width = border_list[2].GetIfInt();
+    absl::optional<int> border_height = border_list[3].GetIfInt();
+
+    if (!(border_x.has_value() && border_y.has_value() &&
+          border_width.has_value() && border_height.has_value()))
+      return nullptr;
+
+    absl::optional<bool> fill_center = val.FindBoolKey("FillCenter");
+    if (!fill_center.has_value())
+      return nullptr;
 
     scoped_refptr<NinePatchLayer> nine_patch_layer = NinePatchLayer::Create();
 
     SkBitmap bitmap;
-    bitmap.allocN32Pixels(image_width, image_height);
+    bitmap.allocN32Pixels(*image_width, *image_height);
     bitmap.setImmutable();
     nine_patch_layer->SetBitmap(bitmap);
     nine_patch_layer->SetAperture(
-        gfx::Rect(aperture_x, aperture_y, aperture_width, aperture_height));
+        gfx::Rect(*aperture_x, *aperture_y, *aperture_width, *aperture_height));
     nine_patch_layer->SetBorder(
-        gfx::Rect(border_x, border_y, border_width, border_height));
-    nine_patch_layer->SetFillCenter(fill_center);
+        gfx::Rect(*border_x, *border_y, *border_width, *border_height));
+    nine_patch_layer->SetFillCenter(*fill_center);
 
     new_layer = nine_patch_layer;
-  } else if (layer_type == "TextureLayer") {
+  } else if (*layer_type == "TextureLayer") {
     new_layer = TextureLayer::CreateForMailbox(nullptr);
-  } else if (layer_type == "PictureLayer") {
+  } else if (*layer_type == "PictureLayer") {
     new_layer = PictureLayer::Create(content_client);
   } else {  // Type "Layer" or "unknown"
     new_layer = Layer::Create();
   }
-  new_layer->SetBounds(gfx::Size(width, height));
-  new_layer->SetIsDrawable(draws_content);
-  new_layer->SetHitTestable(hit_testable);
+  new_layer->SetBounds(gfx::Size(*width, *height));
+  new_layer->SetIsDrawable(*draws_content);
+  new_layer->SetHitTestable(*hit_testable);
 
-  double opacity;
-  if (dict->GetDouble("Opacity", &opacity))
-    new_layer->SetOpacity(opacity);
+  absl::optional<double> opacity = val.FindDoubleKey("Opacity");
+  if (opacity.has_value())
+    new_layer->SetOpacity(*opacity);
 
-  bool contents_opaque;
-  if (dict->GetBoolean("ContentsOpaque", &contents_opaque))
-    new_layer->SetContentsOpaque(contents_opaque);
+  absl::optional<bool> contents_opaque = val.FindBoolKey("ContentsOpaque");
+  if (contents_opaque.has_value())
+    new_layer->SetContentsOpaque(*contents_opaque);
 
-  if (dict->HasKey("TouchRegion")) {
-    success &= dict->GetList("TouchRegion", &list);
+  const base::Value* touch_region_list_value = val.FindListKey("TouchRegion");
+
+  if (touch_region_list_value) {
+    base::Value::ConstListView touch_region_list =
+        touch_region_list_value->GetList();
+
     TouchActionRegion touch_action_region;
-    for (size_t i = 0; i < list->GetSize(); ) {
-      int rect_x, rect_y, rect_width, rect_height;
-      success &= list->GetInteger(i++, &rect_x);
-      success &= list->GetInteger(i++, &rect_y);
-      success &= list->GetInteger(i++, &rect_width);
-      success &= list->GetInteger(i++, &rect_height);
+    for (size_t i = 0; i + 3 < touch_region_list.size(); i += 4) {
+      absl::optional<int> rect_x = touch_region_list[i + 0].GetIfInt();
+      absl::optional<int> rect_y = touch_region_list[i + 1].GetIfInt();
+      absl::optional<int> rect_width = touch_region_list[i + 2].GetIfInt();
+      absl::optional<int> rect_height = touch_region_list[i + 3].GetIfInt();
+
+      if (!(rect_x.has_value() && rect_y.has_value() &&
+            rect_width.has_value() && rect_height.has_value()))
+        return nullptr;
+
       touch_action_region.Union(
           TouchAction::kNone,
-          gfx::Rect(rect_x, rect_y, rect_width, rect_height));
+          gfx::Rect(*rect_x, *rect_y, *rect_width, *rect_height));
     }
     new_layer->SetTouchActionRegion(std::move(touch_action_region));
   }
 
-  success &= dict->GetList("Transform", &list);
+  const base::Value* transform_list_value = val.FindListKey("Transform");
+  if (!transform_list_value)
+    return nullptr;
+  base::Value::ConstListView transform_list = transform_list_value->GetList();
+  if (transform_list.size() < 16)
+    return nullptr;
+
   double transform[16];
-  for (int i = 0; i < 16; ++i)
-    success &= list->GetDouble(i, &transform[i]);
+  for (int i = 0; i < 16; ++i) {
+    // GetDouble can implicitly convert from either double or int; however, it's
+    // not clear if "is_double" is sufficient for this check. Given that int is
+    // also a valid type that can be gotten, check it here.
+    if (!(transform_list[i].is_double() || transform_list[i].is_int())) {
+      return nullptr;
+    }
+
+    transform[i] = transform_list[i].GetDouble();
+  }
 
   gfx::Transform layer_transform;
   layer_transform.matrix().setColMajord(transform);
   new_layer->SetTransform(layer_transform);
 
-  success &= dict->GetList("Children", &list);
-  for (const auto& value : list->GetList()) {
+  const base::Value* child_list_value = val.FindListKey("Children");
+  if (!child_list_value)
+    return nullptr;
+  for (const auto& value : child_list_value->GetList()) {
     new_layer->AddChild(ParseTreeFromValue(value, content_client));
   }
 
-  if (!success)
-    return nullptr;
-
   return new_layer;
 }
 
@@ -145,8 +200,7 @@
 
 scoped_refptr<Layer> ParseTreeFromJson(std::string json,
                                        ContentLayerClient* content_client) {
-  std::unique_ptr<base::Value> val = base::test::ParseJsonDeprecated(json);
-  return ParseTreeFromValue(*val, content_client);
+  return ParseTreeFromValue(base::test::ParseJson(json), content_client);
 }
 
 }  // namespace cc
diff --git a/cc/trees/de_jelly_state.h b/cc/trees/de_jelly_state.h
index 58a865b..b62d1b0 100644
--- a/cc/trees/de_jelly_state.h
+++ b/cc/trees/de_jelly_state.h
@@ -7,7 +7,6 @@
 
 #include <map>
 
-#include "base/no_destructor.h"
 #include "cc/cc_export.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/transform.h"
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 631bcab..19f07602 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -764,7 +764,7 @@
       // ARM Windows, macOS, and Fuchsia has some pixels difference
       // Affected tests: RotatedClippedCircle, RotatedClippedCircleUnderflow
       // crbug.com/1030244, crbug.com/1048249, crbug.com/1128443
-      percentage_pixels_error = 6.1f;
+      percentage_pixels_error = 6.2f;
       average_error_allowed_in_bad_pixels = 5.f;
       large_error_allowed = 20;
 #else
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 91436f3..5a9b978 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -1876,6 +1876,9 @@
     const ElementId element_id = it->second;
     switch (property) {
       case TargetProperty::TRANSFORM:
+      case TargetProperty::TRANSLATE:
+      case TargetProperty::SCALE:
+      case TargetProperty::ROTATE:
         if (TransformNode* transform_node =
                 transform_tree.FindNodeFromElementId(element_id)) {
           if (mask.currently_running[property])
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 99083b3..89282e4 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -225,8 +225,15 @@
   // in the timing of animation state updates can mean that an animation that's
   // in the Finished state at tree-building time on the main thread is still in
   // the Running state right after commit on the compositor thread.
-  const bool has_any_transform_animation = HasAnyAnimationTargetingProperty(
-      mutator_host_, layer, TargetProperty::TRANSFORM);
+  const bool has_any_transform_animation =
+      HasAnyAnimationTargetingProperty(mutator_host_, layer,
+                                       TargetProperty::TRANSFORM) ||
+      HasAnyAnimationTargetingProperty(mutator_host_, layer,
+                                       TargetProperty::TRANSLATE) ||
+      HasAnyAnimationTargetingProperty(mutator_host_, layer,
+                                       TargetProperty::ROTATE) ||
+      HasAnyAnimationTargetingProperty(mutator_host_, layer,
+                                       TargetProperty::SCALE);
 
   const bool has_surface = created_render_surface;
 
diff --git a/cc/trees/target_property.h b/cc/trees/target_property.h
index a60b371..390ba3ae 100644
--- a/cc/trees/target_property.h
+++ b/cc/trees/target_property.h
@@ -13,7 +13,14 @@
 
 // Must be zero-based as this will be stored in a bitset.
 enum Type {
-  TRANSFORM = 0,
+  // Transform related properties must be sequentiallyenumerated in the same
+  // order in which they should be applied.
+  TRANSLATE = 0,
+  FIRST_TRANSFORM_PROPERTY = TRANSLATE,
+  ROTATE,
+  SCALE,
+  TRANSFORM,
+  LAST_TRANSFORM_PROPERTY = TRANSFORM,
   OPACITY,
   FILTER,
   SCROLL_OFFSET,
@@ -25,7 +32,7 @@
   NATIVE_PROPERTY,
   BACKDROP_FILTER,
   // These sentinels must be last
-  FIRST_TARGET_PROPERTY = TRANSFORM,
+  FIRST_TARGET_PROPERTY = TRANSLATE,
   LAST_TARGET_PROPERTY = BACKDROP_FILTER
 };
 
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 93dc43ba..24c6291 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -760,7 +760,6 @@
   "java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java",
   "java/src/org/chromium/chrome/browser/metrics/VariationsSession.java",
   "java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java",
-  "java/src/org/chromium/chrome/browser/metrics/WebApkUma.java",
   "java/src/org/chromium/chrome/browser/metrics/WebApkUninstallUmaTracker.java",
   "java/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenter.java",
   "java/src/org/chromium/chrome/browser/modaldialog/TabModalLifetimeHandler.java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index 7dceb536..065ea34 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -194,6 +194,7 @@
      * @param tabCreatorManager Manages {@link Tab} creation.
      * @param menuOrKeyboardActionController allows access to menu or keyboard actions.
      * @param multiWindowModeStateDispatcher Gives access to the multi window mode state.
+     * @param jankTracker Measures jank while feed or tab switcher are visible.
      */
     public StartSurfaceCoordinator(@NonNull Activity activity,
             @NonNull ScrimCoordinator scrimCoordinator,
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
index 14deb613..f383b32 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
@@ -37,8 +37,8 @@
 /** StartSurfaceDelegate. */
 public class StartSurfaceDelegate {
     public static Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, StartSurface startSurface) {
-        return new StartSurfaceLayout(context, updateHost, renderHost, startSurface);
+            LayoutRenderHost renderHost, StartSurface startSurface, JankTracker jankTracker) {
+        return new StartSurfaceLayout(context, updateHost, renderHost, startSurface, jankTracker);
     }
 
     /** {@see StartSurfaceCoordinator} */
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
index 3da930f..4ec20aa0 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -18,6 +18,8 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
+import org.chromium.base.jank_tracker.JankScenario;
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
@@ -67,6 +69,7 @@
 
     private TabListSceneLayer mSceneLayer;
     private final StartSurface mStartSurface;
+    private final JankTracker mJankTracker;
     private final StartSurface.Controller mController;
     private final StartSurface.OverviewModeObserver mStartSurfaceObserver;
     // Always use getGridTabListDelegate() instead to make sure it's not null.
@@ -99,13 +102,14 @@
     private PerfListener mPerfListenerForTesting;
 
     public StartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, StartSurface startSurface) {
+            LayoutRenderHost renderHost, StartSurface startSurface, JankTracker jankTracker) {
         super(context, updateHost, renderHost);
         mDummyLayoutTab = createLayoutTab(Tab.INVALID_TAB_ID, false, false, false);
         mDummyLayoutTab.setShowToolbar(true);
         mStartSurface = startSurface;
         mStartSurface.setOnTabSelectingListener(this::onTabSelecting);
         mController = mStartSurface.getController();
+        mJankTracker = jankTracker;
 
         mStartSurfaceObserver = new StartSurface.OverviewModeObserver() {
             @Override
@@ -200,6 +204,12 @@
     public void show(long time, boolean animate) {
         super.show(time, animate);
 
+        // When shown on StartSurface jank is tracked under JankScenario.START_SURFACE_TAB_SWITCHER
+        // and it's started/stopped on StartSurfaceMediator.
+        if (!StartSurfaceConfiguration.isStartSurfaceEnabled()) {
+            mJankTracker.startTrackingScenario(JankScenario.TAB_SWITCHER);
+        }
+
         // Lazy initialization if needed.
         mStartSurface.initialize();
 
@@ -295,6 +305,11 @@
         super.doneHiding();
         mStartSurface.onHide();
         RecordUserAction.record("MobileExitStackView");
+        // When shown on StartSurface jank is tracked under JankScenario.START_SURFACE_TAB_SWITCHER
+        // and it's started/stopped on StartSurfaceMediator.
+        if (!StartSurfaceConfiguration.isStartSurfaceEnabled()) {
+            mJankTracker.finishTrackingScenario(JankScenario.TAB_SWITCHER);
+        }
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
index 92f27e8..e9a40ad 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
@@ -209,7 +209,7 @@
      * @return The {@link StartSurfaceLayout}.
      */
     Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, StartSurface startSurface);
+            LayoutRenderHost renderHost, StartSurface startSurface, JankTracker jankTracker);
 
     /**
      * Create the {@link StartSurface}
@@ -238,6 +238,7 @@
      * @param tabCreatorManger Manages creation of tabs.
      * @param menuOrKeyboardActionController allows access to menu or keyboard actions.
      * @param multiWindowModeStateDispatcher Gives access to the multi window mode state.
+     * @param jankTracker Measures jank while tab switcher is visible.
      * @return the {@link StartSurface}
      */
     StartSurface createStartSurface(@NonNull Activity activity,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
index b003376..9b5ddc4 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
@@ -154,9 +154,9 @@
 
     @Override
     public Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, StartSurface startSurface) {
+            LayoutRenderHost renderHost, StartSurface startSurface, JankTracker jankTracker) {
         return StartSurfaceDelegate.createStartSurfaceLayout(
-                context, updateHost, renderHost, startSurface);
+                context, updateHost, renderHost, startSurface, jankTracker);
     }
 
     @Override
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index 474ee9f..5c69059b 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -585,8 +585,7 @@
                 String accessibilityRefreshString =
                         mActivity.getResources().getString(R.string.accessibility_swipe_refresh);
                 swipeRefreshLayout.announceForAccessibility(accessibilityRefreshString);
-                mStream.triggerRefresh(
-                        (Boolean success) -> { swipeRefreshLayout.setRefreshing(false); });
+                mStream.triggerRefresh((Boolean v) -> { swipeRefreshLayout.setRefreshing(false); });
                 RecordUserAction.record("MobilePullGestureReloadNTP");
             }
         });
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java
index bc7af4e..4567088c 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.xsurface.ImageFetchClient;
 import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache;
 import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider;
+import org.chromium.components.version_info.VersionConstants;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
 /**
@@ -126,4 +127,14 @@
     public String getGoogleApiKey() {
         return GoogleAPIKeys.GOOGLE_API_KEY;
     }
+
+    @Override
+    public String getChromeVersion() {
+        return VersionConstants.PRODUCT_VERSION;
+    }
+
+    @Override
+    public int getChromeChannel() {
+        return VersionConstants.CHANNEL;
+    }
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
index 33ce9f9..3af8f66 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
@@ -622,7 +622,9 @@
     @Override
     public void triggerRefresh(Callback<Boolean> callback) {
         PostTask.postTask(UiThreadTaskTraits.DEFAULT,
-                () -> FeedStreamJni.get().refresh(mNativeFeedStream, FeedStream.this, callback));
+                ()
+                        -> FeedStreamJni.get().manualRefresh(
+                                mNativeFeedStream, FeedStream.this, callback));
     }
 
     @Override
@@ -1038,7 +1040,7 @@
         void reportStreamScrolled(long nativeFeedStream, FeedStream caller, int distanceDp);
         void reportStreamScrollStart(long nativeFeedStream, FeedStream caller);
         void loadMore(long nativeFeedStream, FeedStream caller, Callback<Boolean> callback);
-        void refresh(long nativeFeedStream, FeedStream caller, Callback<Boolean> callback);
+        void manualRefresh(long nativeFeedStream, FeedStream caller, Callback<Boolean> callback);
         void processThereAndBackAgain(long nativeFeedStream, FeedStream caller, byte[] data);
         int executeEphemeralChange(long nativeFeedStream, FeedStream caller, byte[] data);
         void commitEphemeralChange(long nativeFeedStream, FeedStream caller, int changeId);
diff --git a/chrome/android/java/res/layout/settings_activity.xml b/chrome/android/java/res/layout/settings_activity.xml
index 170bc5f..542aa3e 100644
--- a/chrome/android/java/res/layout/settings_activity.xml
+++ b/chrome/android/java/res/layout/settings_activity.xml
@@ -7,8 +7,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fitsSystemWindows="true">
+    android:layout_height="match_parent">
 
     <com.google.android.material.appbar.AppBarLayout
         android:id="@+id/app_bar_layout"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index e2cc4a0..a0fb08c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -672,7 +672,7 @@
                         return getCompositorViewHolder().getLayerTitleCache();
                     },
                     mOverviewModeBehaviorSupplier,
-                    mRootUiCoordinator::getTopUiThemeColorProvider);
+                    mRootUiCoordinator::getTopUiThemeColorProvider, mJankTracker);
             mLayoutStateProviderOneshotSupplier.set(mLayoutManager);
             // clang-format on
             mOverviewModeController = mLayoutManager;
@@ -692,7 +692,7 @@
                         return getCompositorViewHolder().getLayerTitleCache();
                     },
                     mOverviewModeBehaviorSupplier,
-                    mRootUiCoordinator::getTopUiThemeColorProvider);
+                    mRootUiCoordinator::getTopUiThemeColorProvider, mJankTracker);
             mLayoutStateProviderOneshotSupplier.set(mLayoutManager);
             // clang-format on
             mOverviewModeController = mLayoutManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index 1586e50..2ed4b8a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -122,6 +122,7 @@
                         add(LensFeature.MIN_AGSA_VERSION_LENS_CAMERA_ASSISTED_SEARCH);
                         add(LensFeature.SEARCH_BOX_START_VARIANT_LENS_CAMERA_ASSISTED_SEARCH);
                         add(LensFeature.SKIP_AGSA_VERSION_CHECK);
+                        add(LensFeature.SKIP_LENS_ELIGIBILITY_CHECKS);
                         add(MerchantViewerConfig.DEFAULT_TRUST_SIGNALS_MESSAGE_DELAY);
                         add(MerchantViewerConfig.TRUST_SIGNALS_MESSAGE_USE_RATING_BAR);
                         add(MerchantViewerConfig.TRUST_SIGNALS_MESSAGE_WINDOW_DURATION_SECONDS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index 2ea9a40..5566af8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ObserverList;
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
@@ -92,7 +93,7 @@
             ObservableSupplier<TabContentManager> tabContentManagerSupplier,
             Supplier<LayerTitleCache> layerTitleCacheSupplier,
             OneshotSupplierImpl<OverviewModeBehavior> overviewModeBehaviorSupplier,
-            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider) {
+            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, JankTracker jankTracker) {
         super(host, contentContainer, tabContentManagerSupplier, layerTitleCacheSupplier,
                 topUiThemeColorProvider);
         Context context = host.getContext();
@@ -123,7 +124,7 @@
                 assert tabManagementDelegate != null;
 
                 mOverviewLayout = tabManagementDelegate.createStartSurfaceLayout(
-                        context, this, renderHost, startSurface);
+                        context, this, renderHost, startSurface, jankTracker);
             }
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
index 963d9856..00888522 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.view.ViewGroup;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
@@ -48,9 +49,10 @@
             ObservableSupplier<TabContentManager> tabContentManagerSupplier,
             Supplier<LayerTitleCache> layerTitleCacheSupplier,
             OneshotSupplierImpl<OverviewModeBehavior> overviewModeBehaviorSupplier,
-            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider) {
+            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, JankTracker jankTracker) {
         super(host, contentContainer, true, startSurface, tabContentManagerSupplier,
-                layerTitleCacheSupplier, overviewModeBehaviorSupplier, topUiThemeColorProvider);
+                layerTitleCacheSupplier, overviewModeBehaviorSupplier, topUiThemeColorProvider,
+                jankTracker);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
index 556b5bc..b38362de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -6,6 +6,7 @@
 
 import android.view.ViewGroup;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
@@ -45,9 +46,10 @@
             ObservableSupplier<TabContentManager> tabContentManagerSupplier,
             Supplier<LayerTitleCache> layerTitleCacheSupplier,
             OneshotSupplierImpl<OverviewModeBehavior> overviewModeBehaviorSupplier,
-            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider) {
+            Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, JankTracker jankTracker) {
         super(host, contentContainer, false, null, tabContentManagerSupplier,
-                layerTitleCacheSupplier, overviewModeBehaviorSupplier, topUiThemeColorProvider);
+                layerTitleCacheSupplier, overviewModeBehaviorSupplier, topUiThemeColorProvider,
+                jankTracker);
 
         mTabStripLayoutHelperManager = new StripLayoutHelperManager(host.getContext(), this,
                 mHost.getLayoutRenderHost(), () -> mTitleCache, layerTitleCacheSupplier);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
index 41c8aad..3c8be4e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/BrowsingHistoryBridge.java
@@ -41,7 +41,13 @@
     @Override
     public void queryHistory(String query) {
         BrowsingHistoryBridgeJni.get().queryHistory(mNativeHistoryBridge,
-                BrowsingHistoryBridge.this, new ArrayList<HistoryItem>(), query);
+                BrowsingHistoryBridge.this, new ArrayList<HistoryItem>(), query, false);
+    }
+
+    @Override
+    public void queryHistoryForHost(String hostName) {
+        BrowsingHistoryBridgeJni.get().queryHistory(mNativeHistoryBridge,
+                BrowsingHistoryBridge.this, new ArrayList<HistoryItem>(), hostName, true);
     }
 
     @Override
@@ -113,7 +119,7 @@
         long init(BrowsingHistoryBridge caller, Profile profile);
         void destroy(long nativeBrowsingHistoryBridge, BrowsingHistoryBridge caller);
         void queryHistory(long nativeBrowsingHistoryBridge, BrowsingHistoryBridge caller,
-                List<HistoryItem> historyItems, String query);
+                List<HistoryItem> historyItems, String query, boolean hostOnly);
         void queryHistoryContinuation(long nativeBrowsingHistoryBridge,
                 BrowsingHistoryBridge caller, List<HistoryItem> historyItems);
         void markItemForRemoval(long nativeBrowsingHistoryBridge, BrowsingHistoryBridge caller,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
index 248eebb4..a78acca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -66,6 +66,7 @@
     private boolean mPrivacyDisclaimersVisible;
     private boolean mClearBrowsingDataButtonVisible;
     private String mQueryText = EMPTY_QUERY;
+    private String mHostName;
 
     private boolean mDisableScrollToLoadForTest;
 
@@ -98,7 +99,11 @@
         mAreHeadersInitialized = false;
         mIsLoadingItems = true;
         mClearOnNextQueryComplete = true;
-        mHistoryProvider.queryHistory(mQueryText);
+        if (mHostName != null) {
+            mHistoryProvider.queryHistoryForHost(mHostName);
+        } else {
+            mHistoryProvider.queryHistory(mQueryText);
+        }
     }
 
     @Override
@@ -411,12 +416,9 @@
         if (mAreHeadersInitialized) setHeaders();
     }
 
-    /**
-     * Sets the query text.
-     * @param query The text to be searched for.
-     */
-    void setQueryText(String query) {
-        mQueryText = query;
+    /** @param hostName The hostName to retrieve history entries for. */
+    public void setHostName(String hostName) {
+        mHostName = hostName;
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
index 373becd..0ba9628f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
@@ -225,12 +225,8 @@
 
     /** Initialize the HistoryContentManager to start loading items. */
     public void initialize() {
-        if (mHostName != null) {
-            // Filtering the adapter to only the results from this particular host.
-            // TODO(crbug.com/1173154): Add robust filtering for just items with a matching host in
-            // backend. QueryText could return entries that contain the string anywhere.
-            mHistoryAdapter.setQueryText(mHostName);
-        }
+        // Filtering the adapter to only the results from this particular host.
+        mHistoryAdapter.setHostName(mHostName);
         mHistoryAdapter.initialize();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryProvider.java
index d15896bc..9565fe6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryProvider.java
@@ -52,6 +52,13 @@
      */
     void queryHistory(String query);
 
+    /**
+     * Query browsing history for a particular host. Only one query may be in-flight at any time.
+     * See BrowsingHistoryService::QueryHistory.
+     * @param hostName The host name.
+     */
+    void queryHistoryForHost(String hostName);
+
     /*
      * Fetches more results using the previous query's text, only valid to call
      * after queryHistory is called.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
index 962d578..dcc91c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
@@ -14,19 +14,25 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.base.IntentUtils;
+import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.sync.SyncService;
+import org.chromium.chrome.browser.sync.TrustedVaultClient;
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
+import org.chromium.chrome.browser.sync.ui.TrustedVaultKeyRetrievalProxyActivity;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
+import org.chromium.components.signin.base.CoreAccountInfo;
+import org.chromium.components.sync.TrustedVaultUserActionTriggerForUMA;
 import org.chromium.content_public.browser.WebContents;
 
 import java.lang.annotation.Retention;
@@ -38,6 +44,7 @@
  */
 public class SyncErrorInfoBar
         extends ConfirmInfoBar implements SyncService.SyncStateChangedListener {
+    private static final String TAG = "SyncErrorInfoBar";
     // Preference key to save the latest time this infobar is viewed.
     @VisibleForTesting
     static final String PREF_SYNC_ERROR_INFOBAR_SHOWN_AT_TIME =
@@ -69,18 +76,30 @@
     // These values are persisted to logs. Entries should not be renumbered and
     // numeric values should never be reused.
     @IntDef({SyncErrorInfoBarAction.SHOWN, SyncErrorInfoBarAction.DISMISSED,
-            SyncErrorInfoBarAction.OPEN_SETTINGS_CLICKED, SyncErrorInfoBarAction.NUM_ENTRIES})
+            SyncErrorInfoBarAction.BUTTON_CLICKED, SyncErrorInfoBarAction.NUM_ENTRIES})
     @Retention(RetentionPolicy.SOURCE)
     private @interface SyncErrorInfoBarAction {
         int SHOWN = 0;
         int DISMISSED = 1;
-        int OPEN_SETTINGS_CLICKED = 2;
+        int BUTTON_CLICKED = 2;
         int NUM_ENTRIES = 3;
     }
 
     private final @SyncErrorInfoBarType int mType;
     private final String mDetailsMessage;
 
+    private static String getPrimaryButtonText(Context context, @SyncError int error) {
+        switch (error) {
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+                return context.getString(R.string.trusted_vault_error_card_button);
+            default:
+                return context.getString(R.string.open_settings_button);
+        }
+    }
+
     /**
      * This function is called after maybeLaunchSyncErrorInfoBar sends launch signal to the native
      * side code.
@@ -94,18 +113,84 @@
                 ? context.getString(R.string.sync_settings_not_confirmed_title)
                 : SyncSettingsUtils.getSyncErrorHint(context, error);
         String title = SyncSettingsUtils.getSyncErrorCardTitle(context, error);
-        return new SyncErrorInfoBar(getSyncErrorInfoBarType(), title, errorMessage,
-                context.getString(R.string.open_settings_button));
+        String primaryButtonText = getPrimaryButtonText(context, error);
+
+        return new SyncErrorInfoBar(
+                getSyncErrorInfoBarType(), title, errorMessage, primaryButtonText);
+    }
+
+    private void openTrustedVaultKeyRetrievalActivity() {
+        CoreAccountInfo primaryAccountInfo = getPrimaryAccountInfo();
+        if (primaryAccountInfo == null) {
+            return;
+        }
+        TrustedVaultClient.get()
+                .createKeyRetrievalIntent(primaryAccountInfo)
+                .then(
+                        (intent)
+                                -> {
+                            IntentUtils.safeStartActivity(getApplicationContext(),
+                                    TrustedVaultKeyRetrievalProxyActivity
+                                            .createKeyRetrievalProxyIntent(intent,
+                                                    TrustedVaultUserActionTriggerForUMA
+                                                            .NEW_TAB_PAGE_INFOBAR));
+                        },
+                        (exception)
+                                -> Log.w(TAG, "Error creating trusted vault key retrieval intent: ",
+                                        exception));
+    }
+
+    private void openTrustedVaultRecoverabilityDegradedActivity() {
+        CoreAccountInfo primaryAccountInfo = getPrimaryAccountInfo();
+        if (primaryAccountInfo == null) {
+            return;
+        }
+        TrustedVaultClient.get()
+                .createRecoverabilityDegradedIntent(primaryAccountInfo)
+                .then(
+                        (intent)
+                                -> {
+                            IntentUtils.safeStartActivity(getApplicationContext(),
+                                    TrustedVaultKeyRetrievalProxyActivity
+                                            .createRecoverabilityDegradedProxyIntent(intent,
+                                                    TrustedVaultUserActionTriggerForUMA
+                                                            .NEW_TAB_PAGE_INFOBAR));
+                        },
+                        (exception)
+                                -> Log.w(TAG,
+                                        "Error creating trusted vault recoverability intent: ",
+                                        exception));
     }
 
     @CalledByNative
     private void accept() {
         SyncService.get().removeSyncStateChangedListener(this);
-        recordHistogram(mType, SyncErrorInfoBarAction.OPEN_SETTINGS_CLICKED);
+        recordHistogram(mType, SyncErrorInfoBarAction.BUTTON_CLICKED);
 
-        SettingsLauncher settingsLauncher = new SettingsLauncherImpl();
-        settingsLauncher.launchSettingsActivity(getApplicationContext(), ManageSyncSettings.class,
-                ManageSyncSettings.createArguments(false));
+        switch (mType) {
+            case SyncErrorInfoBarType.NOT_SHOWN:
+                assert false;
+                break;
+
+            case SyncErrorInfoBarType.AUTH_ERROR:
+            case SyncErrorInfoBarType.PASSPHRASE_REQUIRED:
+            case SyncErrorInfoBarType.SYNC_SETUP_INCOMPLETE:
+            case SyncErrorInfoBarType.CLIENT_OUT_OF_DATE:
+                SettingsLauncher settingsLauncher = new SettingsLauncherImpl();
+                settingsLauncher.launchSettingsActivity(getApplicationContext(),
+                        ManageSyncSettings.class, ManageSyncSettings.createArguments(false));
+                break;
+
+            case SyncErrorInfoBarType.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+            case SyncErrorInfoBarType.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+                openTrustedVaultKeyRetrievalActivity();
+                break;
+
+            case SyncErrorInfoBarType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+            case SyncErrorInfoBarType.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+                openTrustedVaultRecoverabilityDegradedActivity();
+                break;
+        }
     }
 
     @CalledByNative
@@ -114,6 +199,13 @@
         recordHistogram(mType, SyncErrorInfoBarAction.DISMISSED);
     }
 
+    private CoreAccountInfo getPrimaryAccountInfo() {
+        if (!SyncService.get().isAuthenticatedAccountPrimary()) {
+            return null;
+        }
+        return SyncService.get().getAuthenticatedAccountInfo();
+    }
+
     private SyncErrorInfoBar(@SyncErrorInfoBarType int type, String title, String detailsMessage,
             String primaryButtonText) {
         super(R.drawable.ic_sync_error_legacy_40dp, R.color.default_red, null, title, null,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
deleted file mode 100644
index d3168f47..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.metrics;
-
-import android.content.ContentResolver;
-import android.os.Environment;
-import android.os.StatFs;
-import android.provider.Settings;
-
-import androidx.annotation.IntDef;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.task.AsyncTask;
-import org.chromium.components.browser_ui.util.ConversionUtils;
-
-import java.io.File;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Centralizes UMA data collection for WebAPKs. NOTE: Histogram names and values are defined in
- * tools/metrics/histograms/histograms.xml. Please update that file if any change is made.
- * TODO(crbug.com/1219648): Temporarily keep this around to avoid breaking down stream. This
- * class should be removed once down stream is updated.
- */
-public class WebApkUma {
-    private static final long WEBAPK_EXTRA_INSTALLATION_SPACE_BYTES =
-            100 * (long) ConversionUtils.BYTES_PER_MEGABYTE; // 100 MB
-
-    // This enum is used to back UMA histograms, and should therefore be treated as append-only.
-    @IntDef({GooglePlayInstallResult.SUCCESS, GooglePlayInstallResult.FAILED_NO_DELEGATE,
-            GooglePlayInstallResult.FAILED_TO_CONNECT_TO_SERVICE,
-            GooglePlayInstallResult.FAILED_CALLER_VERIFICATION_FAILURE,
-            GooglePlayInstallResult.FAILED_POLICY_VIOLATION,
-            GooglePlayInstallResult.FAILED_API_DISABLED,
-            GooglePlayInstallResult.FAILED_REQUEST_FAILED,
-            GooglePlayInstallResult.FAILED_DOWNLOAD_CANCELLED,
-            GooglePlayInstallResult.FAILED_DOWNLOAD_ERROR,
-            GooglePlayInstallResult.FAILED_INSTALL_ERROR,
-            GooglePlayInstallResult.FAILED_INSTALL_TIMEOUT,
-            GooglePlayInstallResult.REQUEST_FAILED_POLICY_DISABLED,
-            GooglePlayInstallResult.REQUEST_FAILED_UNKNOWN_ACCOUNT,
-            GooglePlayInstallResult.REQUEST_FAILED_NETWORK_ERROR,
-            GooglePlayInstallResult.REQUSET_FAILED_RESOLVE_ERROR,
-            GooglePlayInstallResult.REQUEST_FAILED_NOT_GOOGLE_SIGNED})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface GooglePlayInstallResult {
-        int SUCCESS = 0;
-        int FAILED_NO_DELEGATE = 1;
-        int FAILED_TO_CONNECT_TO_SERVICE = 2;
-        int FAILED_CALLER_VERIFICATION_FAILURE = 3;
-        int FAILED_POLICY_VIOLATION = 4;
-        int FAILED_API_DISABLED = 5;
-        int FAILED_REQUEST_FAILED = 6;
-        int FAILED_DOWNLOAD_CANCELLED = 7;
-        int FAILED_DOWNLOAD_ERROR = 8;
-        int FAILED_INSTALL_ERROR = 9;
-        int FAILED_INSTALL_TIMEOUT = 10;
-        // REQUEST_FAILED_* errors are the error codes shown in the "reason" of
-        // the returned Bundle when calling installPackage() API returns false.
-        int REQUEST_FAILED_POLICY_DISABLED = 11;
-        int REQUEST_FAILED_UNKNOWN_ACCOUNT = 12;
-        int REQUEST_FAILED_NETWORK_ERROR = 13;
-        int REQUSET_FAILED_RESOLVE_ERROR = 14;
-        int REQUEST_FAILED_NOT_GOOGLE_SIGNED = 15;
-        int NUM_ENTRIES = 16;
-    }
-
-    /**
-     * Records whether installing a WebAPK from Google Play succeeded. If not, records the reason
-     * that the install failed.
-     */
-    public static void recordGooglePlayInstallResult(@GooglePlayInstallResult int result) {
-        RecordHistogram.recordEnumeratedHistogram("WebApk.Install.GooglePlayInstallResult", result,
-                GooglePlayInstallResult.NUM_ENTRIES);
-    }
-
-    /** Records the error code if installing a WebAPK via Google Play fails. */
-    public static void recordGooglePlayInstallErrorCode(int errorCode) {
-        // Don't use an enumerated histogram as there are > 30 potential error codes. In practice,
-        // a given client will always get the same error code.
-        RecordHistogram.recordSparseHistogram(
-                "WebApk.Install.GooglePlayErrorCode", Math.min(errorCode, 1000));
-    }
-
-    /**
-     * Records whether updating a WebAPK from Google Play succeeded. If not, records the reason
-     * that the update failed.
-     */
-    public static void recordGooglePlayUpdateResult(@GooglePlayInstallResult int result) {
-        RecordHistogram.recordEnumeratedHistogram("WebApk.Update.GooglePlayUpdateResult", result,
-                GooglePlayInstallResult.NUM_ENTRIES);
-    }
-
-    /**
-     * Log necessary disk usage and cache size UMAs when WebAPK installation fails.
-     */
-    public static void logSpaceUsageUMAWhenInstallationFails() {
-        new AsyncTask<Void>() {
-            long mAvailableSpaceInByte;
-            long mCacheSizeInByte;
-            @Override
-            protected Void doInBackground() {
-                mAvailableSpaceInByte = getAvailableSpaceAboveLowSpaceLimit();
-                mCacheSizeInByte = getCacheDirSize();
-                return null;
-            }
-
-            @Override
-            protected void onPostExecute(Void result) {
-                logSpaceUsageUMAOnDataAvailable(mAvailableSpaceInByte, mCacheSizeInByte);
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-    }
-
-    private static void logSpaceUsageUMAOnDataAvailable(long spaceSize, long cacheSize) {
-        RecordHistogram.recordSparseHistogram(
-                "WebApk.Install.AvailableSpace.Fail", roundByteToMb(spaceSize));
-
-        RecordHistogram.recordSparseHistogram("WebApk.Install.AvailableSpaceAfterFreeUpCache.Fail",
-                roundByteToMb(spaceSize + cacheSize));
-    }
-
-    private static int roundByteToMb(long bytes) {
-        int mbs = (int) (bytes / (long) ConversionUtils.BYTES_PER_MEGABYTE / 10L * 10L);
-        return Math.min(1000, Math.max(-1000, mbs));
-    }
-
-    private static long getDirectorySizeInByte(File dir) {
-        if (dir == null) return 0;
-        if (!dir.isDirectory()) return dir.length();
-
-        long sizeInByte = 0;
-        try {
-            File[] files = dir.listFiles();
-            if (files == null) return 0;
-            for (File file : files) sizeInByte += getDirectorySizeInByte(file);
-        } catch (SecurityException e) {
-            return 0;
-        }
-        return sizeInByte;
-    }
-
-    /**
-     * @return The available space that can be used to install WebAPK. Negative value means there is
-     * less free space available than the system's minimum by the given amount.
-     */
-    public static long getAvailableSpaceAboveLowSpaceLimit() {
-        StatFs partitionStats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
-        long partitionAvailableBytes = partitionStats.getAvailableBytes();
-        long partitionTotalBytes = partitionStats.getTotalBytes();
-        long minimumFreeBytes = getLowSpaceLimitBytes(partitionTotalBytes);
-
-        long webApkExtraSpaceBytes = WEBAPK_EXTRA_INSTALLATION_SPACE_BYTES;
-        return partitionAvailableBytes - minimumFreeBytes + webApkExtraSpaceBytes;
-    }
-
-    /**
-     * @return Size of the cache directory.
-     */
-    public static long getCacheDirSize() {
-        return getDirectorySizeInByte(ContextUtils.getApplicationContext().getCacheDir());
-    }
-
-    /**
-     * Mirror the system-derived calculation of reserved bytes and return that value.
-     */
-    private static long getLowSpaceLimitBytes(long partitionTotalBytes) {
-        // Copied from android/os/storage/StorageManager.java
-        final int defaultThresholdPercentage = 10;
-        // Copied from android/os/storage/StorageManager.java
-        final long defaultThresholdMaxBytes = 500 * ConversionUtils.BYTES_PER_MEGABYTE;
-        // Copied from android/provider/Settings.java
-        final String sysStorageThresholdPercentage = "sys_storage_threshold_percentage";
-        // Copied from android/provider/Settings.java
-        final String sysStorageThresholdMaxBytes = "sys_storage_threshold_max_bytes";
-
-        ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver();
-        int minFreePercent = 0;
-        long minFreeBytes = 0;
-
-        // Retrieve platform-appropriate values first
-        minFreePercent = Settings.Global.getInt(
-                resolver, sysStorageThresholdPercentage, defaultThresholdPercentage);
-        minFreeBytes = Settings.Global.getLong(
-                resolver, sysStorageThresholdMaxBytes, defaultThresholdMaxBytes);
-
-        long minFreePercentInBytes = (partitionTotalBytes * minFreePercent) / 100;
-
-        return Math.min(minFreeBytes, minFreePercentInBytes);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
index 5e297d46..7af232d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -25,8 +25,6 @@
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
 
-import com.google.android.material.appbar.AppBarLayout;
-
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.IntentUtils;
 import org.chromium.chrome.R;
@@ -36,8 +34,6 @@
 import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragmentBasic;
 import org.chromium.chrome.browser.feedback.FragmentHelpAndFeedbackLauncher;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.image_descriptions.ImageDescriptionsController;
 import org.chromium.chrome.browser.image_descriptions.ImageDescriptionsSettings;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
@@ -125,13 +121,6 @@
         setSupportActionBar(actionBar);
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 
-        if (CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)) {
-            // Setting the outline provider to null to prevent the elevation shadow being drawn.
-            // This is needed because we can't remove the shadow in xml pre-P.
-            AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout);
-            appBarLayout.setOutlineProvider(null);
-        }
-
         mIsNewlyCreated = savedInstanceState == null;
 
         String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
@@ -394,9 +383,7 @@
     protected void applyThemeOverlays() {
         super.applyThemeOverlays();
 
-        if (!CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)) {
-            setTheme(R.style.ThemeRefactorOverlay_Disabled_Settings);
-        }
+        setTheme(R.style.ThemeRefactorOverlay_Disabled_Settings);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncErrorNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncErrorNotifier.java
index bb9a5e5..c6b33aca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncErrorNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncErrorNotifier.java
@@ -35,6 +35,7 @@
 import org.chromium.components.signin.base.GoogleServiceAuthError.State;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.sync.PassphraseType;
+import org.chromium.components.sync.TrustedVaultUserActionTriggerForUMA;
 
 /**
  * {@link SyncErrorNotifier} displays Android notifications regarding sync errors.
@@ -245,7 +246,9 @@
                 .then((realIntent)
                                 -> showNotification(notificationTitle, notificationTextBody,
                                         TrustedVaultKeyRetrievalProxyActivity
-                                                .createKeyRetrievalProxyIntent(realIntent)),
+                                                .createKeyRetrievalProxyIntent(realIntent,
+                                                        TrustedVaultUserActionTriggerForUMA
+                                                                .NOTIFICATION)),
                         (exception)
                                 -> Log.w(TAG, "Error creating key retrieval intent: ", exception));
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
index 8a5073d..97bfa74 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncSettingsUtils.java
@@ -169,10 +169,24 @@
      * @param error The sync error.
      */
     public static String getSyncErrorCardTitle(Context context, @SyncError int error) {
-        return (error == SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS
-                       || error == SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS)
-                ? context.getString(R.string.password_sync_error_summary)
-                : context.getString(R.string.sync_error_card_title);
+        switch (error) {
+            case SyncError.ANDROID_SYNC_DISABLED:
+            case SyncError.AUTH_ERROR:
+            case SyncError.CLIENT_OUT_OF_DATE:
+            case SyncError.OTHER_ERRORS:
+            case SyncError.PASSPHRASE_REQUIRED:
+            case SyncError.SYNC_SETUP_INCOMPLETE:
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING:
+                return context.getString(R.string.sync_error_card_title);
+            case SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS:
+                return context.getString(R.string.password_sync_error_summary);
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_EVERYTHING:
+            case SyncError.TRUSTED_VAULT_RECOVERABILITY_DEGRADED_FOR_PASSWORDS:
+                return context.getString(R.string.sync_needs_verification_title);
+            case SyncError.NO_ERROR:
+            default:
+                return null;
+        }
     }
 
     public static @Nullable String getSyncErrorCardButtonLabel(
@@ -255,13 +269,16 @@
             return context.getString(R.string.sync_need_passphrase);
         }
 
-        if (syncService.isTrustedVaultKeyRequiredForPreferredDataTypes()
-                || syncService.isTrustedVaultRecoverabilityDegraded()) {
+        if (syncService.isTrustedVaultKeyRequiredForPreferredDataTypes()) {
             return syncService.isEncryptEverythingEnabled()
                     ? context.getString(R.string.sync_error_card_title)
                     : context.getString(R.string.password_sync_error_summary);
         }
 
+        if (syncService.isTrustedVaultRecoverabilityDegraded()) {
+            return context.getString(R.string.sync_needs_verification_title);
+        }
+
         return context.getString(R.string.sync_on);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/TrustedVaultKeyRetrievalProxyActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/TrustedVaultKeyRetrievalProxyActivity.java
index bee9e7d..61c2a68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/TrustedVaultKeyRetrievalProxyActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/TrustedVaultKeyRetrievalProxyActivity.java
@@ -20,26 +20,66 @@
  * activity (passed via extra). The reason for using this proxy activity is to detect when real key
  * retrieval activity finishes and notify TrustedVaultClient about changed keys.
  */
+// TODO(crbug.com/1100279): Rename this class to avoid 'retrieval' in the name.
 public class TrustedVaultKeyRetrievalProxyActivity extends AsyncInitializationActivity {
-    private static final String KEY_RETRIEVAL_INTENT_NAME = "key_retrieval";
     private static final String TAG = "SyncUI";
+
+    // Note that the implementation relies on request codes being >0 (default value for
+    // |mRequestCode|).
     private static final int REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL = 1;
+    private static final int REQUEST_CODE_TRUSTED_VAULT_RECOVERABILITY_DEGRADED = 2;
+
+    // Key names used when propagating extra param in the proxy intent.
+    private static final String EXTRA_KEY_PROXIED_INTENT = "proxied_intent";
+    private static final String EXTRA_KEY_REQUEST_CODE = "request_code";
+    private static final String EXTRA_KEY_USER_ACTION_TRIGGER = "user_action_trigger";
+
+    private @TrustedVaultUserActionTriggerForUMA int mUserActionTrigger;
+    private int mRequestCode;
 
     /**
-     * Creates an intent that launches an TrustedVaultKeyRetrievalProxyActivity.
+     * Creates an intent that launches an TrustedVaultKeyRetrievalProxyActivity for the purpose of
+     * key retrieval.
      *
      * @param keyRetrievalIntent Actual key retrieval intent, which will be launched by
      * TrustedVaultKeyRetrievalProxyActivity.
+     * @param userActionTrigger Enum representing which UI surface triggered the intent.
      *
      * @return the intent for launching TrustedVaultKeyRetrievalProxyActivity
      */
-    public static Intent createKeyRetrievalProxyIntent(PendingIntent keyRetrievalIntent) {
-        Intent intent = new Intent(
+    public static Intent createKeyRetrievalProxyIntent(PendingIntent keyRetrievalIntent,
+            @TrustedVaultUserActionTriggerForUMA int userActionTrigger) {
+        return createProxyIntent(
+                keyRetrievalIntent, userActionTrigger, REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL);
+    }
+
+    /**
+     * Creates an intent that launches an TrustedVaultKeyRetrievalProxyActivity for the purpose of
+     * fixing the recoverability degraded case.
+     *
+     * @param recoverabilityDegradedIntent Actual recoverability degraded fix intent, which will be
+     *         launched by TrustedVaultKeyRetrievalProxyActivity.
+     * @param userActionTrigger Enum representing which UI surface triggered the intent.
+     *
+     * @return the intent for launching TrustedVaultKeyRetrievalProxyActivity
+     */
+    public static Intent createRecoverabilityDegradedProxyIntent(
+            PendingIntent recoverabilityDegradedIntent,
+            @TrustedVaultUserActionTriggerForUMA int userActionTrigger) {
+        return createProxyIntent(recoverabilityDegradedIntent, userActionTrigger,
+                REQUEST_CODE_TRUSTED_VAULT_RECOVERABILITY_DEGRADED);
+    }
+
+    private static Intent createProxyIntent(PendingIntent proxiedIntent,
+            @TrustedVaultUserActionTriggerForUMA int userActionTrigger, int requestCode) {
+        Intent proxyIntent = new Intent(
                 ContextUtils.getApplicationContext(), TrustedVaultKeyRetrievalProxyActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        intent.putExtra(KEY_RETRIEVAL_INTENT_NAME, keyRetrievalIntent);
-        return intent;
+        proxyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        proxyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        proxyIntent.putExtra(EXTRA_KEY_PROXIED_INTENT, proxiedIntent);
+        proxyIntent.putExtra(EXTRA_KEY_REQUEST_CODE, requestCode);
+        proxyIntent.putExtra(EXTRA_KEY_USER_ACTION_TRIGGER, userActionTrigger);
+        return proxyIntent;
     }
 
     @Override
@@ -52,18 +92,22 @@
         // This Activity has no own UI and uses external pending intent to provide it. Since this
         // Activity requires native initialization it implements AsyncInitializationActivity and
         // thus the pending intent is sent inside triggerLayoutInflation() instead of onCreate().
-        PendingIntent keyRetrievalIntent =
-                getIntent().getParcelableExtra(KEY_RETRIEVAL_INTENT_NAME);
-        assert keyRetrievalIntent != null;
+        PendingIntent proxiedIntent = getIntent().getParcelableExtra(EXTRA_KEY_PROXIED_INTENT);
+        mRequestCode = getIntent().getIntExtra(EXTRA_KEY_REQUEST_CODE, -1);
+        mUserActionTrigger = getIntent().getIntExtra(EXTRA_KEY_USER_ACTION_TRIGGER, -1);
+
+        assert proxiedIntent != null;
+        assert mRequestCode != -1;
+        assert mUserActionTrigger != -1;
+
         try {
             // TODO(crbug.com/1090704): check getSavedInstanceState() before sending the intent.
-            startIntentSenderForResult(keyRetrievalIntent.getIntentSender(),
-                    REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL,
+            startIntentSenderForResult(proxiedIntent.getIntentSender(), mRequestCode,
                     /* fillInIntent */ null, /* flagsMask */ 0,
                     /* flagsValues */ 0, /* extraFlags */ 0,
                     /* options */ null);
         } catch (IntentSender.SendIntentException exception) {
-            Log.w(TAG, "Error sending key retrieval intent: ", exception);
+            Log.w(TAG, "Error sending trusted vault intent: ", exception);
         }
         onInitialLayoutInflationComplete();
     }
@@ -71,22 +115,53 @@
     @Override
     public void finishNativeInitialization() {
         super.finishNativeInitialization();
-        // Activity might be restored and this shouldn't cause recording the histogram second time.
-        if (getSavedInstanceState() == null) {
-            SyncService.get().recordKeyRetrievalTrigger(
-                    TrustedVaultUserActionTriggerForUMA.NOTIFICATION);
+
+        if (getSavedInstanceState() != null) {
+            // The activity might be restored and this shouldn't cause recording the histogram
+            // second time.
+            return;
+        }
+
+        // Note that the metric-recording methods are invoked here, and not earlier, because:
+        // a) The native part must be loaded (which is not guaranteed in triggerLayoutInflation).
+        // b) It cannot be done too early, e.g. upon intent creation, because that doesn't always
+        // mean the intent will actually be launched. This is particularly relevant for Android
+        // notifications (SyncErrorNotifier), because the user may ignore or dismiss a notification.
+        switch (mRequestCode) {
+            case REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL:
+                SyncService.get().recordKeyRetrievalTrigger(mUserActionTrigger);
+                break;
+
+            case REQUEST_CODE_TRUSTED_VAULT_RECOVERABILITY_DEGRADED:
+                SyncService.get().recordRecoverabilityDegradedFixTrigger(mUserActionTrigger);
+                break;
+
+            default:
+                assert false;
         }
     }
 
     @Override
     public boolean onActivityResultWithNative(int requestCode, int resultCode, Intent intent) {
         boolean result = super.onActivityResultWithNative(requestCode, resultCode, intent);
-        assert requestCode == REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL;
 
-        // Upon key retrieval completion, the keys in TrustedVaultClient could have changed. This is
-        // done even if the user cancelled the flow (i.e. resultCode != RESULT_OK) because it's
-        // harmless to issue a redundant notifyKeysChanged().
-        TrustedVaultClient.get().notifyKeysChanged();
+        switch (requestCode) {
+            case REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL:
+                // Upon key retrieval completion, the keys in TrustedVaultClient could have changed.
+                // This is done even if the user cancelled the flow (i.e. resultCode != RESULT_OK)
+                // because it's harmless to issue a redundant notifyKeysChanged().
+                TrustedVaultClient.get().notifyKeysChanged();
+                break;
+
+            case REQUEST_CODE_TRUSTED_VAULT_RECOVERABILITY_DEGRADED:
+                // Same as above, it is harmless to issue redundant notifyRecoverabilityChanged().
+                TrustedVaultClient.get().notifyRecoverabilityChanged();
+                break;
+
+            default:
+                assert false;
+        }
+
         finish();
         return result;
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
index de60cc5..7cd33aa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -42,6 +42,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
+import org.chromium.base.jank_tracker.DummyJankTracker;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.UiThreadTest;
@@ -214,7 +215,7 @@
 
         mManagerPhone = new LayoutManagerChromePhone(layoutManagerHost, container, mStartSurface,
                 tabContentManagerSupplier, null, overviewModeBehaviorSupplier,
-                () -> mTopUiThemeColorProvider);
+                () -> mTopUiThemeColorProvider, new DummyJankTracker());
         verify(mStartSurfaceController)
                 .addOverviewModeObserver(mStartSurfaceOverviewModeCaptor.capture());
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
index 0fc7fcb8..2ace90be 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -166,11 +166,19 @@
         Mockito.doReturn(SEARCH_ENGINE_SHORT_NAME).when(mMockSearchEngine).getShortName();
     }
 
+    private void waitForOptionsMenu() {
+        CriteriaHelper.pollUiThread(() -> {
+            return mSettingsActivityTestRule.getActivity().findViewById(R.id.menu_id_general_help)
+                    != null;
+        });
+    }
+
     @Test
     @LargeTest
     @Feature({"RenderTest"})
     public void testRenderDifferentSignedInStates() throws IOException {
         launchSettingsActivity();
+        waitForOptionsMenu();
         View view = mSettingsActivityTestRule.getActivity()
                             .findViewById(android.R.id.content)
                             .getRootView();
@@ -179,6 +187,7 @@
         // Sign in and render changes.
         mSyncTestRule.setUpAccountAndEnableSyncForTesting();
         SyncTestUtil.waitForSyncFeatureActive();
+        waitForOptionsMenu();
         // Waiting for sync to become active might take some time, so the scrollbar on the settings
         // view starts to fade, making the test flaky due to differences in the rendered image.
         // Sanitize the view to hide scrollbars (see https://crbug.com/1204117 for details).
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
index 8d1fc8cc..fd08b2a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
@@ -62,7 +62,7 @@
 
     @Rule
     public final ChromeRenderTestRule mRenderTestRule =
-            ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(5).build();
+            ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(6).build();
 
     private FakeSyncServiceImpl mFakeSyncServiceImpl;
 
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index dd5fd693..3b9bf45 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -138,7 +138,7 @@
   ]
 
   if (!is_fuchsia) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+    # TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
     deps += [
       "//components/crash/core/app",
       "//components/crash/core/app:test_support",
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index f2a1439a0..800f31d 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1056,6 +1056,12 @@
     <ph name="END_PARAGRAPH1">&lt;/p&gt;</ph>
     <ph name="BEGIN_PARAGRAPH2">&lt;p&gt;</ph>View logs for additional details.<ph name="END_PARAGRAPH2">&lt;/p&gt;</ph>
   </message>
+  <message name="IDS_OS_INSTALL_SCREEN_ERROR_SERVICE_LOGS_LINK_TEXT" desc="Text of the link to service logs dialog of the OS install screen">
+    Show service logs
+  </message>
+  <message name="IDS_OS_INSTALL_SCREEN_SERVICE_LOGS_TITLE" desc="Title of service logs dialog of the OS install screen">
+    Service logs
+  </message>
   <message name="IDS_OS_INSTALL_SCREEN_SUCCESS_TITLE" desc="Title of the success page of the OS install screen">
     Installation complete
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_ERROR_SERVICE_LOGS_LINK_TEXT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_ERROR_SERVICE_LOGS_LINK_TEXT.png.sha1
new file mode 100644
index 0000000..6a8cdc0a
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_ERROR_SERVICE_LOGS_LINK_TEXT.png.sha1
@@ -0,0 +1 @@
+9eb4ec73dc3e5496855fcbf0ce1311c0747fcd85
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_SERVICE_LOGS_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_SERVICE_LOGS_TITLE.png.sha1
new file mode 100644
index 0000000..3d3a18f
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_OS_INSTALL_SCREEN_SERVICE_LOGS_TITLE.png.sha1
@@ -0,0 +1 @@
+11fec75a8aa51d79027b19e3e90ec127eb32d94e
\ No newline at end of file
diff --git a/chrome/app/extensions_strings.grdp b/chrome/app/extensions_strings.grdp
index 6599c948..6a8ff13 100644
--- a/chrome/app/extensions_strings.grdp
+++ b/chrome/app/extensions_strings.grdp
@@ -442,35 +442,6 @@
   Type a letter
 </message>
 
-<!-- Extensions Checkup Banner -->
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_TITLE" desc="Title of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a performance focus.">
-  A healthier, happier Chrome
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY1" desc="First pargagraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a performance focus.">
-  Some extensions can slow you down - especially ones you didn't mean to install.
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY2" desc="Second paragraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a performance focus.">
-  If you don’t recognize an extension, or if your browser isn’t working as expected, you can turn off or customize extensions here.
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_TITLE" desc="Title of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a privacy focus.">
-  Check your extensions
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY1" desc="First pargagraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a privacy focus.">
-  Some extensions can see your browsing activity - including personal information.
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY2" desc="Second paragraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a privacy focus.">
-  If you don’t recognize an extension, or if your browser isn’t working as expected, you can turn off or customize extensions here.
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_TITLE" desc="Title of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a neutral focus.">
-  Manage your extensions
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY1" desc="First paragraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a neutral focus.">
-  On this page you can see all the extensions installed in Chrome.
-</message>
-<message name="IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY2" desc="Second paragraph of the extensions checkup flow shown in the chrome://extensions page, encouraging the user to audit their installed extensions with a neutral focus.">
-  If you don't recognize an extension, or if your browser isn't working as expected, you can turn off or customize extensions here.
-</message>
-
 <if expr="chromeos">
   <!-- Extensions Kiosk apps -->
   <message name="IDS_EXTENSIONS_MANAGE_KIOSK_APP" desc="Label of the button to bring up kiosk management overlay on chrome extensions page.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 420c77b..2d2531e 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -752,6 +752,15 @@
           <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH" desc="The name of the Lens Region Search command in the content area context menu">
             Search part of the page with Google Lens
           </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1" desc="The name of the Lens Region Search command in the content area context menu">
+            Drag to search images with Google Lens
+          </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2" desc="The name of the Lens Region Search command in the content area context menu">
+            Drag over images to search with Google Lens
+          </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3" desc="The name of the Lens Region Search command in the content area context menu">
+            Search your screen with Google Lens
+          </message>
           <message name="IDS_CONTENT_CONTEXT_GOTOURL" desc="The name of the Go to 'url' command in the content area context menu">
             &amp;Go to <ph name="URL">$1<ex>http://www.google.com/</ex></ph>
           </message>
@@ -996,6 +1005,15 @@
           <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH" desc="In Title Case: The name of the Lens Region Search command in the content area context menu">
             Search Part of the Page with Google Lens
           </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1" desc="In Title Case: The name of the Lens Region Search command in the content area context menu">
+            Drag to Search Images with Google Lens
+          </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2" desc="In Title Case: The name of the Lens Region Search command in the content area context menu">
+            Drag over Images to Search with Google Lens
+          </message>
+          <message name="IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3" desc="In Title Case: The name of the Lens Region Search command in the content area context menu">
+            Search Your Screen with Google Lens
+          </message>
           <message name="IDS_CONTENT_CONTEXT_GOTOURL" desc="In Title Case: The name of the Go to url for 'string' command in the content area context menu">
             &amp;Go to <ph name="URL">$1<ex>http://www.google.com/</ex></ph>
           </message>
@@ -8758,6 +8776,9 @@
       <message name="IDS_SYNC_ERROR_USER_MENU_SIGNIN_BUTTON" desc="Button in the header of desktop user menu that prompts the user to sign in again to fix the out-of-date signin info error.">
         Sign in again
       </message>
+      <message name="IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE" desc="Title in the sync error bubble view/notification for the case where sync needs to verify the user.">
+        Sync needs to verify it's you
+      </message>
       <message name="IDS_SYNC_ERROR_USER_MENU_PASSPHRASE_BUTTON" desc="Button in the header of desktop user menu that prompts the user to enter the sync passphrase to fix the out-of-date passphrase error.">
         Enter passphrase
       </message>
@@ -10149,8 +10170,14 @@
       <message name="IDS_DESKTOP_MEDIA_PICKER_TEXT_DELEGATED" desc="Text for the window picker dialog shown when desktop capture is requested by an app to be used by a tab.">
         <ph name="APP_NAME">$1<ex>Google Hangouts</ex></ph> wants to share the contents of your screen with <ph name="TARGET_NAME">$2<ex>https://google.com</ex></ph>.
       </message>
-      <message name="IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE" desc="Text for the checkbox on the window picker dialog, when checked, audio will be shared, otherwise just video sharing">
-        Share audio
+      <message name="IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_SCREEN" desc="Text for the checkbox on the window picker dialog which is displayed when attempting to share a screen. In that case, when checked, system audio will be shared; otherwise only video.">
+        Share system audio
+      </message>
+      <message name="IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_WINDOW" desc="Text for the checkbox on the window picker dialog which is displayed when attempting to share a window. In that case, when checked, window audio will be shared; otherwise only video.">
+        Share window audio
+      </message>
+      <message name="IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TAB" desc="Text for the checkbox on the window picker dialog which is displayed when attempting to share a tab. In that case, when checked, tab audio will be shared; otherwise only video.">
+        Share tab audio
       </message>
       <message name="IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN" desc="Text for the button on the window picker dialog, clicking which takes one to full screen sharing" meaning="Refers to the device's entire screen. Short for 'share the entire screen'.">
         Entire Screen
diff --git a/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1.png.sha1 b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1.png.sha1
new file mode 100644
index 0000000..57b97ec
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1.png.sha1
@@ -0,0 +1 @@
+6b049bae7ef789c6eb315e5368e0664ce07d1762
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2.png.sha1 b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2.png.sha1
new file mode 100644
index 0000000..5853ecc2
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2.png.sha1
@@ -0,0 +1 @@
+eb6a12f01493026bb536866d89de6749230f6cf6
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3.png.sha1 b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3.png.sha1
new file mode 100644
index 0000000..f24e225
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3.png.sha1
@@ -0,0 +1 @@
+785b9817c341f8f5e55a5de2a7addaa2cf595eaf
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_SCREEN.png.sha1 b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_SCREEN.png.sha1
new file mode 100644
index 0000000..ad0ffb2
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_SCREEN.png.sha1
@@ -0,0 +1 @@
+62f5308ecd482308a7efd7e24b12bea60b53e248
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TAB.png.sha1 b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TAB.png.sha1
new file mode 100644
index 0000000..3f03fa51
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TAB.png.sha1
@@ -0,0 +1 @@
+0123f5731a66881e641642adb3ea85bc7faf5fdf
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_WINDOW.png.sha1 b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_WINDOW.png.sha1
new file mode 100644
index 0000000..7acaaced
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_WINDOW.png.sha1
@@ -0,0 +1 @@
+885d8d01930266748d4ce9d1a1b56a6fee094177
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE.png.sha1
new file mode 100644
index 0000000..943c627
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE.png.sha1
@@ -0,0 +1 @@
+47ee7940169362f0faf1da6448ed0c66e6540a2c
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a2a8006..8c08d1c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2461,7 +2461,7 @@
     sources += [ "net/net_error_diagnostics_dialog_stub.cc" ]
   }
 
-  if (is_posix || is_fuchsia) {
+  if (is_posix) {
     sources += [
       "download/trusted_sources_manager_posix.cc",
       "google/google_update_settings_posix.cc",
@@ -4304,7 +4304,7 @@
       deps += [ "//chrome:packed_resources_integrity" ]
     }
 
-    if (is_posix || is_fuchsia) {
+    if (is_posix) {
       sources += [
         "chrome_browser_main_posix.cc",
         "chrome_browser_main_posix.h",
@@ -5366,7 +5366,7 @@
     }
   }
 
-  if (is_posix || is_fuchsia) {
+  if (is_posix) {
     sources += [
       "shutdown_signal_handlers_posix.cc",
       "shutdown_signal_handlers_posix.h",
@@ -5522,7 +5522,7 @@
   }
 
   if (is_posix && !is_mac) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+    # TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
     sources += [
       "//chrome/app/chrome_crash_reporter_client.cc",
       "//chrome/app/chrome_crash_reporter_client.h",
@@ -7033,7 +7033,7 @@
     "//ui/gfx:test_support",
   ]
 
-  if (!is_android && !is_fuchsia) {
+  if (!is_android) {
     deps += [ "//components/policy/test_support" ]
   }
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6123318..8f2c07a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -23,6 +23,7 @@
 #include "base/i18n/base_i18n_switches.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -2236,55 +2237,6 @@
      base::size(kQuietNotificationPromptsWithAdaptiveActivation), nullptr},
 };
 
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-const FeatureEntry::FeatureParam kExtensionsCheckup_Startup_Performance[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kPerformanceMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kStartupEntryPoint}};
-const FeatureEntry::FeatureParam kExtensionsCheckup_Startup_Privacy[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kPrivacyMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kStartupEntryPoint}};
-const FeatureEntry::FeatureParam kExtensionsCheckup_Startup_Neutral[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kNeutralMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kStartupEntryPoint}};
-const FeatureEntry::FeatureParam kExtensionsCheckup_Promo_Performance[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kPerformanceMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kNtpPromoEntryPoint}};
-const FeatureEntry::FeatureParam kExtensionsCheckup_Promo_Privacy[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kPrivacyMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kNtpPromoEntryPoint}};
-const FeatureEntry::FeatureParam kExtensionsCheckup_Promo_Neutral[] = {
-    {extensions_features::kExtensionsCheckupBannerMessageParameter,
-     extensions_features::kNeutralMessage},
-    {extensions_features::kExtensionsCheckupEntryPointParameter,
-     extensions_features::kNtpPromoEntryPoint}};
-
-const FeatureEntry::FeatureVariation kExtensionsCheckupVariations[] = {
-    {"On Startup - Performance Focused Message",
-     kExtensionsCheckup_Startup_Performance,
-     base::size(kExtensionsCheckup_Startup_Performance), nullptr},
-    {"On Startup - Privacy Focused Message", kExtensionsCheckup_Startup_Privacy,
-     base::size(kExtensionsCheckup_Startup_Privacy), nullptr},
-    {"On Startup - Neutral Focused Message", kExtensionsCheckup_Startup_Neutral,
-     base::size(kExtensionsCheckup_Startup_Neutral), nullptr},
-    {"NTP Promo - Performance Focused Message",
-     kExtensionsCheckup_Promo_Performance,
-     base::size(kExtensionsCheckup_Promo_Performance), nullptr},
-    {"NTP Promo - Privacy Focused Message", kExtensionsCheckup_Promo_Privacy,
-     base::size(kExtensionsCheckup_Promo_Privacy), nullptr},
-    {"NTP Promo - Neutral Focused Message", kExtensionsCheckup_Promo_Neutral,
-     base::size(kExtensionsCheckup_Promo_Neutral), nullptr}};
-#endif  // ENABLE_EXTENSIONS
-
 // TODO(crbug.com/991082,1015377): Remove after proper support for back-forward
 // cache is implemented.
 const FeatureEntry::FeatureParam kBackForwardCache_ForceCaching[] = {
@@ -2768,11 +2720,6 @@
      SINGLE_VALUE_TYPE(switches::kEnableNaCl)},
 #endif  // ENABLE_NACL
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-    {"extension-checkup", flag_descriptions::kExtensionsCheckupName,
-     flag_descriptions::kExtensionsCheckupDescription, kOsDesktop,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(extensions_features::kExtensionsCheckup,
-                                    kExtensionsCheckupVariations,
-                                    "ExtensionsCheckup")},
     {"extensions-on-chrome-urls",
      flag_descriptions::kExtensionsOnChromeUrlsName,
      flag_descriptions::kExtensionsOnChromeUrlsDescription, kOsAll,
@@ -4711,7 +4658,8 @@
 
     {flag_descriptions::kScrollableTabStripFlagId,
      flag_descriptions::kScrollableTabStripName,
-     flag_descriptions::kScrollableTabStripDescription, kOsDesktop,
+     flag_descriptions::kScrollableTabStripDescription,
+     kOsMac | kOsWin | kOsLinux,
      FEATURE_WITH_PARAMS_VALUE_TYPE(features::kScrollableTabStrip,
                                     kTabScrollingVariations,
                                     "TabScrolling")},
@@ -4799,6 +4747,11 @@
     {"ntp-modules-redesigned", flag_descriptions::kNtpModulesRedesignedName,
      flag_descriptions::kNtpModulesRedesignedDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(ntp_features::kNtpModulesRedesigned)},
+
+    {"ntp-realbox-suggestion-answers",
+     flag_descriptions::kNtpRealboxSuggestionAnswersName,
+     flag_descriptions::kNtpRealboxSuggestionAnswersDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(omnibox::kNtpRealboxSuggestionAnswers)},
 #endif  // !defined(OS_ANDROID)
 
 #if defined(DCHECK_IS_CONFIGURABLE)
@@ -7512,6 +7465,15 @@
          ash::features::kHoldingSpaceInProgressDownloadsIntegration)},
 #endif
 
+#if defined(OS_WIN) || (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
+    defined(OS_MAC) || (defined(OS_ANDROID))
+    {"omnibox-updated-connection-security-indicators",
+     flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsName,
+     flag_descriptions::kOmniboxUpdatedConnectionSecurityIndicatorsDescription,
+     kOsDesktop | kOsAndroid,
+     FEATURE_VALUE_TYPE(omnibox::kUpdatedConnectionSecurityIndicators)},
+#endif
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/feed/v2/feed_stream.cc b/chrome/browser/android/feed/v2/feed_stream.cc
index a163511..85bcfcd 100644
--- a/chrome/browser/android/feed/v2/feed_stream.cc
+++ b/chrome/browser/android/feed/v2/feed_stream.cc
@@ -104,9 +104,15 @@
                             ScopedJavaGlobalRef<jobject>(callback_obj)));
 }
 
-void FeedStream::Refresh(JNIEnv* env,
-                         const JavaParamRef<jobject>& obj,
-                         const JavaParamRef<jobject>& callback_obj) {}
+void FeedStream::ManualRefresh(JNIEnv* env,
+                               const JavaParamRef<jobject>& obj,
+                               const JavaParamRef<jobject>& callback_obj) {
+  if (!feed_stream_api_)
+    return;
+  feed_stream_api_->ManualRefresh(
+      *this, base::BindOnce(&base::android::RunBooleanCallbackAndroid,
+                            ScopedJavaGlobalRef<jobject>(callback_obj)));
+}
 
 void FeedStream::ProcessThereAndBackAgain(
     JNIEnv* env,
diff --git a/chrome/browser/android/feed/v2/feed_stream.h b/chrome/browser/android/feed/v2/feed_stream.h
index 715ba7c7..613ca0f 100644
--- a/chrome/browser/android/feed/v2/feed_stream.h
+++ b/chrome/browser/android/feed/v2/feed_stream.h
@@ -45,9 +45,9 @@
                 const base::android::JavaParamRef<jobject>& obj,
                 const base::android::JavaParamRef<jobject>& callback_obj);
 
-  void Refresh(JNIEnv* env,
-               const base::android::JavaParamRef<jobject>& obj,
-               const base::android::JavaParamRef<jobject>& callback_obj);
+  void ManualRefresh(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj,
+                     const base::android::JavaParamRef<jobject>& callback_obj);
 
   void ProcessThereAndBackAgain(
       JNIEnv* env,
diff --git a/chrome/browser/android/history/browsing_history_bridge.cc b/chrome/browser/android/history/browsing_history_bridge.cc
index b5a6829..0111d2d 100644
--- a/chrome/browser/android/history/browsing_history_bridge.cc
+++ b/chrome/browser/android/history/browsing_history_bridge.cc
@@ -52,13 +52,15 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     const JavaParamRef<jobject>& j_result_obj,
-    jstring j_query) {
+    jstring j_query,
+    jboolean j_host_only) {
   j_query_result_obj_.Reset(env, j_result_obj);
   query_history_continuation_.Reset();
 
   history::QueryOptions options;
   options.max_count = kMaxQueryCount;
   options.duplicate_policy = history::QueryOptions::REMOVE_DUPLICATES_PER_DAY;
+  options.host_only = j_host_only;
 
   browsing_history_service_->QueryHistory(
       base::android::ConvertJavaStringToUTF16(env, j_query), options);
diff --git a/chrome/browser/android/history/browsing_history_bridge.h b/chrome/browser/android/history/browsing_history_bridge.h
index 80656a2..103ecd1 100644
--- a/chrome/browser/android/history/browsing_history_bridge.h
+++ b/chrome/browser/android/history/browsing_history_bridge.h
@@ -28,7 +28,8 @@
   void QueryHistory(JNIEnv* env,
                     const JavaParamRef<jobject>& obj,
                     const JavaParamRef<jobject>& j_result_obj,
-                    jstring j_query);
+                    jstring j_query,
+                    jboolean j_host_only);
 
   void QueryHistoryContinuation(JNIEnv* env,
                                 const JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
index fe0444e..f23b07b 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -10,9 +10,13 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/web_applications/components/app_registry_controller.h"
 #include "chrome/browser/web_applications/components/os_integration_manager.h"
 #include "chrome/browser/web_applications/components/web_app_shortcut_mac.h"
+#include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/common/chrome_switches.h"
 #include "net/base/filename_util.h"
 #include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h"
@@ -176,26 +180,46 @@
   if (params.protocol_handler_launch_url.has_value()) {
     GURL protocol_url = params.protocol_handler_launch_url.value();
 
-    auto launch_callback = base::BindOnce(
-        [](apps::AppLaunchParams params, Profile* profile, bool accepted) {
-          if (accepted) {
-            apps::AppServiceProxyFactory::GetForProfile(profile)
-                ->BrowserAppLauncher()
-                ->LaunchAppWithParams(std::move(params));
-          }
-        },
-        std::move(params), profile);
+    // Protocol handlers should prompt the user before launching the app,
+    // unless the user has granted permission to this protocol scheme
+    // previously.
+    if (!WebAppProvider::Get(profile)->registrar().IsApprovedLaunchProtocol(
+            app_id, protocol_url.scheme())) {
+      auto launch_callback = base::BindOnce(
+          [](apps::AppLaunchParams params, Profile* profile, bool accepted) {
+            if (accepted) {
+              web_app::WebAppProvider* provider =
+                  web_app::WebAppProvider::GetForWebApps(profile);
+              {
+                web_app::ScopedRegistryUpdate update(
+                    provider->registry_controller().AsWebAppSyncBridge());
+                web_app::WebApp* app_to_update =
+                    update->UpdateApp(params.app_id);
+                std::vector<std::string> protocol_handlers(
+                    app_to_update->approved_launch_protocols());
+                protocol_handlers.push_back(
+                    params.protocol_handler_launch_url.value().scheme());
+                app_to_update->SetApprovedLaunchProtocols(
+                    std::move(protocol_handlers));
+              }
+              apps::AppServiceProxyFactory::GetForProfile(profile)
+                  ->BrowserAppLauncher()
+                  ->LaunchAppWithParams(std::move(params));
+            }
+          },
+          std::move(params), profile);
 
-    // ShowWebAppProtocolHandlerIntentPicker keeps the `profile` alive through
-    // running of `launch_callback`.
-    chrome::ShowWebAppProtocolHandlerIntentPicker(
-        std::move(protocol_url), profile, app_id, std::move(launch_callback));
-
-  } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile)
-        ->BrowserAppLauncher()
-        ->LaunchAppWithParams(std::move(params));
+      // ShowWebAppProtocolHandlerIntentPicker keeps the `profile` alive through
+      // running of `launch_callback`.
+      chrome::ShowWebAppProtocolHandlerIntentPicker(
+          std::move(protocol_url), profile, app_id, std::move(launch_callback));
+      return;
+    }
   }
+
+  apps::AppServiceProxyFactory::GetForProfile(profile)
+      ->BrowserAppLauncher()
+      ->LaunchAppWithParams(std::move(params));
 }
 
 void WebAppShimManagerDelegate::LaunchShim(
diff --git a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
index 0b2a017..17f6981 100644
--- a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
+++ b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
@@ -72,7 +72,7 @@
   PrefService* local_state = g_browser_process->local_state();
   const base::DictionaryValue* const dict =
       local_state->GetDictionary(prefs::kAllKioskUsersToRemove);
-  for (const auto& it : dict->DictItems()) {
+  for (const auto it : dict->DictItems()) {
     std::string app_id;
     if (it.second.is_string())
       app_id = it.second.GetString();
diff --git a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
index 13270fc08..d8e8645 100644
--- a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
@@ -138,11 +138,9 @@
 
 KioskProfileLoader::KioskProfileLoader(const AccountId& app_account_id,
                                        KioskAppType app_type,
-                                       bool use_guest_mount,
                                        Delegate* delegate)
     : account_id_(app_account_id),
       app_type_(app_type),
-      use_guest_mount_(use_guest_mount),
       delegate_(delegate),
       failed_mount_attempts_(0) {}
 
@@ -159,16 +157,12 @@
   login_performer_ = std::make_unique<ChromeLoginPerformer>(this);
   switch (app_type_) {
     case KioskAppType::kArcApp:
-      // Arc kiosks do not support ephemeral mount.
-      DCHECK(!use_guest_mount_);
       login_performer_->LoginAsArcKioskAccount(account_id_);
       return;
     case KioskAppType::kChromeApp:
-      login_performer_->LoginAsKioskAccount(account_id_, use_guest_mount_);
+      login_performer_->LoginAsKioskAccount(account_id_);
       return;
     case KioskAppType::kWebApp:
-      // Web kiosks do not support ephemeral mount.
-      DCHECK(!use_guest_mount_);
       login_performer_->LoginAsWebKioskAccount(account_id_);
       return;
   }
diff --git a/chrome/browser/ash/app_mode/kiosk_profile_loader.h b/chrome/browser/ash/app_mode/kiosk_profile_loader.h
index efd3311..64178d6 100644
--- a/chrome/browser/ash/app_mode/kiosk_profile_loader.h
+++ b/chrome/browser/ash/app_mode/kiosk_profile_loader.h
@@ -42,7 +42,6 @@
 
   KioskProfileLoader(const AccountId& app_account_id,
                      KioskAppType app_type,
-                     bool use_guest_mount,
                      Delegate* delegate);
 
   ~KioskProfileLoader() override;
@@ -69,7 +68,6 @@
 
   const AccountId account_id_;
   const KioskAppType app_type_;
-  bool use_guest_mount_;
   Delegate* delegate_;
   int failed_mount_attempts_;
   std::unique_ptr<CryptohomedChecker> cryptohomed_checker_;
diff --git a/chrome/browser/ash/apps/apk_web_app_service.cc b/chrome/browser/ash/apps/apk_web_app_service.cc
index 8e1e47c..4522ea0 100644
--- a/chrome/browser/ash/apps/apk_web_app_service.cc
+++ b/chrome/browser/ash/apps/apk_web_app_service.cc
@@ -270,7 +270,7 @@
   // Search the pref dict for any |web_app_id| that has a value matching the
   // provided package name.
   std::string web_app_id;
-  for (const auto& it : web_apps_to_apks->DictItems()) {
+  for (const auto it : web_apps_to_apks->DictItems()) {
     const base::Value* v =
         it.second.FindKeyOfType(kPackageNameKey, base::Value::Type::STRING);
 
@@ -347,7 +347,7 @@
   // Search the pref dict for any |web_app_id| that has a value matching the
   // provided package name. We need to uninstall that |web_app_id|.
   std::string web_app_id;
-  for (const auto& it : web_apps_to_apks->DictItems()) {
+  for (const auto it : web_apps_to_apks->DictItems()) {
     const base::Value* v =
         it.second.FindKeyOfType(kPackageNameKey, base::Value::Type::STRING);
 
@@ -381,7 +381,7 @@
   if (!instance)
     return;
 
-  for (const auto& it : web_apps_to_apks->DictItems()) {
+  for (const auto it : web_apps_to_apks->DictItems()) {
     const base::Value* v =
         it.second.FindKeyOfType(kShouldRemoveKey, base::Value::Type::BOOLEAN);
 
diff --git a/chrome/browser/ash/arc/tracing/arc_system_model.cc b/chrome/browser/ash/arc/tracing/arc_system_model.cc
index 4948296..7b1c70d 100644
--- a/chrome/browser/ash/arc/tracing/arc_system_model.cc
+++ b/chrome/browser/ash/arc/tracing/arc_system_model.cc
@@ -25,7 +25,7 @@
   if (!value || !value->is_dict())
     return false;
 
-  for (const auto& it : value->DictItems()) {
+  for (const auto it : value->DictItems()) {
     int tid;
     if (sscanf(it.first.c_str(), "%d", &tid) != 1)
       return false;
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_event.cc b/chrome/browser/ash/arc/tracing/arc_tracing_event.cc
index 056b911..1bf88b9b 100644
--- a/chrome/browser/ash/arc/tracing/arc_tracing_event.cc
+++ b/chrome/browser/ash/arc/tracing/arc_tracing_event.cc
@@ -255,7 +255,7 @@
   const base::DictionaryValue* args = GetArgs();
   if (args) {
     bool first_arg = true;
-    for (const auto& arg : args->DictItems()) {
+    for (const auto arg : args->DictItems()) {
       if (first_arg) {
         result += "|";
         first_arg = false;
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
index 9fa1185..1a2d17f3 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
@@ -307,7 +307,7 @@
     return;
   }
 
-  for (const auto& kv : saved_workers->DictItems()) {
+  for (const auto kv : saved_workers->DictItems()) {
     const base::Value& saved_worker = kv.second;
 
     std::unique_ptr<CertProvisioningWorker> worker =
diff --git a/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
index 05aa2c37..40d12c4 100644
--- a/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
+++ b/chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.cc
@@ -74,7 +74,7 @@
 
   std::vector<UserConsentInfo> info_list;
 
-  for (const auto& entry : user_consent_info_dict_value->DictItems()) {
+  for (const auto entry : user_consent_info_dict_value->DictItems()) {
     const std::string& gaia_id = entry.first;
     const std::string& accepted_tos_version = entry.second.GetString();
     info_list.push_back(UserConsentInfo(gaia_id, accepted_tos_version));
diff --git a/chrome/browser/ash/crostini/crostini_mime_types_service.cc b/chrome/browser/ash/crostini/crostini_mime_types_service.cc
index 4a84657..789969e 100644
--- a/chrome/browser/ash/crostini/crostini_mime_types_service.cc
+++ b/chrome/browser/ash/crostini/crostini_mime_types_service.cc
@@ -74,7 +74,7 @@
   DictionaryPrefUpdate update(prefs_, prefs::kCrostiniMimeTypes);
   base::DictionaryValue* mime_type_mappings = update.Get();
   std::vector<std::string> removed_ids;
-  for (const auto& item : mime_type_mappings->DictItems()) {
+  for (const auto item : mime_type_mappings->DictItems()) {
     if (item.second.FindKey(kAppVmNameKey)->GetString() == vm_name &&
         (container_name.empty() ||
          item.second.FindKey(kAppContainerNameKey)->GetString() ==
@@ -128,7 +128,7 @@
     extensions->SetKey(extension_id, std::move(pref_mapping));
   }
 
-  for (const auto& item : extensions->DictItems()) {
+  for (const auto item : extensions->DictItems()) {
     if (item.second.FindKey(kAppVmNameKey)->GetString() ==
             mime_type_mappings.vm_name() &&
         item.second.FindKey(kAppContainerNameKey)->GetString() ==
diff --git a/chrome/browser/ash/crostini/crostini_shelf_utils.cc b/chrome/browser/ash/crostini/crostini_shelf_utils.cc
index 1f0f883..d841b504 100644
--- a/chrome/browser/ash/crostini/crostini_shelf_utils.cc
+++ b/chrome/browser/ash/crostini/crostini_shelf_utils.cc
@@ -69,7 +69,7 @@
                           bool need_display = false,
                           bool ignore_space = false) {
   result->clear();
-  for (const auto& item : prefs->DictItems()) {
+  for (const auto item : prefs->DictItems()) {
     if (item.first == kCrostiniTerminalSystemAppId)
       continue;
 
diff --git a/chrome/browser/ash/crostini/crostini_terminal.cc b/chrome/browser/ash/crostini/crostini_terminal.cc
index bb5d518..fd542c7c 100644
--- a/chrome/browser/ash/crostini/crostini_terminal.cc
+++ b/chrome/browser/ash/crostini/crostini_terminal.cc
@@ -219,7 +219,7 @@
 
   const base::DictionaryValue* settings = profile->GetPrefs()->GetDictionary(
       crostini::prefs::kCrostiniTerminalSettings);
-  for (const auto& item : settings->DictItems()) {
+  for (const auto item : settings->DictItems()) {
     // Only record settings for /hterm/profiles/default/.
     if (!base::StartsWith(item.first, kSettingPrefix,
                           base::CompareCase::SENSITIVE)) {
diff --git a/chrome/browser/ash/guest_os/guest_os_registry_service.cc b/chrome/browser/ash/guest_os/guest_os_registry_service.cc
index 5a8064a..d1c7666 100644
--- a/chrome/browser/ash/guest_os/guest_os_registry_service.cc
+++ b/chrome/browser/ash/guest_os/guest_os_registry_service.cc
@@ -563,7 +563,7 @@
                  GetTerminalRegistration(
                      apps->FindKeyOfType(crostini::kCrostiniTerminalSystemAppId,
                                          base::Value::Type::DICTIONARY)));
-  for (const auto& item : apps->DictItems()) {
+  for (const auto item : apps->DictItems()) {
     if (item.first != crostini::kCrostiniTerminalSystemAppId) {
       result.emplace(item.first, Registration(item.first, item.second.Clone()));
     }
@@ -656,7 +656,7 @@
   int num_crostini_apps = 0;
   int num_plugin_vm_apps = 0;
 
-  for (const auto& item : apps->DictItems()) {
+  for (const auto item : apps->DictItems()) {
     if (item.first == crostini::kCrostiniTerminalSystemAppId)
       continue;
 
@@ -826,7 +826,7 @@
     DictionaryPrefUpdate update(prefs_, guest_os::prefs::kGuestOsRegistry);
     base::DictionaryValue* apps = update.Get();
 
-    for (const auto& item : apps->DictItems()) {
+    for (const auto item : apps->DictItems()) {
       if (item.first == crostini::kCrostiniTerminalSystemAppId)
         continue;
       Registration registration(item.first, item.second.Clone());
@@ -934,7 +934,7 @@
       apps->SetKey(app_id, std::move(pref_registration));
     }
 
-    for (const auto& item : apps->DictItems()) {
+    for (const auto item : apps->DictItems()) {
       if (item.first == crostini::kCrostiniTerminalSystemAppId)
         continue;
       if (item.second.FindKey(guest_os::prefs::kAppVmNameKey)->GetString() ==
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path.cc b/chrome/browser/ash/guest_os/guest_os_share_path.cc
index 8fd8a50..9ad0a44 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path.cc
@@ -521,7 +521,7 @@
   const base::DictionaryValue* shared_paths =
       profile_->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms);
   CHECK(shared_paths);
-  for (const auto& it : shared_paths->DictItems()) {
+  for (const auto it : shared_paths->DictItems()) {
     base::FilePath path(it.first);
     for (const auto& vm : it.second.GetList()) {
       // Register all shared paths for all VMs since we want FilePathWatchers
@@ -553,7 +553,7 @@
   // E.g. if path /foo/bar is already shared, and then we share /foo, we
   // remove /foo/bar from the list since it will be shared as part of /foo.
   std::vector<base::FilePath> children;
-  for (const auto& it : shared_paths->DictItems()) {
+  for (const auto it : shared_paths->DictItems()) {
     base::FilePath shared(it.first);
     auto& vms = it.second;
     auto vm_matches = base::Contains(vms.GetList(), base::Value(vm_name));
@@ -612,7 +612,7 @@
   // of it then share them with any running VMs.
   const base::DictionaryValue* shared_paths =
       profile_->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms);
-  for (const auto& it : shared_paths->DictItems()) {
+  for (const auto it : shared_paths->DictItems()) {
     base::FilePath path(it.first);
     if (path != volume.mount_path() && !volume.mount_path().IsParent(path)) {
       continue;
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
index 2ac13af..a625335c 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
@@ -198,8 +198,7 @@
                                           weak_ptr_factory_.GetWeakPtr()));
 
   kiosk_profile_loader_ = std::make_unique<KioskProfileLoader>(
-      *kiosk_app_id_.account_id, kiosk_app_id_.type,
-      /*use_guest_mount=*/false, /*delegate=*/this);
+      *kiosk_app_id_.account_id, kiosk_app_id_.type, /*delegate=*/this);
   kiosk_profile_loader_->Start();
 }
 
diff --git a/chrome/browser/ash/login/challenge_response_auth_keys_loader.cc b/chrome/browser/ash/login/challenge_response_auth_keys_loader.cc
index 45f09fa8..21f1ec0 100644
--- a/chrome/browser/ash/login/challenge_response_auth_keys_loader.cc
+++ b/chrome/browser/ash/login/challenge_response_auth_keys_loader.cc
@@ -61,7 +61,7 @@
     return {};
 
   base::flat_set<std::string> extension_ids;
-  for (const auto& item : pref->GetValue()->DictItems())
+  for (const auto item : pref->GetValue()->DictItems())
     extension_ids.insert(item.first);
   return extension_ids;
 }
diff --git a/chrome/browser/ash/login/configuration_keys.cc b/chrome/browser/ash/login/configuration_keys.cc
index 7170096a..68a1614 100644
--- a/chrome/browser/ash/login/configuration_keys.cc
+++ b/chrome/browser/ash/login/configuration_keys.cc
@@ -172,7 +172,7 @@
       clone.RemoveKey(key.key);
     }
   }
-  for (const auto& item : clone.DictItems())
+  for (const auto item : clone.DictItems())
     LOG(WARNING) << "Unknown configuration key " << item.first;
   return valid;
 }
diff --git a/chrome/browser/ash/login/login_screen_extensions_lifetime_manager.cc b/chrome/browser/ash/login/login_screen_extensions_lifetime_manager.cc
index c2f4872..46b4ef4 100644
--- a/chrome/browser/ash/login/login_screen_extensions_lifetime_manager.cc
+++ b/chrome/browser/ash/login/login_screen_extensions_lifetime_manager.cc
@@ -43,7 +43,7 @@
     return {};
   }
   std::vector<std::string> extension_ids;
-  for (const auto& item : pref->GetValue()->DictItems())
+  for (const auto item : pref->GetValue()->DictItems())
     extension_ids.push_back(item.first);
   return extension_ids;
 }
diff --git a/chrome/browser/ash/login/login_screen_extensions_storage_cleaner.cc b/chrome/browser/ash/login/login_screen_extensions_storage_cleaner.cc
index ef3a249..93f6404 100644
--- a/chrome/browser/ash/login/login_screen_extensions_storage_cleaner.cc
+++ b/chrome/browser/ash/login/login_screen_extensions_storage_cleaner.cc
@@ -48,7 +48,7 @@
   if (pref && pref->IsManaged() &&
       pref->GetType() == base::Value::Type::DICTIONARY) {
     // Each `item` contains a pair of extension ID and update URL.
-    for (const auto& item : pref->GetValue()->DictItems())
+    for (const auto item : pref->GetValue()->DictItems())
       installed_extension_ids.push_back(item.first);
   }
   SessionManagerClient::Get()->LoginScreenStorageListKeys(base::BindOnce(
diff --git a/chrome/browser/ash/net/secure_dns_manager_unittest.cc b/chrome/browser/ash/net/secure_dns_manager_unittest.cc
index e622cfd..7238f7f 100644
--- a/chrome/browser/ash/net/secure_dns_manager_unittest.cc
+++ b/chrome/browser/ash/net/secure_dns_manager_unittest.cc
@@ -34,7 +34,7 @@
     base::Value* value = result->FindKeyOfType(
         shill::kDNSProxyDOHProvidersProperty, base::Value::Type::DICTIONARY);
     if (value != nullptr) {
-      for (const auto& kv : value->DictItems()) {
+      for (const auto kv : value->DictItems()) {
         props_out->emplace(kv.first, kv.second.GetString());
       }
     }
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service.cc b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service.cc
index 42da4e8..52dbca5 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service.cc
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service.cc
@@ -119,7 +119,7 @@
 
   // Search for "Policy" and "Recommended" keys in dict, perform some type
   // conversions on the sub-dicts and put them into |policy|.
-  for (const auto& it : dict.value().DictItems()) {
+  for (const auto it : dict.value().DictItems()) {
     const Level* level = FindMatchingLevel(it.first);
     if (!level) {
       LOG(WARNING) << "Unknown key '" << it.first
diff --git a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc
index c8af9bb4..fa69079 100644
--- a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc
+++ b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc
@@ -72,18 +72,5 @@
   return policy;
 }
 
-void SetExternalDataReference(CloudPolicyCore* core,
-                              const std::string& policy,
-                              base::DictionaryValue metadata) {
-  CloudPolicyStore* store = core->store();
-  ASSERT_TRUE(store);
-  PolicyMap policy_map;
-  policy_map.Set(policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                 POLICY_SOURCE_CLOUD, std::move(metadata),
-                 std::make_unique<ExternalDataFetcher>(
-                     store->external_data_manager(), policy));
-  store->SetPolicyMapForTesting(policy_map);
-}
-
 }  // namespace test
 }  // namespace policy
diff --git a/chrome/browser/ash/settings/about_flags.cc b/chrome/browser/ash/settings/about_flags.cc
index bb55386..1b7e302 100644
--- a/chrome/browser/ash/settings/about_flags.cc
+++ b/chrome/browser/ash/settings/about_flags.cc
@@ -68,7 +68,7 @@
     return origin_list_flags;
   }
 
-  for (const auto& entry : origin_list_flags_dict->DictItems()) {
+  for (const auto entry : origin_list_flags_dict->DictItems()) {
     if (!entry.second.is_string()) {
       LOG(WARNING) << "Invalid entry in encoded origin list flags";
       continue;
diff --git a/chrome/browser/ash/settings/device_settings_provider.cc b/chrome/browser/ash/settings/device_settings_provider.cc
index 0ecba65..10806ac 100644
--- a/chrome/browser/ash/settings/device_settings_provider.cc
+++ b/chrome/browser/ash/settings/device_settings_provider.cc
@@ -15,6 +15,7 @@
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
+#include "base/feature_list.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -481,13 +482,20 @@
 
 void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy,
                            PrefValueMap* new_values_cache) {
-  // kSignedDataRoamingEnabled has a default value of false.
-  new_values_cache->SetBoolean(
-      kSignedDataRoamingEnabled,
-      policy.has_data_roaming_enabled() &&
-          policy.data_roaming_enabled().has_data_roaming_enabled() &&
-          policy.data_roaming_enabled().data_roaming_enabled());
-
+  // Device-level cellular roaming should always be enabled for devices not
+  // enrolled in an enterprise policy when per-network cellular roaming
+  // configuration is enabled.
+  if (base::FeatureList::IsEnabled(
+          ash::features::kCellularAllowPerNetworkRoaming) &&
+      !chromeos::InstallAttributes::Get()->IsEnterpriseManaged()) {
+    new_values_cache->SetBoolean(kSignedDataRoamingEnabled, true);
+  } else {
+    new_values_cache->SetBoolean(
+        kSignedDataRoamingEnabled,
+        policy.has_data_roaming_enabled() &&
+            policy.data_roaming_enabled().has_data_roaming_enabled() &&
+            policy.data_roaming_enabled().data_roaming_enabled());
+  }
   if (policy.has_system_proxy_settings()) {
     const em::SystemProxySettingsProto& settings_proto(
         policy.system_proxy_settings());
diff --git a/chrome/browser/ash/settings/device_settings_provider_unittest.cc b/chrome/browser/ash/settings/device_settings_provider_unittest.cc
index efc9cf92..da8a79a 100644
--- a/chrome/browser/ash/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/ash/settings/device_settings_provider_unittest.cc
@@ -406,6 +406,13 @@
     BuildAndInstallDevicePolicy();
   }
 
+  void SetDeviceDataRoamingEnabled(bool data_roaming_enabled) {
+    em::DataRoamingEnabledProto* proto =
+        device_policy_->payload().mutable_data_roaming_enabled();
+    proto->set_data_roaming_enabled(data_roaming_enabled);
+    BuildAndInstallDevicePolicy();
+  }
+
   void VerifyDevicePrinterList(const char* policy_key,
                                std::vector<std::string>& values) {
     base::Value list(base::Value::Type::LIST);
@@ -1282,6 +1289,48 @@
   VerifyPolicyValue(kDeviceScheduledReboot, &expected_val);
 }
 
+TEST_F(DeviceSettingsProviderTest, DataRoamingEnabledWithFeatureFlag) {
+  base::test::ScopedFeatureList scoped_feature_list(
+      ash::features::kCellularAllowPerNetworkRoaming);
+  SetDeviceDataRoamingEnabled(false);
+
+  profile_->ScopedCrosSettingsTestHelper()
+      ->InstallAttributes()
+      ->SetCloudManaged(policy::PolicyBuilder::kFakeDomain,
+                        policy::PolicyBuilder::kFakeDeviceId);
+  BuildAndInstallDevicePolicy();
+
+  // Cloud managed device value.
+  const base::Value* value = provider_->Get(kSignedDataRoamingEnabled);
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_bool());
+  EXPECT_FALSE(value->GetBool());
+
+  profile_->ScopedCrosSettingsTestHelper()
+      ->InstallAttributes()
+      ->SetConsumerOwned();
+  BuildAndInstallDevicePolicy();
+
+  // Consumer owned device value.
+  value = provider_->Get(kSignedDataRoamingEnabled);
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->GetBool());
+}
+
+TEST_F(DeviceSettingsProviderTest, DataRoamingEnabledWithoutFeatureFlag) {
+  SetDeviceDataRoamingEnabled(false);
+
+  profile_->ScopedCrosSettingsTestHelper()
+      ->InstallAttributes()
+      ->SetConsumerOwned();
+
+  // Consumer owned device value.
+  const base::Value* value = provider_->Get(kSignedDataRoamingEnabled);
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_bool());
+  EXPECT_FALSE(value->GetBool());
+}
+
 // Checks that content_protection decodes correctly.
 TEST_F(DeviceSettingsProviderTest, DecodeContentProtectionDefault) {
   BuildAndInstallDevicePolicy();
diff --git a/chrome/browser/ash/system_logs/crosapi_system_log_source.cc b/chrome/browser/ash/system_logs/crosapi_system_log_source.cc
index 25703c4..6826b076 100644
--- a/chrome/browser/ash/system_logs/crosapi_system_log_source.cc
+++ b/chrome/browser/ash/system_logs/crosapi_system_log_source.cc
@@ -45,7 +45,7 @@
   DCHECK(system_infos.is_dict());
   const base::DictionaryValue* sysinfo_dict;
   if (system_infos.GetAsDictionary(&sysinfo_dict)) {
-    for (const auto& item : sysinfo_dict->DictItems()) {
+    for (const auto item : sysinfo_dict->DictItems()) {
       std::string log_entry_key = kLacrosLogEntryPrefix + item.first;
       if (item.second.is_string()) {
         response->emplace(log_entry_key, item.second.GetString());
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
index 3341724..aab4d5d 100644
--- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -89,7 +89,7 @@
         content::WebContents::FromRenderFrameHost(frame);
     BrowserAutofillManager* autofill_manager =
         ContentAutofillDriverFactory::FromWebContents(web_contents)
-            ->DriverForFrame(frame)
+            ->DriverForFrame(frame->GetMainFrame())
             ->browser_autofill_manager();
     autofill_manager->SetTestDelegate(test_delegate());
 
@@ -191,6 +191,12 @@
   // InProcessBrowserTest:
   void SetUpOnMainThread() override {
     AutofillUiTest::SetUpOnMainThread();
+    if (base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
+      test_delegate()->SetIgnoreBackToBackMessages(
+          ObservedUiEvents::kPreviewFormData, true);
+      test_delegate()->SetIgnoreBackToBackMessages(
+          ObservedUiEvents::kFormDataFilled, true);
+    }
     recipe_replayer_ =
         std::make_unique<captured_sites_test_utils::TestRecipeReplayer>(
             browser(), this);
@@ -228,7 +234,8 @@
     // prediction. Test will check this attribute on all the relevant input
     // elements in a form to determine if the form is ready for interaction.
     feature_list_.InitWithFeatures(
-        /*enabled_features=*/{features::kAutofillShowTypePredictions},
+        /*enabled_features=*/{features::kAutofillAcrossIframes,
+                              features::kAutofillShowTypePredictions},
         /*disabled_features=*/{});
     command_line->AppendSwitchASCII(
         variations::switches::kVariationsOverrideCountry, "us");
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 76df200..d92ce95 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -1252,9 +1252,7 @@
   ExpectFilledTestForm();
 }
 
-class AutofillCompanyInteractiveTest
-    : public AutofillInteractiveTestBase,
-      public testing::WithParamInterface<bool> {
+class AutofillCompanyInteractiveTest : public AutofillInteractiveTestBase {
  protected:
   AutofillCompanyInteractiveTest() = default;
   ~AutofillCompanyInteractiveTest() override = default;
@@ -2733,6 +2731,8 @@
 #endif
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveIsolationTest,
                        MAYBE_SimpleCrossSiteFill) {
+  test_delegate()->SetIgnoreBackToBackMessages(
+      ObservedUiEvents::kPreviewFormData, true);
   CreateTestProfile();
 
   // Main frame is on a.com, iframe is on b.com.
@@ -2741,9 +2741,13 @@
   ui_test_utils::NavigateToURL(browser(), url);
   GURL iframe_url = embedded_test_server()->GetURL(
       "b.com", "/autofill/autofill_test_form.html");
+
   EXPECT_TRUE(
       content::NavigateIframeToURL(GetWebContents(), "crossFrame", iframe_url));
 
+  // Wait to make sure the cross-frame form is parsed.
+  DoNothingAndWait(2);
+
   // Let |test_delegate()| also observe autofill events in the iframe.
   content::RenderFrameHost* cross_frame =
       RenderFrameHostForName(GetWebContents(), "crossFrame");
@@ -2863,7 +2867,11 @@
   EXPECT_FALSE(IsPopupShown());
 }
 
-class AutofillDynamicFormInteractiveTest : public AutofillInteractiveTestBase {
+// The boolean parameter controls whether or not
+// features::kAutofillAcrossIframes is enabled.
+class AutofillDynamicFormInteractiveTest
+    : public AutofillInteractiveTestBase,
+      public testing::WithParamInterface<bool> {
  public:
   AutofillDynamicFormInteractiveTest(
       const AutofillDynamicFormInteractiveTest&) = delete;
@@ -2872,6 +2880,11 @@
 
  protected:
   AutofillDynamicFormInteractiveTest() {
+    std::vector<base::Feature> enabled;
+    std::vector<base::Feature> disabled;
+    (GetParam() ? enabled : disabled)
+        .push_back(features::kAutofillAcrossIframes);
+    scoped_feature_.InitWithFeatures(enabled, disabled);
     // Setup that the test expects a re-fill to happen.
     test_delegate()->SetIsExpectingDynamicRefill(true);
   }
@@ -2887,20 +2900,32 @@
     // load pages from "a.com" without an interstitial.
     command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
   }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_;
 };
 
+// The boolean parameters indicate whether features::kAutofillAcrossIframes and
+// features::kAutofillRefillWithRendererIds, respectively, are enabled.
 class AutofillDynamicFormReplacementInteractiveTest
     : public AutofillInteractiveTestBase,
-      public testing::WithParamInterface<bool> {
+      public testing::WithParamInterface<std::tuple<bool, bool>> {
  public:
   AutofillDynamicFormReplacementInteractiveTest()
-      : refill_with_renderer_ids_(GetParam()) {
-    scoped_feature_.InitWithFeatureState(
-        features::kAutofillRefillWithRendererIds, refill_with_renderer_ids_);
+      : autofill_across_iframes_(std::get<0>(GetParam())),
+        refill_with_renderer_ids_(std::get<1>(GetParam())) {
+    std::vector<base::Feature> enabled;
+    std::vector<base::Feature> disabled;
+    (autofill_across_iframes_ ? enabled : disabled)
+        .push_back(features::kAutofillAcrossIframes);
+    (refill_with_renderer_ids_ ? enabled : disabled)
+        .push_back(features::kAutofillRefillWithRendererIds);
+    scoped_feature_.InitWithFeatures(enabled, disabled);
   }
 
  protected:
-  bool refill_with_renderer_ids_;
+  const bool autofill_across_iframes_;
+  const bool refill_with_renderer_ids_;
   base::test::ScopedFeatureList scoped_feature_;
 };
 
@@ -3023,7 +3048,7 @@
 }
 
 // Test that forms that dynamically change after a second do not get filled.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_AfterDelay) {
   CreateTestProfile();
 
@@ -3090,7 +3115,7 @@
 
 // Test that we can autofill forms that dynamically change select fields to text
 // fields by changing the visibilities.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_SelectToText) {
   CreateTestProfile();
 
@@ -3116,7 +3141,7 @@
 
 // Test that we can autofill forms that dynamically change the visibility of a
 // field after it's autofilled.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_VisibilitySwitch) {
   CreateTestProfile();
 
@@ -3144,7 +3169,7 @@
 
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_FirstElementDisappears) {
   CreateTestProfile();
 
@@ -3170,7 +3195,7 @@
 
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on, even though the form has no name.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_FirstElementDisappearsNoNameForm) {
   CreateTestProfile();
 
@@ -3197,7 +3222,7 @@
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on, even though there are multiple forms with identical
 // names.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     AutofillDynamicFormInteractiveTest,
     DynamicFormFill_FirstElementDisappearsMultipleBadNameForms) {
   CreateTestProfile();
@@ -3230,7 +3255,7 @@
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on, even though there are multiple forms with identical
 // names.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_FirstElementDisappearsBadnameUnowned) {
   CreateTestProfile();
 
@@ -3260,7 +3285,7 @@
 
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on, even though there are multiple forms with no name.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     AutofillDynamicFormInteractiveTest,
     DynamicFormFill_FirstElementDisappearsMultipleNoNameForms) {
   CreateTestProfile();
@@ -3292,7 +3317,7 @@
 
 // Test that we can autofill forms that dynamically change the element that
 // has been clicked on, even though the elements are unowned.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicFormFill_FirstElementDisappearsUnowned) {
   CreateTestProfile();
 
@@ -3356,7 +3381,7 @@
 
 // Test that we can Autofill dynamically changing selects that have options
 // added and removed.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_SelectUpdated) {
   CreateTestProfile();
 
@@ -3384,7 +3409,7 @@
 
 // Test that we can Autofill dynamically changing selects that have options
 // added and removed only once.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_DoubleSelectUpdated) {
   CreateTestProfile();
 
@@ -3447,7 +3472,7 @@
 // Test that we can Autofill dynamically changing selects that have options
 // added and removed for forms with no names if the NameForAutofill of the first
 // field matches.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_SelectUpdated_FormWithoutName) {
   CreateTestProfile();
 
@@ -3476,7 +3501,7 @@
 
 // Test that we can Autofill dynamically generated synthetic forms if the
 // NameForAutofill of the first field matches.
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_SyntheticForm) {
   CreateTestProfile();
 
@@ -3504,7 +3529,7 @@
 
 // Test that we can Autofill dynamically synthetic forms when the select options
 // change if the NameForAutofill of the first field matches
-IN_PROC_BROWSER_TEST_F(AutofillDynamicFormInteractiveTest,
+IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest,
                        DynamicChangingFormFill_SelectUpdated_SyntheticForm) {
   CreateTestProfile();
 
@@ -3586,7 +3611,11 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
-                         AutofillDynamicFormReplacementInteractiveTest,
+                         AutofillDynamicFormInteractiveTest,
                          testing::Bool());
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         AutofillDynamicFormReplacementInteractiveTest,
+                         testing::Combine(testing::Bool(), testing::Bool()));
+
 }  // namespace autofill
diff --git a/chrome/browser/autofill/mock_autofill_popup_controller.h b/chrome/browser/autofill/mock_autofill_popup_controller.h
index 25c6f88..511b784 100644
--- a/chrome/browser/autofill/mock_autofill_popup_controller.h
+++ b/chrome/browser/autofill/mock_autofill_popup_controller.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 6123cfe..727b580 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -155,6 +155,9 @@
   force_installed_tracker_observation_.Reset();
   DCHECK(!profile_keep_alive_);
   profile_ = nullptr;
+  // Remove this Profile* from |background_mode_data|.
+  bool did_unregister = manager_->UnregisterProfile(profile);
+  DCHECK(did_unregister);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -408,6 +411,26 @@
     UpdateStatusTrayIconContextMenu();
 }
 
+bool BackgroundModeManager::UnregisterProfile(Profile* profile) {
+  // Remove the profile from our map of profiles.
+  auto it = background_mode_data_.find(profile);
+  // If a profile isn't running a background app, it may not be in the map.
+  if (it == background_mode_data_.end())
+    return false;
+
+  it->second->applications()->RemoveObserver(this);
+  background_mode_data_.erase(it);
+  // If there are no background mode profiles any longer, then turn off
+  // background mode.
+  UpdateEnableLaunchOnStartup();
+  if (!ShouldBeInBackgroundMode()) {
+    EndBackgroundMode();
+  }
+  UpdateStatusTrayIconContextMenu();
+
+  return true;
+}
+
 // static
 void BackgroundModeManager::LaunchBackgroundApplication(
     Profile* profile,
@@ -548,24 +571,10 @@
 
 void BackgroundModeManager::OnProfileWillBeRemoved(
     const base::FilePath& profile_path) {
-  ProfileAttributesEntry* entry =
-      profile_storage_->GetProfileAttributesWithPath(profile_path);
-  DCHECK(entry);
-  std::u16string profile_name = entry->GetName();
-  // Remove the profile from our map of profiles.
-  auto it = GetBackgroundModeIterator(profile_name);
-  // If a profile isn't running a background app, it may not be in the map.
-  if (it != background_mode_data_.end()) {
-    it->second->applications()->RemoveObserver(this);
-    background_mode_data_.erase(it);
-    // If there are no background mode profiles any longer, then turn off
-    // background mode.
-    UpdateEnableLaunchOnStartup();
-    if (!ShouldBeInBackgroundMode()) {
-      EndBackgroundMode();
-    }
-    UpdateStatusTrayIconContextMenu();
-  }
+  Profile* profile =
+      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
+  DCHECK(profile);
+  UnregisterProfile(profile);
 }
 
 void BackgroundModeManager::OnProfileNameChanged(
diff --git a/chrome/browser/background/background_mode_manager.h b/chrome/browser/background/background_mode_manager.h
index 2b03e5a..4b6c6fc 100644
--- a/chrome/browser/background/background_mode_manager.h
+++ b/chrome/browser/background/background_mode_manager.h
@@ -75,7 +75,13 @@
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
-  virtual void RegisterProfile(Profile* profile);
+  // Adds an entry for |profile| to |background_mode_data_|, and starts tracking
+  // events for this profile.
+  void RegisterProfile(Profile* profile);
+
+  // Removes the entry for |profile| from |background_mode_data_|, if present.
+  // Returns true if a removal was performed.
+  bool UnregisterProfile(Profile* profile);
 
   static void LaunchBackgroundApplication(
       Profile* profile,
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index 00a07a91..4d0c204 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -132,13 +132,6 @@
   NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
 #endif
 
-#if defined(TOOLKIT_VIEWS)
-  // Notification that the nested loop using during tab dragging has returned.
-  // Used for testing.
-  // TODO(https://crbug.com/1174797): Remove.
-  NOTIFICATION_TAB_DRAG_LOOP_DONE,
-#endif
-
   // Sent when the applications in the NTP app launcher have been reordered.
   // The details, if not NoDetails, is the std::string ID of the extension that
   // was moved.
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 02d9cdea..fa9447bb 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3308,6 +3308,8 @@
       "chromebox_for_meetings/logger/cfm_logger_service.h",
       "chromebox_for_meetings/logger/reporting_pipeline.cc",
       "chromebox_for_meetings/logger/reporting_pipeline.h",
+      "chromebox_for_meetings/network_settings/network_settings_service.cc",
+      "chromebox_for_meetings/network_settings/network_settings_service.h",
       "chromebox_for_meetings/service_adaptor.cc",
       "chromebox_for_meetings/service_adaptor.h",
     ]
diff --git a/chrome/browser/chromeos/chromebox_for_meetings/cfm_chrome_services.cc b/chrome/browser/chromeos/chromebox_for_meetings/cfm_chrome_services.cc
index ffe0efb..6729467 100644
--- a/chrome/browser/chromeos/chromebox_for_meetings/cfm_chrome_services.cc
+++ b/chrome/browser/chromeos/chromebox_for_meetings/cfm_chrome_services.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/chromeos/chromebox_for_meetings/device_info/device_info_service.h"
 #include "chrome/browser/chromeos/chromebox_for_meetings/diagnostics/diagnostics_service.h"
 #include "chrome/browser/chromeos/chromebox_for_meetings/logger/cfm_logger_service.h"
+#include "chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.h"
 #include "chromeos/components/chromebox_for_meetings/features/features.h"
 #include "chromeos/dbus/chromebox_for_meetings/cfm_hotline_client.h"
 
@@ -24,6 +25,7 @@
   CfmLoggerService::Initialize();
   DeviceInfoService::Initialize();
   DiagnosticsService::Initialize();
+  NetworkSettingsService::Initialize();
 }
 
 void ShutdownCfmServices() {
@@ -32,6 +34,7 @@
     return;
   }
 
+  NetworkSettingsService::Shutdown();
   DiagnosticsService::Shutdown();
   DeviceInfoService::Shutdown();
   CfmLoggerService::Shutdown();
diff --git a/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.cc b/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.cc
new file mode 100644
index 0000000..917f0b4
--- /dev/null
+++ b/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.cc
@@ -0,0 +1,73 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.h"
+
+#include <utility>
+
+#include "base/macros.h"
+#include "base/notreached.h"
+#include "chromeos/dbus/chromebox_for_meetings/cfm_hotline_client.h"
+
+namespace chromeos {
+namespace cfm {
+
+namespace {
+NetworkSettingsService* g_network_settings_service = nullptr;
+}  // namespace
+
+NetworkSettingsService::NetworkSettingsService()
+    : service_adaptor_(mojom::CfmNetworkSettings::Name_, this) {
+  CfmHotlineClient::Get()->AddObserver(this);
+}
+
+NetworkSettingsService::~NetworkSettingsService() {
+  CfmHotlineClient::Get()->RemoveObserver(this);
+}
+
+void NetworkSettingsService::Initialize() {
+  CHECK(!g_network_settings_service);
+  g_network_settings_service = new NetworkSettingsService();
+}
+
+void NetworkSettingsService::Shutdown() {
+  CHECK(g_network_settings_service);
+  delete g_network_settings_service;
+  g_network_settings_service = nullptr;
+}
+
+NetworkSettingsService* NetworkSettingsService::Get() {
+  return g_network_settings_service;
+}
+
+bool NetworkSettingsService::IsInitialized() {
+  return g_network_settings_service;
+}
+
+void NetworkSettingsService::ShowDialog() {
+  // TODO(b/35772861): Displays the dialog if not already open.
+  NOTIMPLEMENTED();
+}
+
+bool NetworkSettingsService::ServiceRequestReceived(
+    const std::string& interface_name) {
+  if (interface_name != mojom::CfmNetworkSettings::Name_) {
+    return false;
+  }
+  service_adaptor_.BindServiceAdaptor();
+  return true;
+}
+
+void NetworkSettingsService::OnBindService(
+    mojo::ScopedMessagePipeHandle receiver_pipe) {
+  receivers_.Add(this, mojo::PendingReceiver<mojom::CfmNetworkSettings>(
+                           std::move(receiver_pipe)));
+}
+
+void NetworkSettingsService::OnAdaptorDisconnect() {
+  receivers_.Clear();
+}
+
+}  // namespace cfm
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.h b/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.h
new file mode 100644
index 0000000..e5d151b
--- /dev/null
+++ b/chrome/browser/chromeos/chromebox_for_meetings/network_settings/network_settings_service.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CHROMEBOX_FOR_MEETINGS_NETWORK_SETTINGS_NETWORK_SETTINGS_SERVICE_H_
+#define CHROME_BROWSER_CHROMEOS_CHROMEBOX_FOR_MEETINGS_NETWORK_SETTINGS_NETWORK_SETTINGS_SERVICE_H_
+
+#include <string>
+
+#include "chrome/browser/chromeos/chromebox_for_meetings/service_adaptor.h"
+#include "chromeos/dbus/chromebox_for_meetings/cfm_observer.h"
+#include "chromeos/services/chromebox_for_meetings/public/mojom/cfm_network_settings.mojom.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace chromeos {
+namespace cfm {
+
+// Hotline service allowing CFMs to open the network settings dialog from Meet.
+class NetworkSettingsService : public CfmObserver,
+                               public ServiceAdaptor::Delegate,
+                               public mojom::CfmNetworkSettings {
+ public:
+  ~NetworkSettingsService() override;
+
+  NetworkSettingsService(const NetworkSettingsService&) = delete;
+  NetworkSettingsService& operator=(const NetworkSettingsService&) = delete;
+
+  static void Initialize();
+  static void Shutdown();
+  static NetworkSettingsService* Get();
+  static bool IsInitialized();
+
+  // mojom::CfmNetworkSettings implementation
+  void ShowDialog() override;
+
+  // CfmObserver implementation
+  bool ServiceRequestReceived(const std::string& interface_name) override;
+
+  // ServiceAdaptorDelegate implementation
+  void OnBindService(mojo::ScopedMessagePipeHandle receiver_pipe) override;
+  void OnAdaptorDisconnect() override;
+
+ private:
+  NetworkSettingsService();
+
+  ServiceAdaptor service_adaptor_;
+  mojo::ReceiverSet<mojom::CfmNetworkSettings> receivers_;
+};
+
+}  // namespace cfm
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CHROMEBOX_FOR_MEETINGS_NETWORK_SETTINGS_NETWORK_SETTINGS_SERVICE_H_
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
index fee92895..d7bb140 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
@@ -709,13 +709,13 @@
           continue;
         }
         // Try to read as string.
-        std::string permission_string;
-        if (!entry.GetAsString(&permission_string)) {
+        if (!entry.is_string()) {
           LOG(ERROR) << extension->id() << ": " << it.key()
                      << " contains a token that's neither a string nor a dict.";
           safe = false;
           continue;
         }
+        const std::string permission_string = entry.GetString();
         // Log permission (usual, string form).
         LogPermissionUmaStats(permission_string);
         // Accept whitelisted permissions.
diff --git a/chrome/browser/chromeos/extensions/extensions_permissions_tracker.cc b/chrome/browser/chromeos/extensions/extensions_permissions_tracker.cc
index 3c83eae..a61ab87 100644
--- a/chrome/browser/chromeos/extensions/extensions_permissions_tracker.cc
+++ b/chrome/browser/chromeos/extensions/extensions_permissions_tracker.cc
@@ -50,7 +50,7 @@
   extension_safety_ratings_.clear();
   pending_forced_extensions_.clear();
 
-  for (const auto& entry : value->DictItems()) {
+  for (const auto entry : value->DictItems()) {
     const ExtensionId& extension_id = entry.first;
     // By default the extension permissions are assumed to trigger full warning
     // (false). When the extension is loaded, if all of its permissions is safe,
diff --git a/chrome/browser/chromeos/extensions/external_cache_impl.cc b/chrome/browser/chromeos/extensions/external_cache_impl.cc
index 8ef75eb19..17efc5e 100644
--- a/chrome/browser/chromeos/extensions/external_cache_impl.cc
+++ b/chrome/browser/chromeos/extensions/external_cache_impl.cc
@@ -248,7 +248,7 @@
   }
 
   cached_extensions_->Clear();
-  for (const auto& entry : extensions_->DictItems()) {
+  for (const auto entry : extensions_->DictItems()) {
     if (!entry.second.is_dict()) {
       LOG(ERROR) << "ExternalCacheImpl found bad entry with type "
                  << entry.second.type();
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index 586efb0..955ca96 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -739,7 +739,8 @@
     base::DictionaryValue dict;
     std::string highlight;
     base::Value* value = entry.FindKey("fileFullPath");
-    if (value && value->GetAsString(&highlight)) {
+    if (value && value->is_string()) {
+      highlight = value->GetString();
       base::FilePath path(highlight);
       if (!drive::internal::FindAndHighlight(path.BaseName().value(), queries,
                                              &highlight)) {
diff --git a/chrome/browser/chromeos/extensions/public_session_permission_helper.cc b/chrome/browser/chromeos/extensions/public_session_permission_helper.cc
index b7132afc..f1164a0 100644
--- a/chrome/browser/chromeos/extensions/public_session_permission_helper.cc
+++ b/chrome/browser/chromeos/extensions/public_session_permission_helper.cc
@@ -65,9 +65,10 @@
                              APIPermissionID permission);
 
  private:
-  void ResolvePermissionPrompt(const ExtensionInstallPrompt* prompt,
-                               const PermissionIDSet& unprompted_permissions,
-                               ExtensionInstallPrompt::Result prompt_result);
+  void ResolvePermissionPrompt(
+      const ExtensionInstallPrompt* prompt,
+      const PermissionIDSet& unprompted_permissions,
+      ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   PermissionIDSet FilterAllowedPermissions(const PermissionIDSet& permissions);
 
@@ -185,10 +186,11 @@
 void PublicSessionPermissionHelper::ResolvePermissionPrompt(
     const ExtensionInstallPrompt* prompt,
     const PermissionIDSet& unprompted_permissions,
-    ExtensionInstallPrompt::Result prompt_result) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
   PermissionIDSet& add_to_set =
-      prompt_result == ExtensionInstallPrompt::Result::ACCEPTED ?
-          allowed_permission_set_ : denied_permission_set_;
+      payload.result == ExtensionInstallPrompt::Result::ACCEPTED
+          ? allowed_permission_set_
+          : denied_permission_set_;
   for (const auto& permission : unprompted_permissions) {
     prompted_permission_set_.erase(permission.id());
     add_to_set.insert(permission.id());
diff --git a/chrome/browser/chromeos/extensions/public_session_permission_helper_unittest.cc b/chrome/browser/chromeos/extensions/public_session_permission_helper_unittest.cc
index 9c0e4c6..9a75d60 100644
--- a/chrome/browser/chromeos/extensions/public_session_permission_helper_unittest.cc
+++ b/chrome/browser/chromeos/extensions/public_session_permission_helper_unittest.cc
@@ -31,6 +31,7 @@
 using extensions::Extension;
 using extensions::Manifest;
 using Result = ExtensionInstallPrompt::Result;
+using DoneCallbackPayload = ExtensionInstallPrompt::DoneCallbackPayload;
 using extensions::mojom::APIPermissionID;
 
 namespace extensions {
@@ -86,8 +87,8 @@
     did_show_dialog = true;
   }
 
-  void Resolve(ExtensionInstallPrompt::Result result) {
-    std::move(done_callback_).Run(result);
+  void Resolve(ExtensionInstallPrompt::DoneCallbackPayload payload) {
+    std::move(done_callback_).Run(payload);
   }
 
  private:
@@ -181,7 +182,7 @@
   auto prompt = CallHandlePermissionRequest(extension_a_, {permission_a});
   EXPECT_TRUE(prompt);
   EXPECT_TRUE(get_did_show_dialog_and_reset());
-  prompt->Resolve(Result::ACCEPTED);
+  prompt->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_TRUE(allowed_permissions_.at(0).Equals({permission_a}));
 
   // permission_a was already allowed for extension_a hence no prompt is being
@@ -196,7 +197,7 @@
   prompt = CallHandlePermissionRequest(extension_b_, {permission_a});
   EXPECT_TRUE(prompt);
   EXPECT_TRUE(get_did_show_dialog_and_reset());
-  prompt->Resolve(Result::USER_CANCELED);
+  prompt->Resolve(DoneCallbackPayload(Result::USER_CANCELED));
   EXPECT_TRUE(allowed_permissions_.at(2).Equals({}));
 }
 
@@ -205,7 +206,7 @@
   auto prompt = CallHandlePermissionRequest(extension_a_, {permission_a});
   EXPECT_TRUE(prompt);
   EXPECT_TRUE(get_did_show_dialog_and_reset());
-  prompt->Resolve(Result::USER_CANCELED);
+  prompt->Resolve(DoneCallbackPayload(Result::USER_CANCELED));
   EXPECT_TRUE(allowed_permissions_.at(0).Equals({}));
 
   // Still denied (previous choice is remembered).
@@ -217,7 +218,7 @@
   prompt = CallHandlePermissionRequest(extension_b_, {permission_a});
   EXPECT_TRUE(prompt);
   EXPECT_TRUE(get_did_show_dialog_and_reset());
-  prompt->Resolve(Result::ACCEPTED);
+  prompt->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_TRUE(allowed_permissions_.at(2).Equals({permission_a}));
 }
 
@@ -232,7 +233,7 @@
   // prompt1 resolves both permission requests (second permission request
   // doesn't show a prompt as permission_b is already prompted by first
   // permission request).
-  prompt1->Resolve(Result::ACCEPTED);
+  prompt1->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_TRUE(allowed_permissions_.at(0).Equals({permission_a, permission_b}));
   EXPECT_TRUE(allowed_permissions_.at(1).Equals({permission_b}));
 }
@@ -247,9 +248,9 @@
   EXPECT_TRUE(get_did_show_dialog_and_reset());
   // prompt2 resolves only permission_b because prompt1 already prompted for
   // permission_a.
-  prompt2->Resolve(Result::ACCEPTED);
+  prompt2->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_EQ(allowed_permissions_.size(), 0u);
-  prompt1->Resolve(Result::ACCEPTED);
+  prompt1->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_TRUE(allowed_permissions_.at(0).Equals({permission_a}));
   EXPECT_TRUE(allowed_permissions_.at(1).Equals({permission_a, permission_b}));
 }
@@ -262,9 +263,9 @@
       CallHandlePermissionRequest(extension_a_, {permission_a, permission_b});
   EXPECT_TRUE(prompt2);
   EXPECT_TRUE(get_did_show_dialog_and_reset());
-  prompt1->Resolve(Result::USER_CANCELED);
+  prompt1->Resolve(DoneCallbackPayload(Result::USER_CANCELED));
   EXPECT_TRUE(allowed_permissions_.at(0).Equals({}));
-  prompt2->Resolve(Result::ACCEPTED);
+  prompt2->Resolve(DoneCallbackPayload(Result::ACCEPTED));
   EXPECT_TRUE(allowed_permissions_.at(1).Equals({permission_b}));
 }
 
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
index 108f291..ad7620c 100644
--- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -326,9 +326,9 @@
 
     EXPECT_TRUE(result->is_list());
     for (const base::Value& value : result->GetList()) {
-      std::string mode;
-      EXPECT_TRUE(value.GetAsString(&mode));
-      modes.push_back(quick_unlock_private::ParseQuickUnlockMode(mode));
+      EXPECT_TRUE(value.is_string());
+      modes.push_back(
+          quick_unlock_private::ParseQuickUnlockMode(value.GetString()));
     }
 
     return modes;
@@ -344,9 +344,9 @@
 
     EXPECT_TRUE(result->is_list());
     for (const base::Value& value : result->GetList()) {
-      std::string mode;
-      EXPECT_TRUE(value.GetAsString(&mode));
-      modes.push_back(quick_unlock_private::ParseQuickUnlockMode(mode));
+      EXPECT_TRUE(value.is_string());
+      modes.push_back(
+          quick_unlock_private::ParseQuickUnlockMode(value.GetString()));
     }
 
     return modes;
diff --git a/chrome/browser/chromeos/extensions/test_external_cache.cc b/chrome/browser/chromeos/extensions/test_external_cache.cc
index c47b9ae1..d12b023 100644
--- a/chrome/browser/chromeos/extensions/test_external_cache.cc
+++ b/chrome/browser/chromeos/extensions/test_external_cache.cc
@@ -44,7 +44,7 @@
 }
 
 void TestExternalCache::OnDamagedFileDetected(const base::FilePath& path) {
-  for (const auto& entry : cached_extensions_.DictItems()) {
+  for (const auto entry : cached_extensions_.DictItems()) {
     const base::Value* entry_path = entry.second.FindKeyOfType(
         extensions::ExternalProviderImpl::kExternalCrx,
         base::Value::Type::STRING);
@@ -112,7 +112,7 @@
 }
 
 void TestExternalCache::UpdateCachedExtensions() {
-  for (const auto& entry : configured_extensions_->DictItems()) {
+  for (const auto entry : configured_extensions_->DictItems()) {
     DCHECK(entry.second.is_dict());
     if (GetExtensionUpdateUrl(entry.second, always_check_for_updates_)
             .is_valid()) {
diff --git a/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc b/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc
index 20113ea..3f69d68 100644
--- a/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc
@@ -64,7 +64,8 @@
   bool AppendToListCrosSetting(const std::string& pref_name,
                                const base::Value& value) override {
     std::string email;
-    value.GetAsString(&email);
+    if (value.is_string())
+      email = value.GetString();
 
     for (auto& user : user_list_) {
       if (email == user)
@@ -78,7 +79,8 @@
   bool RemoveFromListCrosSetting(const std::string& pref_name,
                                  const base::Value& value) override {
     std::string email;
-    value.GetAsString(&email);
+    if (value.is_string())
+      email = value.GetString();
 
     auto iter = std::find(user_list_.begin(), user_list_.end(), email);
     if (iter != user_list_.end())
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
index 4fe06d02..57c4857a 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_delegate_impl.cc
@@ -256,9 +256,7 @@
   const base::Value* language_value = nullptr;
   if (dict.Get(extensions::manifest_keys::kLanguage, &language_value)) {
     if (language_value->is_string()) {
-      std::string language_str;
-      language_value->GetAsString(&language_str);
-      languages.insert(language_str);
+      languages.insert(language_value->GetString());
     } else if (language_value->is_list()) {
       const base::ListValue* language_list = nullptr;
       language_value->GetAsList(&language_list);
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_base.cc b/chrome/browser/chromeos/input_method/input_method_engine_base.cc
index 32f4e17..5090213 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_base.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_base.cc
@@ -88,7 +88,7 @@
           prefs::kLanguageInputMethodSpecificSettings);
   const base::DictionaryValue& old_settings =
       base::Value::AsDictionaryValue(input_method_settings_snapshot_);
-  for (const auto& it : new_settings->DictItems()) {
+  for (const auto it : new_settings->DictItems()) {
     if (old_settings.HasKey(it.first)) {
       if (*(old_settings.FindPath(it.first)) !=
           *(new_settings->FindPath(it.first))) {
diff --git a/chrome/browser/chromeos/policy/networking/network_configuration_updater.cc b/chrome/browser/chromeos/policy/networking/network_configuration_updater.cc
index 4bb0ef72..f07d2c8aa 100644
--- a/chrome/browser/chromeos/policy/networking/network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/networking/network_configuration_updater.cc
@@ -179,12 +179,14 @@
       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
   const base::Value* policy_value = policies.GetValue(policy_key_);
 
-  std::string onc_blob;
   if (!policy_value)
     VLOG(2) << LogHeader() << " is not set.";
-  else if (!policy_value->GetAsString(&onc_blob))
+  else if (!policy_value->is_string())
     LOG(ERROR) << LogHeader() << " is not a string value.";
 
+  const std::string onc_blob = policy_value && policy_value->is_string()
+                                   ? policy_value->GetString()
+                                   : std::string();
   chromeos::onc::ParseAndValidateOncForImport(
       onc_blob, onc_source_, std::string() /* no passphrase */, network_configs,
       global_network_config, certificates);
diff --git a/chrome/browser/chromeos/policy/reporting/extension_install_event_logger.cc b/chrome/browser/chromeos/policy/reporting/extension_install_event_logger.cc
index 21b828e..0ac064b 100644
--- a/chrome/browser/chromeos/policy/reporting/extension_install_event_logger.cc
+++ b/chrome/browser/chromeos/policy/reporting/extension_install_event_logger.cc
@@ -63,7 +63,7 @@
   if (!value)
     return;
   std::set<extensions::ExtensionId> current_requested;
-  for (const auto& entry : value->DictItems())
+  for (const auto entry : value->DictItems())
     current_requested.insert(entry.first);
   const std::set<extensions::ExtensionId> previous_pending =
       pending_extensions_;
diff --git a/chrome/browser/chromeos/policy/status_collector/activity_storage.cc b/chrome/browser/chromeos/policy/status_collector/activity_storage.cc
index 16bac58..3060e60c 100644
--- a/chrome/browser/chromeos/policy/status_collector/activity_storage.cc
+++ b/chrome/browser/chromeos/policy/status_collector/activity_storage.cc
@@ -254,7 +254,7 @@
         void(const int64_t, const int64_t, const std::string&)>& f) const {
   const base::DictionaryValue* stored_activity_periods =
       pref_service_->GetDictionary(pref_name_);
-  for (const auto& item : stored_activity_periods->DictItems()) {
+  for (const auto item : stored_activity_periods->DictItems()) {
     int64_t timestamp;
     std::string activity_id;
     if (!ParseActivityPeriodPrefKey(item.first, &timestamp, &activity_id)) {
diff --git a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
index 1178770..5dc0545 100644
--- a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
+++ b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
@@ -220,7 +220,8 @@
     const apps::AppUpdate& update,
     const std::vector<em::TimePeriod>& app_activity) const {
   em::AppInfo info;
-  bool is_web_app = update.AppType() == apps::mojom::AppType::kWeb;
+  bool is_web_app = (update.AppType() == apps::mojom::AppType::kWeb) ||
+                    (update.AppType() == apps::mojom::AppType::kSystemWeb);
   if (!is_web_app) {
     info.set_app_id(update.AppId());
     info.set_app_name(update.Name());
diff --git a/chrome/browser/chromeos/policy/status_collector/app_info_generator_unittest.cc b/chrome/browser/chromeos/policy/status_collector/app_info_generator_unittest.cc
index cb504b0e..c2540b1 100644
--- a/chrome/browser/chromeos/policy/status_collector/app_info_generator_unittest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/app_info_generator_unittest.cc
@@ -341,6 +341,31 @@
                                       MakeUTCTime("29-MAR-2020 5:00am"))})));
 }
 
+TEST_F(AppInfoGeneratorTest, GenerateSystemWebApp) {
+  user_manager()->LoginUser(account_id(), true);
+  auto generator = GetReadyGenerator();
+  PushApp("c", "App", apps::mojom::Readiness::kUninstalledByUser, "",
+          apps::mojom::AppType::kSystemWeb);
+  auto web_app = CreateWebApp();
+  RegisterApp(std::move(web_app));
+  Instance app_instance("c");
+  test_clock().SetNow(MakeLocalTime("29-MAR-2020 3:30pm"));
+  PushAppInstance(app_instance, apps::InstanceState::kStarted);
+  test_clock().SetNow(MakeLocalTime("29-MAR-2020 8:30pm"));
+  PushAppInstance(app_instance, apps::InstanceState::kDestroyed);
+
+  test_clock().SetNow(MakeLocalTime("30-MAR-2020 11:00am"));
+  auto result = generator->Generate();
+
+  EXPECT_THAT(
+      result.value(),
+      ElementsAre(EqApp("http://app.com/", "http://app.com/",
+                        em::AppInfo_Status_STATUS_UNINSTALLED, "",
+                        em::AppInfo_AppType_TYPE_WEB,
+                        {MakeActivity(MakeUTCTime("29-MAR-2020 12:00am"),
+                                      MakeUTCTime("29-MAR-2020 5:00am"))})));
+}
+
 TEST_F(AppInfoGeneratorTest, MultipleInstances) {
   user_manager()->LoginUser(account_id(), true);
   auto generator = GetReadyGenerator();
diff --git a/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc b/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc
index 81ccecd1..20637d02 100644
--- a/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc
@@ -75,7 +75,7 @@
     int32_t prev_ = 0;
     int32_t end_of_last_interval = 0;
     int32_t num_intervals = 0;
-    for (const auto& r : testee_) {
+    for (const auto r : testee_) {
       num_intervals++;
       EXPECT_LT(r.first.begin, r.first.end);
       if (r.first.begin == std::numeric_limits<int32_t>::min()) {
@@ -96,7 +96,7 @@
         LOG(ERROR) << i << ": Truth =" << truth_[i]
                    << " Testee = " << testee_[i];
       }
-      for (const auto& r : testee_) {
+      for (const auto r : testee_) {
         LOG(ERROR) << "Interval:  " << r.first.begin << " - " << r.first.end
                    << " = " << r.second;
       }
diff --git a/chrome/browser/chromeos/startup_settings_cache.cc b/chrome/browser/chromeos/startup_settings_cache.cc
index ce522f7..3198502 100644
--- a/chrome/browser/chromeos/startup_settings_cache.cc
+++ b/chrome/browser/chromeos/startup_settings_cache.cc
@@ -50,11 +50,10 @@
   if (!app_locale_setting)
     return std::string();
 
-  std::string app_locale;
-  app_locale_setting->GetAsString(&app_locale);
   // The locale is already an "actual locale", so this does not need to call
   // language::ConvertToActualUILocale().
-  return app_locale;
+  return app_locale_setting->is_string() ? app_locale_setting->GetString()
+                                         : std::string();
 }
 
 void WriteAppLocale(std::string app_locale) {
diff --git a/chrome/browser/content_creation/notes/internal/android/BUILD.gn b/chrome/browser/content_creation/notes/internal/android/BUILD.gn
index ea0972cd..e0b15f1 100644
--- a/chrome/browser/content_creation/notes/internal/android/BUILD.gn
+++ b/chrome/browser/content_creation/notes/internal/android/BUILD.gn
@@ -33,6 +33,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//chrome/android:chrome_java",
     "//chrome/browser/content_creation/notes/android:public_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/share:java",
diff --git a/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationCoordinatorImpl.java b/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationCoordinatorImpl.java
index 30ac4c2..6277b96 100644
--- a/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationCoordinatorImpl.java
+++ b/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationCoordinatorImpl.java
@@ -141,7 +141,8 @@
                                         @Override
                                         public void onTargetChosen(ComponentName chosenComponent) {
                                             NoteCreationMetrics.recordNoteShared(
-                                                    getTimeElapsedSinceCreationStart());
+                                                    getTimeElapsedSinceCreationStart(),
+                                                    chosenComponent);
                                         }
 
                                         @Override
diff --git a/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationMetrics.java b/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationMetrics.java
index c36c1b4..1ea371d 100644
--- a/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationMetrics.java
+++ b/chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationMetrics.java
@@ -4,9 +4,12 @@
 
 package org.chromium.chrome.browser.content_creation.notes;
 
+import android.content.ComponentName;
+
 import androidx.annotation.IntDef;
 
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.share.share_sheet.ChromeProvidedSharingOptionsProvider;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -44,6 +47,15 @@
         int NUM_ENTRIES = 11;
     }
 
+    // Constants used to log the share destination for the created note.
+    // Constants used to log the Note Creation Funnel enum histogram.
+    @IntDef({NoteShareDestination.FIRST_PARTY, NoteShareDestination.THIRD_PARTY})
+    private @interface NoteShareDestination {
+        int FIRST_PARTY = 0;
+        int THIRD_PARTY = 1;
+        int NUM_ENTRIES = 2;
+    }
+
     /**
      * Records metrics related to the user starting the creation flow.
      */
@@ -85,14 +97,24 @@
      *
      * @param duration The time elapsed between the start of the creation flow and when the user
      *         shared their created note.
+     * @param chosenComponent The component that was picked as a share desitination.
      */
-    public static void recordNoteShared(long duration) {
+    public static void recordNoteShared(long duration, ComponentName chosenComponent) {
         RecordHistogram.recordEnumeratedHistogram("NoteCreation.Funnel",
                 NoteCreationFunnel.NOTE_SHARED, NoteCreationFunnel.NUM_ENTRIES);
 
         RecordHistogram.recordBooleanHistogram("NoteCreation.NoteShared", true);
 
         RecordHistogram.recordMediumTimesHistogram("NoteCreation.TimeTo.ShareCreation", duration);
+
+        if (chosenComponent.equals(
+                    ChromeProvidedSharingOptionsProvider.CHROME_PROVIDED_FEATURE_COMPONENT_NAME)) {
+            RecordHistogram.recordEnumeratedHistogram("NoteCreation.ShareDestination",
+                    NoteShareDestination.FIRST_PARTY, NoteShareDestination.NUM_ENTRIES);
+        } else {
+            RecordHistogram.recordEnumeratedHistogram("NoteCreation.ShareDestination",
+                    NoteShareDestination.THIRD_PARTY, NoteShareDestination.NUM_ENTRIES);
+        }
     }
 
     /**
diff --git a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListMediator.java b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListMediator.java
index f3b3e2e..1d551f3 100644
--- a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListMediator.java
+++ b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListMediator.java
@@ -57,13 +57,16 @@
     private ContinuousNavigationUserDataImpl mCurrentUserData;
     private @PageCategory int mPageCategory;
     private boolean mVisible;
-    private boolean mScrolled;
     private boolean mDismissed;
+    private boolean mUiShown;
     // The navigation index when CSN metadata was retrieved.
     private int mStartNavigationIndex;
     private int mSrpVisits;
     private BrowserControlsStateProvider.Observer mScrollObserver;
 
+    private boolean mScrolled;
+    private boolean mProviderButtonClicked;
+
     @IntDef({TriggerMode.ALWAYS, TriggerMode.AFTER_SECOND_SRP, TriggerMode.ON_REVERSE_SCROLL})
     @Retention(RetentionPolicy.SOURCE)
     public @interface TriggerMode {
@@ -105,9 +108,14 @@
     }
 
     private void reset() {
+        // Only record the metrics if the UI was shown.
+        if (mUiShown) recordUiMetrics();
         mModelList.clear();
         mDismissed = false;
         mOnSrp = false;
+        mUiShown = false;
+        mScrolled = false;
+        mProviderButtonClicked = false;
         mSrpVisits = 0;
     }
 
@@ -272,6 +280,7 @@
                     navigationController.goToNavigationIndex(mStartNavigationIndex);
                 }
             }
+            mProviderButtonClicked = true;
         } else if (mCurrentTab != null && url != null) {
             LoadUrlParams params = new LoadUrlParams(url.getSpec());
             params.setReferrer(
@@ -286,8 +295,8 @@
     }
 
     private void setVisibility(boolean visibility, Runnable onHideFinished) {
-        if (mVisible && !visibility) recordListScrolled();
         mVisible = visibility;
+        if (mVisible) mUiShown = true;
         mSetLayoutVisibility.onResult(new VisibilitySettings(mVisible, onHideFinished));
     }
 
@@ -295,11 +304,16 @@
         mScrolled = true;
     }
 
-    private void recordListScrolled() {
-        RecordHistogram.recordBooleanHistogram("Browser.ContinuousSearch.UI.CarouselScrolled"
-                        + SearchUrlHelper.getHistogramSuffixForPageCategory(mPageCategory),
-                mScrolled);
-        mScrolled = false;
+    private void recordUiMetrics() {
+        String histogramSuffix = SearchUrlHelper.getHistogramSuffixForPageCategory(mPageCategory);
+
+        RecordHistogram.recordBooleanHistogram(
+                "Browser.ContinuousSearch.UI.CarouselScrolled2" + histogramSuffix, mScrolled);
+        RecordHistogram.recordBooleanHistogram(
+                "Browser.ContinuousSearch.UI.ProviderButtonClicked" + histogramSuffix,
+                mProviderButtonClicked);
+        RecordHistogram.recordBooleanHistogram(
+                "Browser.ContinuousSearch.UI.DismissButtonClicked" + histogramSuffix, mDismissed);
     }
 
     private void initScrollObserver() {
@@ -365,6 +379,8 @@
     }
 
     void destroy() {
+        reset();
+
         if (mCurrentUserData != null) mCurrentUserData.removeObserver(this);
         if (mThemeColorProvider != null) mThemeColorProvider.removeThemeColorObserver(this);
 
diff --git a/chrome/browser/device_api/device_attribute_api.cc b/chrome/browser/device_api/device_attribute_api.cc
index 66bc6ed..73b2ff6 100644
--- a/chrome/browser/device_api/device_attribute_api.cc
+++ b/chrome/browser/device_api/device_attribute_api.cc
@@ -22,6 +22,9 @@
 
 using Result = blink::mojom::DeviceAttributeResult;
 
+const char kNotAffiliatedErrorMessage[] =
+    "This web API is not allowed if the current profile is not affiliated.";
+
 const char kNotAllowedOriginErrorMessage[] =
     "The current origin cannot use this web API because it is not allowed by "
     "the DeviceAttributesAllowedForOrigins policy.";
@@ -50,6 +53,11 @@
 
 }  // namespace
 
+void ReportNotAffiliatedError(
+    base::OnceCallback<void(DeviceAttributeResultPtr)> callback) {
+  std::move(callback).Run(Result::NewErrorMessage(kNotAffiliatedErrorMessage));
+}
+
 void ReportNotAllowedError(
     base::OnceCallback<void(DeviceAttributeResultPtr)> callback) {
   std::move(callback).Run(
diff --git a/chrome/browser/device_api/device_attribute_api.h b/chrome/browser/device_api/device_attribute_api.h
index e13fea68..97b5ba85 100644
--- a/chrome/browser/device_api/device_attribute_api.h
+++ b/chrome/browser/device_api/device_attribute_api.h
@@ -12,6 +12,8 @@
 
 namespace device_attribute_api {
 
+void ReportNotAffiliatedError(
+    base::OnceCallback<void(DeviceAttributeResultPtr)> callback);
 void ReportNotAllowedError(
     base::OnceCallback<void(DeviceAttributeResultPtr)> callback);
 void GetDirectoryId(DeviceAPIService::GetDirectoryIdCallback callback);
diff --git a/chrome/browser/device_api/device_service_impl.cc b/chrome/browser/device_api/device_service_impl.cc
index 2fbe734..e3bc9c943 100644
--- a/chrome/browser/device_api/device_service_impl.cc
+++ b/chrome/browser/device_api/device_service_impl.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ash/login/app_mode/kiosk_launch_controller.h"
+#include "components/user_manager/user_manager.h"
 #endif
 
 namespace {
@@ -72,8 +73,22 @@
   });
 }
 
+const Profile* GetProfile(content::RenderFrameHost* host) {
+  return Profile::FromBrowserContext(host->GetBrowserContext());
+}
+
 const PrefService* GetPrefs(content::RenderFrameHost* host) {
-  return Profile::FromBrowserContext(host->GetBrowserContext())->GetPrefs();
+  return GetProfile(host)->GetPrefs();
+}
+
+bool IsAffiliatedUser() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  const user_manager::User* user =
+      user_manager::UserManager::Get()->GetPrimaryUser();
+  return user && user->IsAffiliated();
+#else
+  return false;
+#endif
 }
 
 bool IsTrustedContext(content::RenderFrameHost* host,
@@ -83,6 +98,10 @@
   if (!base::FeatureList::IsEnabled(features::kEnableRestrictedWebApis))
     return false;
 
+  // Do not create the service for the incognito mode.
+  if (GetProfile(host)->IsIncognitoProfile())
+    return false;
+
   if (chrome::IsRunningInAppMode()) {
     return IsEqualToKioskOrigin(origin);
   } else {
@@ -170,6 +189,11 @@
 void DeviceServiceImpl::GetDeviceAttribute(
     base::OnceCallback<void(DeviceAttributeCallback)> handler,
     DeviceAttributeCallback callback) {
+  if (!IsAffiliatedUser()) {
+    device_attribute_api::ReportNotAffiliatedError(std::move(callback));
+    return;
+  }
+
   if (!CanAccessDeviceAttributes(GetPrefs(host_), origin())) {
     device_attribute_api::ReportNotAllowedError(std::move(callback));
     return;
diff --git a/chrome/browser/device_api/device_service_unittest.cc b/chrome/browser/device_api/device_service_unittest.cc
index 925cb43..a4d3e3f8 100644
--- a/chrome/browser/device_api/device_service_unittest.cc
+++ b/chrome/browser/device_api/device_service_unittest.cc
@@ -13,29 +13,30 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/profile_metrics/browser_profile_type.h"
+#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/web_contents_tester.h"
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "base/command_line.h"
 #include "base/test/scoped_command_line.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/user_manager/scoped_user_manager.h"
 #endif
 
 namespace {
 
 constexpr char kDefaultAppInstallUrl[] = "https://example.com/install";
 constexpr char kTrustedUrl[] = "https://example.com/sample";
-constexpr char kUntrustedUrl[] = "https://non-example.com/sample";
 constexpr char kKioskAppInstallUrl[] = "https://kiosk.com/install";
+constexpr char kUserEmail[] = "user-email@example.com";
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-constexpr char kAppEmail[] = "email@example.com";
+constexpr char kUntrustedUrl[] = "https://non-example.com/sample";
 constexpr char kKioskAppUrl[] = "https://kiosk.com/sample";
 constexpr char kInvalidKioskAppUrl[] = "https://invalid-kiosk.com/sample";
 #endif
@@ -48,6 +49,8 @@
 
 class DeviceAPIServiceTest : public ChromeRenderViewHostTestHarness {
  public:
+  DeviceAPIServiceTest() : account_id_(AccountId::FromUserEmail(kUserEmail)) {}
+
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     InstallTrustedApp();
@@ -82,20 +85,30 @@
     update->ClearList();
   }
 
-  void TryCreatingService(content::WebContents* web_contents, const GURL& url) {
-    content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents,
+  void TryCreatingService(const GURL& url) {
+    content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(),
                                                                url);
     DeviceServiceImpl::Create(main_rfh(), remote_.BindNewPipeAndPassReceiver());
   }
 
-  void TryCreatingService(const GURL& url) {
-    TryCreatingService(web_contents(), url);
+  void VerifyErrorMessageResultForAllDeviceAttributesAPIs() {
+    remote()->get()->GetDirectoryId(base::BindOnce(VerifyErrorMessageResult));
+    remote()->get()->GetHostname(base::BindOnce(VerifyErrorMessageResult));
+    remote()->get()->GetSerialNumber(base::BindOnce(VerifyErrorMessageResult));
+    remote()->get()->GetAnnotatedAssetId(
+        base::BindOnce(VerifyErrorMessageResult));
+    remote()->get()->GetAnnotatedLocation(
+        base::BindOnce(VerifyErrorMessageResult));
+    remote()->FlushForTesting();
   }
 
+  const AccountId& account_id() const { return account_id_; }
+
   mojo::Remote<blink::mojom::DeviceAPIService>* remote() { return &remote_; }
 
  private:
   mojo::Remote<blink::mojom::DeviceAPIService> remote_;
+  AccountId account_id_;
 };
 
 TEST_F(DeviceAPIServiceTest, EnableServiceByDefault) {
@@ -104,27 +117,17 @@
   ASSERT_TRUE(remote()->is_connected());
 }
 
-TEST_F(DeviceAPIServiceTest, ReportErrorForDisallowedOrigin) {
+TEST_F(DeviceAPIServiceTest, ReportErrorForDefaultUser) {
   TryCreatingService(GURL(kTrustedUrl));
-  RemoveAllowedOrigin();
-
-  remote()->get()->GetDirectoryId(base::BindOnce(VerifyErrorMessageResult));
-  remote()->get()->GetHostname(base::BindOnce(VerifyErrorMessageResult));
-  remote()->get()->GetSerialNumber(base::BindOnce(VerifyErrorMessageResult));
-  remote()->get()->GetAnnotatedAssetId(
-      base::BindOnce(VerifyErrorMessageResult));
-  remote()->get()->GetAnnotatedLocation(
-      base::BindOnce(VerifyErrorMessageResult));
-  remote()->FlushForTesting();
+  VerifyErrorMessageResultForAllDeviceAttributesAPIs();
   ASSERT_TRUE(remote()->is_connected());
 }
 
 // The service should be disabled in the Incognito mode.
 TEST_F(DeviceAPIServiceTest, IncognitoProfile) {
-  std::unique_ptr<content::WebContents> incognito_web_contents =
-      content::WebContentsTester::CreateTestWebContents(
-          profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true), nullptr);
-  TryCreatingService(incognito_web_contents.get(), GURL(kTrustedUrl));
+  profile_metrics::SetBrowserProfileType(
+      profile(), profile_metrics::BrowserProfileType::kIncognito);
+  TryCreatingService(GURL(kTrustedUrl));
 
   remote()->FlushForTesting();
   ASSERT_FALSE(remote()->is_connected());
@@ -132,6 +135,45 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 
+class DeviceAPIServiceRegularUserTest : public DeviceAPIServiceTest {
+ public:
+  DeviceAPIServiceRegularUserTest()
+      : fake_user_manager_(new user_manager::FakeUserManager()),
+        scoped_user_manager_(base::WrapUnique(fake_user_manager_)) {}
+
+  void LoginRegularUser(bool is_affiliated) {
+    const user_manager::User* user =
+        fake_user_manager()->AddUserWithAffiliation(account_id(),
+                                                    is_affiliated);
+    fake_user_manager()->UserLoggedIn(user->GetAccountId(),
+                                      user->username_hash(), false, false);
+  }
+
+  user_manager::FakeUserManager* fake_user_manager() const {
+    return fake_user_manager_;
+  }
+
+ private:
+  user_manager::FakeUserManager* fake_user_manager_;
+  user_manager::ScopedUserManager scoped_user_manager_;
+};
+
+TEST_F(DeviceAPIServiceRegularUserTest, ReportErrorForUnaffiliatedUser) {
+  LoginRegularUser(false);
+  TryCreatingService(GURL(kTrustedUrl));
+  VerifyErrorMessageResultForAllDeviceAttributesAPIs();
+  ASSERT_TRUE(remote()->is_connected());
+}
+
+TEST_F(DeviceAPIServiceRegularUserTest, ReportErrorForDisallowedOrigin) {
+  LoginRegularUser(true);
+  TryCreatingService(GURL(kTrustedUrl));
+  RemoveAllowedOrigin();
+
+  VerifyErrorMessageResultForAllDeviceAttributesAPIs();
+  ASSERT_TRUE(remote()->is_connected());
+}
+
 class DeviceAPIServiceWithKioskUserTest : public DeviceAPIServiceTest {
  public:
   DeviceAPIServiceWithKioskUserTest()
@@ -142,7 +184,6 @@
     DeviceAPIServiceTest::SetUp();
     command_line_.GetProcessCommandLine()->AppendSwitch(
         switches::kForceAppMode);
-    account_id_ = AccountId::FromUserEmail(kAppEmail);
     app_manager_ = std::make_unique<ash::WebKioskAppManager>();
   }
 
@@ -161,16 +202,13 @@
     return fake_user_manager_;
   }
 
-  const AccountId& account_id() const { return account_id_; }
-
   ash::WebKioskAppManager* app_manager() const { return app_manager_.get(); }
 
  private:
   ash::FakeChromeUserManager* fake_user_manager_;
   user_manager::ScopedUserManager scoped_user_manager_;
-  base::test::ScopedCommandLine command_line_;
-  AccountId account_id_;
   std::unique_ptr<ash::WebKioskAppManager> app_manager_;
+  base::test::ScopedCommandLine command_line_;
 };
 
 // The service should be enabled if the current origin is same as the origin of
@@ -201,9 +239,8 @@
   ASSERT_FALSE(remote()->is_connected());
 }
 
-#endif
-
-class DeviceAPIServiceWithFeatureFlagTest : public DeviceAPIServiceTest {
+class DeviceAPIServiceWithFeatureFlagTest
+    : public DeviceAPIServiceRegularUserTest {
  public:
   DeviceAPIServiceWithFeatureFlagTest() {
     scoped_feature_list_.InitAndEnableFeature(
@@ -233,7 +270,8 @@
   ASSERT_FALSE(remote()->is_connected());
 }
 
-class DeviceAPIServiceWithoutFeatureFlagTest : public DeviceAPIServiceTest {
+class DeviceAPIServiceWithoutFeatureFlagTest
+    : public DeviceAPIServiceRegularUserTest {
  public:
   DeviceAPIServiceWithoutFeatureFlagTest() {
     scoped_feature_list_.InitAndDisableFeature(
@@ -248,3 +286,5 @@
   remote()->FlushForTesting();
   ASSERT_FALSE(remote()->is_connected());
 }
+
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/download/internal/android/java/res/layout/downloads_empty_view.xml b/chrome/browser/download/internal/android/java/res/layout/downloads_empty_view.xml
index f163316..536e39db 100644
--- a/chrome/browser/download/internal/android/java/res/layout/downloads_empty_view.xml
+++ b/chrome/browser/download/internal/android/java/res/layout/downloads_empty_view.xml
@@ -15,7 +15,7 @@
         android:layout_marginEnd="@dimen/default_list_row_padding"
         android:layout_marginStart="@dimen/default_list_row_padding"
         android:gravity="center"
-        android:padding="@dimen/card_padding"
+        app:contentPadding="@dimen/card_padding"
         style="@style/MaterialCardStyle">
 
         <org.chromium.ui.widget.TextViewWithLeading
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
index 8993a4c..436eb59 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
@@ -402,9 +402,11 @@
   bad_rule->set_rule_name("malware");
 
   FakeBinaryUploadServiceStorage()->SetResponseForFile(
-      "ok.doc", BinaryUploadService::Result::SUCCESS, ok_response);
+      created_file_paths()[0].AsUTF8Unsafe(),
+      BinaryUploadService::Result::SUCCESS, ok_response);
   FakeBinaryUploadServiceStorage()->SetResponseForFile(
-      "bad.exe", BinaryUploadService::Result::SUCCESS, bad_response);
+      created_file_paths()[1].AsUTF8Unsafe(),
+      BinaryUploadService::Result::SUCCESS, bad_response);
 
   bool called = false;
   base::RunLoop run_loop;
@@ -566,9 +568,10 @@
   // TOO_MANY_REQUEST result, it can be any of them depending on how quickly
   // they are opened asynchronously. This means responses must be set up for
   // each of them.
-  for (const std::string& file_name : {"a.exe", "b.exe", "c.exe"}) {
+  for (size_t i = 0; i < 3; ++i) {
     FakeBinaryUploadServiceStorage()->SetResponseForFile(
-        file_name, BinaryUploadService::Result::TOO_MANY_REQUESTS,
+        created_file_paths()[i].AsUTF8Unsafe(),
+        BinaryUploadService::Result::TOO_MANY_REQUESTS,
         ContentAnalysisResponse());
   }
 
@@ -920,7 +923,8 @@
   dlp_rule->set_rule_name("some_dlp_rule");
 
   FakeBinaryUploadServiceStorage()->SetResponseForFile(
-      "foo.doc", BinaryUploadService::Result::SUCCESS, response);
+      created_file_paths()[0].AsUTF8Unsafe(),
+      BinaryUploadService::Result::SUCCESS, response);
   validator.ExpectDangerousDeepScanningResultAndSensitiveDataEvent(
       /*url*/ "about:blank",
       /*filename*/ created_file_paths()[0].AsUTF8Unsafe(),
diff --git a/chrome/browser/enterprise/connectors/connectors_service.cc b/chrome/browser/enterprise/connectors/connectors_service.cc
index d6f5e44b..cc64ef4 100644
--- a/chrome/browser/enterprise/connectors/connectors_service.cc
+++ b/chrome/browser/enterprise/connectors/connectors_service.cc
@@ -23,13 +23,16 @@
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/ui/managed_ui.h"
 #include "components/embedder_support/user_agent_utils.h"
 #include "components/enterprise/browser/controller/browser_dm_token_storage.h"
 #include "components/enterprise/common/proto/connectors.pb.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/policy/core/common/cloud/cloud_policy_store.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/core/common/cloud/dm_token.h"
 #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
+#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
@@ -39,6 +42,7 @@
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_context.h"
 #include "device_management_backend.pb.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/policy/core/user_cloud_policy_manager_chromeos.h"
@@ -367,6 +371,51 @@
   return connectors_manager_->GetAnalysisServiceProviderNames(connector);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+std::string ConnectorsService::GetManagementDomain() {
+  if (!ConnectorsEnabled())
+    return std::string();
+
+  absl::optional<policy::PolicyScope> scope = absl::nullopt;
+  for (const char* scope_pref :
+       {prefs::kSafeBrowsingEnterpriseRealTimeUrlCheckScope,
+        ConnectorScopePref(AnalysisConnector::FILE_ATTACHED),
+        ConnectorScopePref(AnalysisConnector::FILE_DOWNLOADED),
+        ConnectorScopePref(AnalysisConnector::BULK_DATA_ENTRY),
+        ConnectorScopePref(ReportingConnector::SECURITY_EVENT)}) {
+    absl::optional<DmToken> dm_token = GetDmToken(scope_pref);
+    if (dm_token.has_value()) {
+      scope = dm_token.value().scope;
+
+      // Having one CBCM Connector policy set implies that profile ones will be
+      // ignored for another domain, so the loop can stop immediately.
+      if (scope == policy::PolicyScope::POLICY_SCOPE_MACHINE)
+        break;
+    }
+  }
+
+  if (!scope.has_value())
+    return std::string();
+
+  if (scope.value() == policy::PolicyScope::POLICY_SCOPE_USER) {
+    return chrome::GetAccountManagerIdentity(
+               Profile::FromBrowserContext(context_))
+        .value_or(std::string());
+  }
+
+  policy::MachineLevelUserCloudPolicyManager* manager =
+      g_browser_process->browser_policy_connector()
+          ->machine_level_user_cloud_policy_manager();
+  if (!manager)
+    return std::string();
+
+  policy::CloudPolicyStore* store = manager->store();
+  return (store && store->has_policy())
+             ? gaia::ExtractDomainName(store->policy()->username())
+             : std::string();
+}
+#endif
+
 absl::optional<std::string> ConnectorsService::GetDMTokenForRealTimeUrlCheck()
     const {
   if (!ConnectorsEnabled())
diff --git a/chrome/browser/enterprise/connectors/connectors_service.h b/chrome/browser/enterprise/connectors/connectors_service.h
index ffad8e2..a3ca9b3 100644
--- a/chrome/browser/enterprise/connectors/connectors_service.h
+++ b/chrome/browser/enterprise/connectors/connectors_service.h
@@ -86,6 +86,13 @@
   safe_browsing::EnterpriseRealTimeUrlCheckMode GetAppliedRealTimeUrlCheck()
       const;
 
+  // Returns the CBCM domain or profile domain that enables connector policies.
+  // If both set Connector policies, the CBCM domain is returned as it has
+  // precedence.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+  std::string GetManagementDomain();
+#endif
+
   // Testing functions.
   ConnectorsManager* ConnectorsManagerForTesting();
 
diff --git a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc
index c381934..9bfc3db 100644
--- a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc
@@ -52,6 +52,10 @@
 constexpr char kFakeProfileClientId[] = "fake-profile-client-id";
 constexpr char kAffiliationId1[] = "affiliation-id-1";
 constexpr char kAffiliationId2[] = "affiliation-id-2";
+constexpr char kUsername1[] = "user@domain1.com";
+constexpr char kUsername2[] = "admin@domain2.com";
+constexpr char kDomain1[] = "domain1.com";
+constexpr char kDomain2[] = "domain2.com";
 #endif
 
 constexpr char kFakeBrowserDMToken[] = "fake-browser-dm-token";
@@ -117,6 +121,7 @@
     auto profile_policy_data =
         std::make_unique<enterprise_management::PolicyData>();
     profile_policy_data->add_user_affiliation_ids(kAffiliationId1);
+    profile_policy_data->set_managed_by(kDomain1);
     profile_policy_data->set_device_id(kFakeProfileClientId);
     profile_policy_manager->core()->store()->set_policy_data_for_testing(
         std::move(profile_policy_data));
@@ -131,6 +136,9 @@
           management_status() == ManagementStatus::AFFILIATED
               ? kAffiliationId1
               : kAffiliationId2);
+      browser_policy_data->set_username(
+          management_status() == ManagementStatus::AFFILIATED ? kUsername1
+                                                              : kUsername2);
       browser_policy_manager->core()->store()->set_policy_data_for_testing(
           std::move(browser_policy_data));
     }
@@ -206,19 +214,25 @@
     ASSERT_EQ(kFakeBrowserDMToken, settings.value().dm_token);
   }
 #else
+  std::string management_domain =
+      ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
+          ->GetManagementDomain();
   switch (management_status()) {
     case ManagementStatus::AFFILIATED:
       EXPECT_TRUE(settings.has_value());
       ASSERT_EQ(kFakeProfileDMToken, settings.value().dm_token);
       ASSERT_TRUE(settings.value().per_profile);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
     case ManagementStatus::UNAFFILIATED:
       EXPECT_FALSE(settings.has_value());
+      ASSERT_TRUE(management_domain.empty());
       break;
     case ManagementStatus::UNMANAGED:
       EXPECT_TRUE(settings.has_value());
       ASSERT_EQ(kFakeProfileDMToken, settings.value().dm_token);
       ASSERT_TRUE(settings.value().per_profile);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
   }
 #endif
@@ -282,7 +296,6 @@
   auto settings =
       ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
           ->GetAnalysisSettings(GURL(kTestUrl), connector());
-
   if (management_status() == ManagementStatus::UNMANAGED) {
     ASSERT_FALSE(settings.has_value());
   } else {
@@ -292,6 +305,13 @@
     ValidateClientMetadata(*settings.value().client_metadata,
                            /*profile_reporting*/ false);
   }
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+  ASSERT_EQ((management_status() == ManagementStatus::UNAFFILIATED) ? kDomain2
+                                                                    : kDomain1,
+            ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
+                ->GetManagementDomain());
+#endif
 }
 
 IN_PROC_BROWSER_TEST_P(ConnectorsServiceAnalysisProfileBrowserTest,
@@ -316,6 +336,9 @@
                            /*profile_reporting*/ false);
   }
 #else
+  std::string management_domain =
+      ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
+          ->GetManagementDomain();
   switch (management_status()) {
     case ManagementStatus::AFFILIATED:
       EXPECT_TRUE(settings.has_value());
@@ -323,9 +346,11 @@
       ASSERT_TRUE(settings.value().per_profile);
       ValidateClientMetadata(*settings.value().client_metadata,
                              /*profile_reporting*/ true);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
     case ManagementStatus::UNAFFILIATED:
       EXPECT_FALSE(settings.has_value());
+      ASSERT_TRUE(management_domain.empty());
       break;
     case ManagementStatus::UNMANAGED:
       EXPECT_TRUE(settings.has_value());
@@ -334,6 +359,7 @@
       ASSERT_TRUE(settings.value().client_metadata);
       ValidateClientMetadata(*settings.value().client_metadata,
                              /*profile_reporting*/ true);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
   }
 #endif
@@ -357,21 +383,27 @@
     ASSERT_FALSE(settings.value().client_metadata);
   }
 #else
+  std::string management_domain =
+      ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
+          ->GetManagementDomain();
   switch (management_status()) {
     case ManagementStatus::AFFILIATED:
       EXPECT_TRUE(settings.has_value());
       ASSERT_EQ(kFakeProfileDMToken, settings.value().dm_token);
       ASSERT_TRUE(settings.value().per_profile);
       ASSERT_FALSE(settings.value().client_metadata);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
     case ManagementStatus::UNAFFILIATED:
       EXPECT_FALSE(settings.has_value());
+      ASSERT_TRUE(management_domain.empty());
       break;
     case ManagementStatus::UNMANAGED:
       EXPECT_TRUE(settings.has_value());
       ASSERT_EQ(kFakeProfileDMToken, settings.value().dm_token);
       ASSERT_TRUE(settings.value().per_profile);
       ASSERT_FALSE(settings.value().client_metadata);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
   }
 #endif
@@ -413,22 +445,28 @@
               url_check_pref);
   }
 #else
+  std::string management_domain =
+      ConnectorsServiceFactory::GetForBrowserContext(browser()->profile())
+          ->GetManagementDomain();
   switch (management_status()) {
     case ManagementStatus::AFFILIATED:
       ASSERT_TRUE(maybe_dm_token.has_value());
       ASSERT_EQ(kFakeProfileDMToken, maybe_dm_token.value());
       ASSERT_EQ(safe_browsing::REAL_TIME_CHECK_FOR_MAINFRAME_ENABLED,
                 url_check_pref);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
     case ManagementStatus::UNAFFILIATED:
       ASSERT_FALSE(maybe_dm_token.has_value());
       ASSERT_EQ(safe_browsing::REAL_TIME_CHECK_DISABLED, url_check_pref);
+      ASSERT_TRUE(management_domain.empty());
       break;
     case ManagementStatus::UNMANAGED:
       ASSERT_TRUE(maybe_dm_token.has_value());
       ASSERT_EQ(kFakeProfileDMToken, maybe_dm_token.value());
       ASSERT_EQ(safe_browsing::REAL_TIME_CHECK_FOR_MAINFRAME_ENABLED,
                 url_check_pref);
+      ASSERT_EQ(kDomain1, management_domain);
       break;
   }
 #endif
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 4b3ed336..481adff 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -529,8 +529,6 @@
     "extension_assets_manager.h",
     "extension_browser_window_helper.cc",
     "extension_browser_window_helper.h",
-    "extension_checkup.cc",
-    "extension_checkup.h",
     "extension_commands_global_registry.cc",
     "extension_commands_global_registry.h",
     "extension_context_menu_model.cc",
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
index 2e246fc6..9c2c75b 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
@@ -161,8 +161,8 @@
 }
 
 void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::
-    OnInstallPromptDone(ExtensionInstallPrompt::Result result) {
-  bool accepted = (result == ExtensionInstallPrompt::Result::ACCEPTED);
+    OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  bool accepted = (payload.result == ExtensionInstallPrompt::Result::ACCEPTED);
   Respond(
       BuildResponse(accepted ? api::dashboard_private::RESULT_EMPTY_STRING
                              : api::dashboard_private::RESULT_USER_CANCELLED,
@@ -183,4 +183,3 @@
 }
 
 }  // namespace extensions
-
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
index 08091ee..a41579a 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.h
@@ -50,7 +50,7 @@
                               InstallHelperResultCode result,
                               const std::string& error_message) override;
 
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   ExtensionFunction::ResponseValue BuildResponse(
       api::dashboard_private::Result result,
@@ -73,4 +73,3 @@
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_DASHBOARD_PRIVATE_DASHBOARD_PRIVATE_API_H_
-
diff --git a/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc b/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
index 8499259a..cc28d5b 100644
--- a/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
+++ b/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
@@ -84,8 +84,8 @@
 }
 
 void ShowPermissionsDialogHelper::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  if (result == ExtensionInstallPrompt::Result::ACCEPTED) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload.result == ExtensionInstallPrompt::Result::ACCEPTED) {
     // This is true when the user clicks "Revoke File Access."
     const Extension* extension =
         ExtensionRegistry::Get(profile_)
diff --git a/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.h b/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.h
index 859902c..3fea6b6 100644
--- a/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.h
+++ b/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.h
@@ -39,7 +39,7 @@
   void ShowPermissionsDialog(content::WebContents* web_contents,
                              const Extension* extension);
 
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   std::unique_ptr<ExtensionInstallPrompt> prompt_;
 
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index dd7f832..82d5251 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -144,8 +144,9 @@
   ~ManagementSetEnabledFunctionInstallPromptDelegate() override {}
 
  private:
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result) {
-    std::move(callback_).Run(result ==
+  void OnInstallPromptDone(
+      ExtensionInstallPrompt::DoneCallbackPayload payload) {
+    std::move(callback_).Run(payload.result ==
                              ExtensionInstallPrompt::Result::ACCEPTED);
   }
 
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc
index 9b9f237b..08cc1394 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api.cc
@@ -301,7 +301,8 @@
           .empty();
   if (has_no_warnings ||
       extension_->location() == mojom::ManifestLocation::kComponent) {
-    OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
+    OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+        ExtensionInstallPrompt::Result::ACCEPTED));
     return did_respond() ? AlreadyResponded() : RespondLater();
   }
 
@@ -310,9 +311,11 @@
   if (auto_confirm_for_tests != DO_NOT_SKIP) {
     prompted_permissions_for_testing_ = total_new_permissions->Clone();
     if (auto_confirm_for_tests == PROCEED)
-      OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
+      OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::ACCEPTED));
     else if (auto_confirm_for_tests == ABORT)
-      OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
+      OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::USER_CANCELED));
     return did_respond() ? AlreadyResponded() : RespondLater();
   }
 
@@ -332,8 +335,8 @@
 }
 
 void PermissionsRequestFunction::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  if (result != ExtensionInstallPrompt::Result::ACCEPTED) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload.result != ExtensionInstallPrompt::Result::ACCEPTED) {
     Respond(ArgumentList(api::permissions::Request::Results::Create(false)));
     return;
   }
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.h b/chrome/browser/extensions/api/permissions/permissions_api.h
index 7b8c249..551c20ad 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.h
+++ b/chrome/browser/extensions/api/permissions/permissions_api.h
@@ -71,7 +71,7 @@
   ResponseAction Run() override;
 
  private:
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
   void OnRuntimePermissionsGranted();
   void OnOptionalPermissionsGranted();
   void RespondIfRequestsFinished();
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index b2f5f1e..ffd4b0d2 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -988,6 +988,13 @@
         GetRestrictedCrosSettingValueForChildUser(profile_, name)->Clone());
     return pref_object;
   }
+
+  if (IsHotwordDisabledForChildUser(name)) {
+    pref_object->controlled_by =
+        settings_api::ControlledBy::CONTROLLED_BY_CHILD_RESTRICTION;
+    pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED;
+    return pref_object;
+  }
 #endif
 
   const Extension* extension = GetExtensionControllingPref(*pref_object);
@@ -1188,6 +1195,20 @@
   }
   return false;
 }
+
+bool PrefsUtil::IsHotwordDisabledForChildUser(const std::string& pref_name) {
+  const std::string& hotwordEnabledPref =
+      chromeos::assistant::prefs::kAssistantHotwordEnabled;
+  if (!profile_->IsChild() || pref_name != hotwordEnabledPref)
+    return false;
+
+  PrefService* pref_service = FindServiceForPref(hotwordEnabledPref);
+  const PrefService::Preference* pref =
+      pref_service->FindPreference(hotwordEnabledPref);
+  DCHECK(pref);
+  const bool isHotwordEnabled = pref->GetValue()->GetIfBool().value_or(false);
+  return !isHotwordEnabled;
+}
 #endif
 
 bool PrefsUtil::IsPrefSupervisorControlled(const std::string& pref_name) {
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.h b/chrome/browser/extensions/api/settings_private/prefs_util.h
index 569aa01..f333756 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.h
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.h
@@ -82,6 +82,10 @@
   // Returns whether |pref_name| corresponds to a pref that is controlled by
   // the primary user, and |profile_| is not the primary profile.
   bool IsPrefPrimaryUserControlled(const std::string& pref_name);
+
+  // Returns whether |pref_name| corresponds to the hotword enabled pref, if the
+  // pref is disabled, and if |profile_| is a child user.
+  bool IsHotwordDisabledForChildUser(const std::string& pref_name);
 #endif
 
   // Returns whether |pref_name| corresponds to a pref that is controlled by
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index db87355..f8f6656 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -690,8 +690,8 @@
 }
 
 void WebstorePrivateBeginInstallWithManifest3Function::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  switch (result) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  switch (payload.result) {
     case ExtensionInstallPrompt::Result::ACCEPTED:
     case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED: {
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
@@ -715,7 +715,7 @@
     }
     case ExtensionInstallPrompt::Result::USER_CANCELED:
     case ExtensionInstallPrompt::Result::ABORTED: {
-      HandleInstallAbort(result ==
+      HandleInstallAbort(payload.result ==
                          ExtensionInstallPrompt::Result::USER_CANCELED);
       break;
     }
@@ -726,8 +726,8 @@
 }
 
 void WebstorePrivateBeginInstallWithManifest3Function::OnRequestPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  switch (result) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  switch (payload.result) {
     case ExtensionInstallPrompt::Result::ACCEPTED:
       AddExtensionToPendingList(details().id, profile_);
       break;
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
index 9f9477c..f80ba9fb 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -102,8 +102,8 @@
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
 
   void OnFrictionPromptDone(bool result);
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
-  void OnRequestPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
+  void OnRequestPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
   void OnBlockByPolicyPromptDone();
 
   void HandleInstallProceed();
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index ded5a17..e629ccd 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -826,7 +826,8 @@
   }
 }
 
-void CrxInstaller::OnInstallPromptDone(ExtensionInstallPrompt::Result result) {
+void CrxInstaller::OnInstallPromptDone(
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // If update_from_settings_page_ boolean is true, this functions is
@@ -835,7 +836,7 @@
   // ExtensionInstallPrompt::ShowDialog().
 
   ExtensionService* service = service_weak_.get();
-  switch (result) {
+  switch (payload.result) {
     case ExtensionInstallPrompt::Result::ACCEPTED:
       if (!service || service->browser_terminating())
         return;
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index ac9bc86..23f6f961 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -140,7 +140,7 @@
                                       const std::string& public_key,
                                       const base::FilePath& unpacked_dir);
 
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   void InitializeCreationFlagsForUpdate(const Extension* extension,
                                         const int initial_flags);
diff --git a/chrome/browser/extensions/extension_assets_manager_chromeos.cc b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
index cf4500f..59bc7776 100644
--- a/chrome/browser/extensions/extension_assets_manager_chromeos.cc
+++ b/chrome/browser/extensions/extension_assets_manager_chromeos.cc
@@ -441,7 +441,7 @@
 
   std::vector<std::string> versions;
   versions.reserve(extension_info->DictSize());
-  for (const auto& kv : extension_info->DictItems()) {
+  for (const auto kv : extension_info->DictItems()) {
     versions.push_back(kv.first);
   }
 
diff --git a/chrome/browser/extensions/extension_checkup.cc b/chrome/browser/extensions/extension_checkup.cc
deleted file mode 100644
index e2358010..0000000
--- a/chrome/browser/extensions/extension_checkup.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2019 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/extensions/extension_checkup.h"
-
-#include "base/metrics/field_trial_params.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "extensions/browser/extension_prefs.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/management_policy.h"
-#include "extensions/common/extension_features.h"
-#include "extensions/common/extension_set.h"
-
-using content::BrowserContext;
-
-namespace {
-
-bool ShouldShowExtensionsCheckup(content::BrowserContext* context) {
-  // Don't show the promo if the extensions checkup experiment isn't enabled.
-  if (!base::FeatureList::IsEnabled(extensions_features::kExtensionsCheckup)) {
-    return false;
-  }
-
-  // Don't show promo if extensions are not enabled.
-  extensions::ExtensionService* extension_service =
-      extensions::ExtensionSystem::Get(context)->extension_service();
-  if (!extension_service || !extension_service->extensions_enabled())
-    return false;
-
-  // Don't show the promo if there are no extensions installed.
-  std::unique_ptr<extensions::ExtensionSet> extension_set =
-      extensions::ExtensionRegistry::Get(context)
-          ->GenerateInstalledExtensionsSet();
-  if (extension_set->is_empty())
-    return false;
-
-  // Check if users have non policy-installed extensions. If all the extensions
-  // are policy-installed (even if they can be disabled), then do not show the
-  // extensions checkup experiment.
-  for (const auto& extension : *extension_set) {
-    if (extension->is_extension() &&
-        !extensions::Manifest::IsPolicyLocation(extension->location()) &&
-        !extensions::Manifest::IsComponentLocation(extension->location()) &&
-        !(extension->creation_flags() &
-          extensions::Extension::WAS_INSTALLED_BY_DEFAULT)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-}  // namespace
-
-namespace extensions {
-
-bool ShouldShowExtensionsCheckupOnStartup(content::BrowserContext* context) {
-  ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
-  if (ShouldShowExtensionsCheckup(context) &&
-      base::GetFieldTrialParamValueByFeature(
-          extensions_features::kExtensionsCheckup,
-          extensions_features::kExtensionsCheckupEntryPointParameter) ==
-          extensions_features::kStartupEntryPoint &&
-      !prefs->HasUserSeenExtensionsCheckupOnStartup()) {
-    return true;
-  }
-  return false;
-}
-
-bool ShouldShowExtensionsCheckupPromo(content::BrowserContext* context) {
-  return ShouldShowExtensionsCheckup(context) &&
-         base::GetFieldTrialParamValueByFeature(
-             extensions_features::kExtensionsCheckup,
-             extensions_features::kExtensionsCheckupEntryPointParameter) ==
-             extensions_features::kNtpPromoEntryPoint;
-}
-
-CheckupMessage GetCheckupMessageFocus() {
-  return static_cast<CheckupMessage>(base::GetFieldTrialParamByFeatureAsInt(
-      extensions_features::kExtensionsCheckup,
-      extensions_features::kExtensionsCheckupBannerMessageParameter, 2));
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_checkup.h b/chrome/browser/extensions/extension_checkup.h
deleted file mode 100644
index b33fc56c7..0000000
--- a/chrome/browser/extensions/extension_checkup.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2019 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_EXTENSIONS_EXTENSION_CHECKUP_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_CHECKUP_H_
-
-namespace content {
-class BrowserContext;
-}
-
-namespace extensions {
-// The type of message the extensions checkup banner will convey. These values
-// are persisted to logs. Entries should not be renumbered and numeric values
-// should never be reused.
-enum class CheckupMessage {
-  // A performance focused message.
-  PERFORMANCE = 0,
-  // A privacy focused message.
-  PRIVACY = 1,
-  // A neutral message.
-  NEUTRAL = 2,
-  kMaxValue = NEUTRAL
-};
-
-// Returns true if the user should be shown the extensions page and checkup
-// banner upon startup.
-bool ShouldShowExtensionsCheckupOnStartup(content::BrowserContext* context);
-
-// Returns true if the user should be shown the extensions checkup promo in
-// the NTP.
-bool ShouldShowExtensionsCheckupPromo(content::BrowserContext* context);
-
-// Returns an enum representing the type of message the checkup banner will
-// convey.
-CheckupMessage GetCheckupMessageFocus();
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_CHECKUP_H_
diff --git a/chrome/browser/extensions/extension_checkup_unittest.cc b/chrome/browser/extensions/extension_checkup_unittest.cc
deleted file mode 100644
index 225cace..0000000
--- a/chrome/browser/extensions/extension_checkup_unittest.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2019 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/extensions/extension_checkup.h"
-
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_service_test_base.h"
-#include "extensions/common/extension_builder.h"
-#include "extensions/common/extension_features.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-class ExtensionCheckupTest : public ExtensionServiceTestBase,
-                             public testing::WithParamInterface<const char*> {
- public:
-  ExtensionCheckupTest() {}
-  ~ExtensionCheckupTest() override {}
-
-  void SetUp() override {
-    feature_list_.InitAndEnableFeatureWithParameters(
-        extensions_features::kExtensionsCheckup,
-        {{extensions_features::kExtensionsCheckupEntryPointParameter,
-          GetParam()}});
-    ExtensionServiceTestBase::SetUp();
-    InitializeEmptyExtensionService();
-    service()->Init();
-  }
-
-  // Adds a user installed extension.
-  void AddUserInstalledExtension() {
-    scoped_refptr<const Extension> extension = ExtensionBuilder("foo").Build();
-    service()->AddExtension(extension.get());
-  }
-
-  void AddExemptExtensions() {
-    // Install policy extension.
-    scoped_refptr<const Extension> policy_extension =
-        ExtensionBuilder("policy")
-            .SetLocation(mojom::ManifestLocation::kExternalPolicy)
-            .Build();
-    service()->AddExtension(policy_extension.get());
-    // Install component extension.
-    scoped_refptr<const Extension> component_extension =
-        ExtensionBuilder("component")
-            .SetLocation(mojom::ManifestLocation::kComponent)
-            .Build();
-    service()->AddExtension(component_extension.get());
-    // Load a default installed extension.
-    int creation_flags = Extension::WAS_INSTALLED_BY_DEFAULT;
-    scoped_refptr<const Extension> default_install_extension =
-        ExtensionBuilder("default").AddFlags(creation_flags).Build();
-    service()->AddExtension(default_install_extension.get());
-    ASSERT_TRUE(default_install_extension);
-  }
-
-  // Verify the extensions checkup behavior.
-  bool ShouldShowExperimentCheckup() {
-    if (GetParam() == extensions_features::kNtpPromoEntryPoint)
-      return ShouldShowExtensionsCheckupPromo(browser_context());
-    return ShouldShowExtensionsCheckupOnStartup(browser_context());
-  }
-
-  // Verify that the opposite entry point will always return false (i.e if the
-  // user is supposed to see the middle slot promo entry point they should never
-  // see the extensions checkup upon startup).
-  void VerifyNonExperimentCheckupDisabled() {
-    if (GetParam() == extensions_features::kNtpPromoEntryPoint)
-      EXPECT_FALSE(ShouldShowExtensionsCheckupOnStartup(browser_context()));
-    else
-      EXPECT_FALSE(ShouldShowExtensionsCheckupPromo(browser_context()));
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(ExtensionCheckupTest);
-};
-
-TEST_P(ExtensionCheckupTest, NoInstalledExtensions) {
-  VerifyNonExperimentCheckupDisabled();
-  EXPECT_FALSE(ShouldShowExperimentCheckup());
-}
-
-TEST_P(ExtensionCheckupTest, NoUserInstalledExtensions) {
-  AddExemptExtensions();
-  VerifyNonExperimentCheckupDisabled();
-  EXPECT_FALSE(ShouldShowExperimentCheckup());
-}
-
-// Checkup is shown if at least one non policy extension is installed.
-TEST_P(ExtensionCheckupTest, OnlyOneUserInstalledExtension) {
-  AddUserInstalledExtension();
-  VerifyNonExperimentCheckupDisabled();
-  EXPECT_TRUE(ShouldShowExperimentCheckup());
-}
-
-TEST_P(ExtensionCheckupTest, UserAndNonUserInstalledExtensions) {
-  AddUserInstalledExtension();
-  AddExemptExtensions();
-  VerifyNonExperimentCheckupDisabled();
-  EXPECT_TRUE(ShouldShowExperimentCheckup());
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    ExtensionCheckupTest,
-    ::testing::Values(extensions_features::kNtpPromoEntryPoint,
-                      extensions_features::kStartupEntryPoint));
-}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index 2013a50..d638831 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -449,6 +449,14 @@
          is_requesting_host_permissions_ && type_ == INSTALL_PROMPT;
 }
 
+ExtensionInstallPrompt::DoneCallbackPayload::DoneCallbackPayload(Result result)
+    : DoneCallbackPayload(result, std::string()) {}
+
+ExtensionInstallPrompt::DoneCallbackPayload::DoneCallbackPayload(
+    Result result,
+    std::string justification)
+    : result(result), justification(std::move(justification)) {}
+
 // static
 ExtensionInstallPrompt::PromptType
 ExtensionInstallPrompt::GetReEnablePromptTypeForExtension(
@@ -553,7 +561,7 @@
   if (extension->is_theme() && extension->from_webstore() &&
       prompt_->type() != EXTENSION_REQUEST_PROMPT &&
       prompt_->type() != EXTENSION_PENDING_REQUEST_PROMPT) {
-    std::move(done_callback_).Run(Result::ACCEPTED);
+    std::move(done_callback_).Run(DoneCallbackPayload(Result::ACCEPTED));
     return;
   }
 
@@ -647,7 +655,7 @@
   prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
 
   if (show_params_->WasParentDestroyed()) {
-    std::move(done_callback_).Run(Result::ABORTED);
+    std::move(done_callback_).Run(DoneCallbackPayload(Result::ABORTED));
     return;
   }
 
@@ -679,22 +687,25 @@
     // pumping a few times before the user clicks accept or cancel.
     case extensions::ScopedTestDialogAutoConfirm::ACCEPT:
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::BindOnce(std::move(done_callback_),
-                                    ExtensionInstallPrompt::Result::ACCEPTED));
+          FROM_HERE,
+          base::BindOnce(
+              std::move(done_callback_),
+              DoneCallbackPayload(ExtensionInstallPrompt::Result::ACCEPTED)));
       return true;
     case extensions::ScopedTestDialogAutoConfirm::ACCEPT_AND_OPTION:
     case extensions::ScopedTestDialogAutoConfirm::ACCEPT_AND_REMEMBER_OPTION:
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
-          base::BindOnce(
-              std::move(done_callback_),
-              ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED));
+          base::BindOnce(std::move(done_callback_),
+                         DoneCallbackPayload(ExtensionInstallPrompt::Result::
+                                                 ACCEPTED_AND_OPTION_CHECKED)));
       return true;
     case extensions::ScopedTestDialogAutoConfirm::CANCEL:
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
           base::BindOnce(std::move(done_callback_),
-                         ExtensionInstallPrompt::Result::USER_CANCELED));
+                         DoneCallbackPayload(
+                             ExtensionInstallPrompt::Result::USER_CANCELED)));
       return true;
   }
 
diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h
index 1affafa6..2f8aa2c 100644
--- a/chrome/browser/extensions/extension_install_prompt.h
+++ b/chrome/browser/extensions/extension_install_prompt.h
@@ -253,7 +253,16 @@
     ABORTED,
   };
 
-  using DoneCallback = base::OnceCallback<void(Result result)>;
+  struct DoneCallbackPayload {
+    explicit DoneCallbackPayload(Result result);
+    DoneCallbackPayload(Result result, std::string justification);
+    ~DoneCallbackPayload() = default;
+
+    const Result result;
+    const std::string justification;
+  };
+
+  using DoneCallback = base::OnceCallback<void(DoneCallbackPayload payload)>;
 
   using ShowDialogCallback = base::RepeatingCallback<void(
       std::unique_ptr<ExtensionInstallPromptShowParams>,
diff --git a/chrome/browser/extensions/extension_install_prompt_test_helper.cc b/chrome/browser/extensions/extension_install_prompt_test_helper.cc
index 6c5cb878..de5d754 100644
--- a/chrome/browser/extensions/extension_install_prompt_test_helper.cc
+++ b/chrome/browser/extensions/extension_install_prompt_test_helper.cc
@@ -19,32 +19,51 @@
 
 ExtensionInstallPrompt::DoneCallback
 ExtensionInstallPromptTestHelper::GetCallback() {
-  return base::BindOnce(&ExtensionInstallPromptTestHelper::HandleResult,
+  return base::BindOnce(&ExtensionInstallPromptTestHelper::HandlePayload,
                         base::Unretained(this));
 }
 
-ExtensionInstallPrompt::Result
-ExtensionInstallPromptTestHelper::result() const {
-  if (!result_.get()) {
-    ADD_FAILURE() << "Result was never set!";
+ExtensionInstallPrompt::DoneCallbackPayload
+ExtensionInstallPromptTestHelper::payload() const {
+  if (!payload_.get()) {
+    ADD_FAILURE() << "Payload was never set!";
+    return ExtensionInstallPrompt::DoneCallbackPayload(
+        ExtensionInstallPrompt::Result::ACCEPTED);  // Avoid crashing.
+  }
+  return *payload_;
+}
+
+ExtensionInstallPrompt::Result ExtensionInstallPromptTestHelper::result()
+    const {
+  if (!payload_.get()) {
+    ADD_FAILURE() << "Payload was never set!";
     return ExtensionInstallPrompt::Result::ACCEPTED;  // Avoid crashing.
   }
-  return *result_;
+  return payload_->result;
 }
 
-void ExtensionInstallPromptTestHelper::ClearResultForTesting() {
-  if (!result_.get()) {
-    ADD_FAILURE() << "Result was never set!";
+std::string ExtensionInstallPromptTestHelper::justification() const {
+  if (!payload_.get()) {
+    ADD_FAILURE() << "Payload was never set!";
+    return std::string();  // Avoid crashing.
+  }
+  return payload_->justification;
+}
+
+void ExtensionInstallPromptTestHelper::ClearPayloadForTesting() {
+  if (!payload_.get()) {
+    ADD_FAILURE() << "Payload was never set!";
     return;
   }
-  result_.reset();
+  payload_.reset();
 }
 
-void ExtensionInstallPromptTestHelper::HandleResult(
-    ExtensionInstallPrompt::Result result) {
-  if (result_.get())
-    ADD_FAILURE() << "HandleResult() called twice!";
+void ExtensionInstallPromptTestHelper::HandlePayload(
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload_.get())
+    ADD_FAILURE() << "HandlePayload() called twice!";
   if (quit_closure_)
     std::move(quit_closure_).Run();
-  result_ = std::make_unique<ExtensionInstallPrompt::Result>(result);
+  payload_ = std::make_unique<ExtensionInstallPrompt::DoneCallbackPayload>(
+      std::move(payload));
 }
diff --git a/chrome/browser/extensions/extension_install_prompt_test_helper.h b/chrome/browser/extensions/extension_install_prompt_test_helper.h
index 2f76c5c3..a6e5fcc 100644
--- a/chrome/browser/extensions/extension_install_prompt_test_helper.h
+++ b/chrome/browser/extensions/extension_install_prompt_test_helper.h
@@ -9,7 +9,7 @@
 #include "chrome/browser/extensions/extension_install_prompt.h"
 
 // A helper class to be used with ExtensionInstallPrompt that keeps track of the
-// result. Note that this class does no lifetime management.
+// payload. Note that this class does no lifetime management.
 class ExtensionInstallPromptTestHelper {
  public:
   ExtensionInstallPromptTestHelper();
@@ -19,21 +19,27 @@
   // Returns a callback to be used with the ExtensionInstallPrompt.
   ExtensionInstallPrompt::DoneCallback GetCallback();
 
-  // Note: This ADD_FAILURE()s if result_ has not been set.
+  // Note: This causes |ADD_FAILURE()| if |payload_| has not been set.
+  ExtensionInstallPrompt::DoneCallbackPayload payload() const;
+
+  // Note: This causes |ADD_FAILURE()| if |payload_| has not been set.
   ExtensionInstallPrompt::Result result() const;
 
-  bool has_result() const { return result_ != nullptr; }
+  // Note: This causes |ADD_FAILURE()| if |payload_| has not been set.
+  std::string justification() const;
 
-  // Clears the result to re-use this test helper.
-  // Note: This ADD_FAILURE()s if the result_ has not been set.
-  void ClearResultForTesting();
+  bool has_payload() const { return payload_ != nullptr; }
+
+  // Clears the payload to re-use this test helper.
+  // Note: This ADD_FAILURE()s if the payload_ has not been set.
+  void ClearPayloadForTesting();
 
  private:
-  void HandleResult(ExtensionInstallPrompt::Result result);
+  void HandlePayload(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
-  std::unique_ptr<ExtensionInstallPrompt::Result> result_;
+  std::unique_ptr<ExtensionInstallPrompt::DoneCallbackPayload> payload_;
 
-  // A closure to run once HandleResult() has been called; used for exiting
+  // A closure to run once HandlePayload() has been called; used for exiting
   // run loops in tests.
   base::OnceClosure quit_closure_;
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 544162b..80a83726 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4527,7 +4527,8 @@
     std::vector<ExternalInstallError*> errors =
         external_install_manager->GetErrorsForTesting();
     ASSERT_EQ(1u, errors.size());
-    errors[0]->OnInstallPromptDone(ExtensionInstallPrompt::Result::ABORTED);
+    errors[0]->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+        ExtensionInstallPrompt::Result::ABORTED));
     base::RunLoop().RunUntilIdle();
     // Note: Calling OnInstallPromptDone() can result in the removal of the
     // error by the manager (which owns the object), so the contents |errors|
@@ -7031,15 +7032,17 @@
 
   // Accept the first extension, this will remove the error associated with
   // this extension. Also verify the other errors still exist.
-  GetError(extension_ids[0])->OnInstallPromptDone(
-      ExtensionInstallPrompt::Result::ACCEPTED);
+  GetError(extension_ids[0])
+      ->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::ACCEPTED));
   EXPECT_FALSE(GetError(extension_ids[0]));
   ASSERT_TRUE(GetError(extension_ids[1]));
   EXPECT_TRUE(GetError(extension_ids[2]));
 
   // Abort the second extension.
-  GetError(extension_ids[1])->OnInstallPromptDone(
-      ExtensionInstallPrompt::Result::USER_CANCELED);
+  GetError(extension_ids[1])
+      ->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::USER_CANCELED));
   EXPECT_FALSE(GetError(extension_ids[0]));
   EXPECT_FALSE(GetError(extension_ids[1]));
   ASSERT_TRUE(GetError(extension_ids[2]));
@@ -7074,7 +7077,8 @@
   // Abort the extension install prompt. This should cause the
   // ExternalInstallError to be deleted asynchronously.
   GetError(good_crx)->OnInstallPromptDone(
-      ExtensionInstallPrompt::Result::ABORTED);
+      ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::ABORTED));
   EXPECT_TRUE(GetError(good_crx));
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(GetError(good_crx));
@@ -7144,7 +7148,8 @@
     const std::string& extension_id = data[i].id;
     EXPECT_TRUE(GetError(extension_id));
     GetError(extension_id)
-        ->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
+        ->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+            ExtensionInstallPrompt::Result::USER_CANCELED));
     EXPECT_FALSE(GetError(extension_id));
   }
   EXPECT_FALSE(service()
@@ -7354,7 +7359,8 @@
   // Click the negative response.
   service_->external_install_manager()
       ->GetErrorsForTesting()[0]
-      ->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
+      ->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::USER_CANCELED));
   // The Extension should be uninstalled.
   EXPECT_FALSE(registry()->GetExtensionById(updates_from_webstore,
                                             ExtensionRegistry::EVERYTHING));
@@ -7392,7 +7398,8 @@
   // Accept the extension.
   service_->external_install_manager()
       ->GetErrorsForTesting()[0]
-      ->OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
+      ->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::ACCEPTED));
 
   // It should be enabled again.
   EXPECT_TRUE(registry()->enabled_extensions().GetByID(updates_from_webstore));
diff --git a/chrome/browser/extensions/external_install_error.cc b/chrome/browser/extensions/external_install_error.cc
index ab0fc50..65016ef 100644
--- a/chrome/browser/extensions/external_install_error.cc
+++ b/chrome/browser/extensions/external_install_error.cc
@@ -281,12 +281,14 @@
 
 void ExternalInstallBubbleAlert::BubbleViewAcceptButtonPressed(
     Browser* browser) {
-  error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
+  error_->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+      ExtensionInstallPrompt::Result::ACCEPTED));
 }
 
 void ExternalInstallBubbleAlert::BubbleViewCancelButtonPressed(
     Browser* browser) {
-  error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
+  error_->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+      ExtensionInstallPrompt::Result::USER_CANCELED));
 }
 
 }  // namespace
@@ -350,7 +352,7 @@
 }
 
 void ExternalInstallError::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
   const Extension* extension = GetExtension();
 
   // If the error isn't removed and deleted as part of handling the user's
@@ -360,7 +362,7 @@
       FROM_HERE, base::BindOnce(&ExternalInstallError::RemoveError,
                                 weak_factory_.GetWeakPtr()));
 
-  switch (result) {
+  switch (payload.result) {
     case ExtensionInstallPrompt::Result::ACCEPTED:
     case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED:
       if (extension) {
diff --git a/chrome/browser/extensions/external_install_error.h b/chrome/browser/extensions/external_install_error.h
index dbb51ba..f2f560d 100644
--- a/chrome/browser/extensions/external_install_error.h
+++ b/chrome/browser/extensions/external_install_error.h
@@ -57,7 +57,7 @@
                        ExternalInstallManager* manager);
   ~ExternalInstallError() override;
 
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   void DidOpenBubbleView();
   void DidCloseBubbleView();
diff --git a/chrome/browser/extensions/navigation_observer.cc b/chrome/browser/extensions/navigation_observer.cc
index f938714..3b97d05 100644
--- a/chrome/browser/extensions/navigation_observer.cc
+++ b/chrome/browser/extensions/navigation_observer.cc
@@ -116,7 +116,7 @@
 }
 
 void NavigationObserver::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
   // The extension was already uninstalled.
   if (in_progress_prompt_extension_id_.empty())
     return;
@@ -126,7 +126,7 @@
       in_progress_prompt_extension_id_, ExtensionRegistry::EVERYTHING);
   CHECK(extension);
 
-  if (result == ExtensionInstallPrompt::Result::ACCEPTED) {
+  if (payload.result == ExtensionInstallPrompt::Result::ACCEPTED) {
     NavigationController* nav_controller =
         in_progress_prompt_navigation_controller_;
     CHECK(nav_controller);
diff --git a/chrome/browser/extensions/navigation_observer.h b/chrome/browser/extensions/navigation_observer.h
index 555632f..e1f60fbd 100644
--- a/chrome/browser/extensions/navigation_observer.h
+++ b/chrome/browser/extensions/navigation_observer.h
@@ -55,7 +55,7 @@
   void PromptToEnableExtensionIfNecessary(
       content::NavigationController* nav_controller);
 
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  void OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   // extensions::ExtensionRegistryObserver:
   void OnExtensionUninstalled(content::BrowserContext* browser_context,
diff --git a/chrome/browser/extensions/webstore_reinstaller.cc b/chrome/browser/extensions/webstore_reinstaller.cc
index 282a84b..24abc5b3 100644
--- a/chrome/browser/extensions/webstore_reinstaller.cc
+++ b/chrome/browser/extensions/webstore_reinstaller.cc
@@ -76,9 +76,9 @@
 }
 
 void WebstoreReinstaller::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  if (result != ExtensionInstallPrompt::Result::ACCEPTED) {
-    WebstoreStandaloneInstaller::OnInstallPromptDone(result);
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload.result != ExtensionInstallPrompt::Result::ACCEPTED) {
+    WebstoreStandaloneInstaller::OnInstallPromptDone(std::move(payload));
     return;
   }
 
@@ -92,7 +92,7 @@
     AbortInstall();
     return;
   }
-  WebstoreStandaloneInstaller::OnInstallPromptDone(result);
+  WebstoreStandaloneInstaller::OnInstallPromptDone(std::move(payload));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/webstore_reinstaller.h b/chrome/browser/extensions/webstore_reinstaller.h
index 7e1c0c5..34d83bd 100644
--- a/chrome/browser/extensions/webstore_reinstaller.h
+++ b/chrome/browser/extensions/webstore_reinstaller.h
@@ -35,7 +35,8 @@
   content::WebContents* GetWebContents() const override;
   std::unique_ptr<ExtensionInstallPrompt::Prompt> CreateInstallPrompt()
       const override;
-  void OnInstallPromptDone(ExtensionInstallPrompt::Result result) override;
+  void OnInstallPromptDone(
+      ExtensionInstallPrompt::DoneCallbackPayload payload) override;
 
   // content::WebContentsObserver:
   void WebContentsDestroyed() override;
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index 7090196..c3ef0d2d 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -133,7 +133,8 @@
     ShowInstallUI();
     // Control flow finishes up in OnInstallPromptDone().
   } else {
-    OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
+    OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
+        ExtensionInstallPrompt::Result::ACCEPTED));
   }
 }
 
@@ -179,20 +180,20 @@
 }
 
 void WebstoreStandaloneInstaller::OnInstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  if (result == ExtensionInstallPrompt::Result::USER_CANCELED) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload.result == ExtensionInstallPrompt::Result::USER_CANCELED) {
     CompleteInstall(webstore_install::USER_CANCELLED,
                     webstore_install::kUserCancelledError);
     return;
   }
 
-  if (result == ExtensionInstallPrompt::Result::ABORTED ||
+  if (payload.result == ExtensionInstallPrompt::Result::ABORTED ||
       !CheckRequestorAlive()) {
     CompleteInstall(webstore_install::ABORTED, std::string());
     return;
   }
 
-  DCHECK(result == ExtensionInstallPrompt::Result::ACCEPTED);
+  DCHECK(payload.result == ExtensionInstallPrompt::Result::ACCEPTED);
 
   std::unique_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
 
diff --git a/chrome/browser/extensions/webstore_standalone_installer.h b/chrome/browser/extensions/webstore_standalone_installer.h
index b70309d..96b9afd 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.h
+++ b/chrome/browser/extensions/webstore_standalone_installer.h
@@ -125,7 +125,8 @@
   virtual std::unique_ptr<WebstoreInstaller::Approval> CreateApproval() const;
 
   // Called once the install prompt has finished.
-  virtual void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+  virtual void OnInstallPromptDone(
+      ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   // Accessors to be used by subclasses.
   bool show_user_count() const { return show_user_count_; }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 3257267..c7010b0 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4006,6 +4006,11 @@
     "expiry_milestone": 96
   },
   {
+    "name": "ntp-realbox-suggestion-answers",
+    "owners": [ "mahmadi", "mfacey" ],
+    "expiry_milestone": 96
+  },
+  {
     "name": "ntp-recipe-tasks-module",
     "owners": [ "mahmadi", "tiborg" ],
     "expiry_milestone": 96
@@ -4271,6 +4276,11 @@
     "expiry_milestone": 89
   },
   {
+    "name": "omnibox-updated-connection-security-indicators",
+    "owners": [ "meacer", "chrome-trusty-transport@google.com" ],
+    "expiry_milestone": 96
+  },
+  {
     "name": "omnibox-webui-omnibox-popup",
     "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 99
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a133c1a..ba1948b 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1275,10 +1275,6 @@
 const char kExtensionContentVerificationEnforceStrict[] =
     "Enforce strict (hard fail if we can't get hashes)";
 
-const char kExtensionsCheckupName[] = "Extensions Checkup";
-const char kExtensionsCheckupDescription[] =
-    "Enable the extensions checkup experiment";
-
 const char kExtensionsOnChromeUrlsName[] = "Extensions on chrome:// URLs";
 const char kExtensionsOnChromeUrlsDescription[] =
     "Enables running extensions on chrome:// URLs, where extensions explicitly "
@@ -1891,6 +1887,11 @@
     "Changes the maximum number of autocomplete matches displayed in the "
     "Omnibox UI.";
 
+const char kOmniboxUpdatedConnectionSecurityIndicatorsName[] =
+    "Omnibox Updated connection security indicators";
+const char kOmniboxUpdatedConnectionSecurityIndicatorsDescription[] =
+    "Use new connection security indicators for https pages in the omnibox.";
+
 const char kOmniboxMaxURLMatchesName[] = "Omnibox Max URL Matches";
 const char kOmniboxMaxURLMatchesDescription[] =
     "The maximum number of URL matches to show, unless there are no "
@@ -3746,6 +3747,11 @@
 const char kNtpModulesRedesignedDescription[] =
     "Shows the redesigned modules on the New Tab Page.";
 
+const char kNtpRealboxSuggestionAnswersName[] =
+    "NTP Realbox Suggestion Answers";
+const char kNtpRealboxSuggestionAnswersDescription[] =
+    "Shows suggestion answers in the NTP Realbox when enabled.";
+
 const char kEnableReaderModeName[] = "Enable Reader Mode";
 const char kEnableReaderModeDescription[] =
     "Allows viewing of simplified web pages by selecting 'Customize and "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 69a98db..26b9cc8 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -732,9 +732,6 @@
 extern const char kExtensionContentVerificationEnforce[];
 extern const char kExtensionContentVerificationEnforceStrict[];
 
-extern const char kExtensionsCheckupName[];
-extern const char kExtensionsCheckupDescription[];
-
 extern const char kExtensionsOnChromeUrlsName[];
 extern const char kExtensionsOnChromeUrlsDescription[];
 
@@ -1077,6 +1074,9 @@
 extern const char kOmniboxUIMaxAutocompleteMatchesName[];
 extern const char kOmniboxUIMaxAutocompleteMatchesDescription[];
 
+extern const char kOmniboxUpdatedConnectionSecurityIndicatorsName[];
+extern const char kOmniboxUpdatedConnectionSecurityIndicatorsDescription[];
+
 extern const char kOmniboxMaxURLMatchesName[];
 extern const char kOmniboxMaxURLMatchesDescription[];
 
@@ -2139,6 +2139,9 @@
 extern const char kNtpModulesRedesignedName[];
 extern const char kNtpModulesRedesignedDescription[];
 
+extern const char kNtpRealboxSuggestionAnswersName[];
+extern const char kNtpRealboxSuggestionAnswersDescription[];
+
 extern const char kEnableReaderModeName[];
 extern const char kEnableReaderModeDescription[];
 
diff --git a/chrome/browser/hid/chrome_hid_delegate.cc b/chrome/browser/hid/chrome_hid_delegate.cc
index 48d746a9..ce1e982 100644
--- a/chrome/browser/hid/chrome_hid_delegate.cc
+++ b/chrome/browser/hid/chrome_hid_delegate.cc
@@ -13,14 +13,12 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/hid/hid_chooser.h"
 #include "chrome/browser/ui/hid/hid_chooser_controller.h"
-#include "content/public/browser/web_contents.h"
+#include "content/public/browser/render_frame_host.h"
 
 namespace {
 
 HidChooserContext* GetChooserContext(content::RenderFrameHost* frame) {
-  auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
-  auto* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  auto* profile = Profile::FromBrowserContext(frame->GetBrowserContext());
   return HidChooserContextFactory::GetForProfile(profile);
 }
 
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java
index 91236b1..6e860c20 100644
--- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java
+++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java
@@ -52,4 +52,9 @@
     public static final BooleanCachedFieldTrialParameter SKIP_AGSA_VERSION_CHECK =
             new BooleanCachedFieldTrialParameter(ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH,
                     SKIP_AGSA_VERSION_CHECK_PARAM_NAME, false);
+    private static final String SKIP_LENS_ELIGIBILITY_CHECKS_PARAM_NAME =
+            "skipLensEligibilityChecks";
+    public static final BooleanCachedFieldTrialParameter SKIP_LENS_ELIGIBILITY_CHECKS =
+            new BooleanCachedFieldTrialParameter(ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH,
+                    SKIP_LENS_ELIGIBILITY_CHECKS_PARAM_NAME, false);
 }
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
index f18606bc..119da55 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
+++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -99,7 +99,7 @@
   params.target_name = params.app_name;
   params.select_only_screen = true;
   params.request_audio = true;
-  params.approve_audio_by_default = true;
+  params.force_audio_checkboxes_to_default_checked = true;
 
   return params;
 }
diff --git a/chrome/browser/media/webrtc/desktop_media_picker.h b/chrome/browser/media/webrtc/desktop_media_picker.h
index 5a6386b..4e7c9b1 100644
--- a/chrome/browser/media/webrtc/desktop_media_picker.h
+++ b/chrome/browser/media/webrtc/desktop_media_picker.h
@@ -59,8 +59,10 @@
     std::u16string target_name;
     // Whether audio capture should be shown as an option in the picker.
     bool request_audio = false;
-    // Whether audio capture option should be approved by default if shown.
-    bool approve_audio_by_default = true;
+    // Normally, the media-picker sets the default states for the audio
+    // checkboxes. If |force_audio_checkboxes_to_default_checked| is |true|,
+    // it sets them all to |checked|.
+    bool force_audio_checkboxes_to_default_checked = false;
     // This flag controls the behvior in the case where the picker is invoked to
     // select a screen and there is only one screen available.  If true, the
     // dialog is bypassed entirely and the screen is automatically selected.
diff --git a/chrome/browser/media/webrtc/desktop_media_picker_controller.cc b/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
index cc6248d..1cb59ec 100644
--- a/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
+++ b/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
@@ -90,8 +90,7 @@
     content::DesktopMediaID media_id = source_list->GetSource(0).id;
     DCHECK_EQ(media_id.type, content::DesktopMediaID::TYPE_SCREEN);
 #if defined(USE_CRAS) || defined(OS_WIN)
-    media_id.audio_share =
-        params_.request_audio && params_.approve_audio_by_default;
+    media_id.audio_share = params_.request_audio;
 #else
     media_id.audio_share = false;
 #endif
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc
index 7d053ca..0e4ae525 100644
--- a/chrome/browser/media/webrtc/display_media_access_handler.cc
+++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -254,12 +254,6 @@
   picker_params.request_audio =
       pending_request.request.audio_type ==
       blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE;
-  // getDisplayMedia's checkbox state defaults to unchecked, but for
-  // getCurrentBrowsingContextMedia, we default to checked.
-  picker_params.approve_audio_by_default =
-      (picker_params.request_audio &&
-       pending_request.request.video_type ==
-           blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB);
   pending_request.picker->Show(picker_params, std::move(source_lists),
                                std::move(done_callback));
 }
diff --git a/chrome/browser/metrics/BUILD.gn b/chrome/browser/metrics/BUILD.gn
index 564454e..89912a4 100644
--- a/chrome/browser/metrics/BUILD.gn
+++ b/chrome/browser/metrics/BUILD.gn
@@ -15,15 +15,12 @@
     "//base",
     "//build:chromeos_buildflags",
     "//chrome/browser",
+    "//chrome/test:sync_integration_test_support",
     "//components/signin/public/identity_manager",
     "//components/sync/test/fake_server",
     "//third_party/metrics_proto",
   ]
 
-  if (!is_fuchsia) {
-    deps += [ "//chrome/test:sync_integration_test_support" ]
-  }
-
   if (is_android) {
     deps += [ "//content/public/browser" ]
   }
diff --git a/chrome/browser/metrics/power/power_details_provider.h b/chrome/browser/metrics/power/power_details_provider.h
index 1403f0c..c7d39f8 100644
--- a/chrome/browser/metrics/power/power_details_provider.h
+++ b/chrome/browser/metrics/power/power_details_provider.h
@@ -7,11 +7,11 @@
 
 #include <memory>
 
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
 // Used to retrieve some power related metrics.
 class PowerDetailsProvider {
  public:
-  static constexpr double kInvalidScreenBrightness = -1.0;
-
   // Creates a platform specific PowerDetailsProvider.
   static std::unique_ptr<PowerDetailsProvider> Create();
 
@@ -20,9 +20,9 @@
   PowerDetailsProvider(const PowerDetailsProvider& other) = delete;
   PowerDetailsProvider& operator=(const PowerDetailsProvider& other) = delete;
 
-  // Returns the brightness of the main screen when available,
-  // |kInvalidScreenBrightness| otherwise.
-  virtual double GetMainScreenBrightnessLevel() = 0;
+  // Returns the brightness of the main screen when available, |nullopt|
+  // otherwise.
+  virtual absl::optional<double> GetMainScreenBrightnessLevel() = 0;
 
  protected:
   PowerDetailsProvider() = default;
diff --git a/chrome/browser/metrics/power/power_details_provider_mac.mm b/chrome/browser/metrics/power/power_details_provider_mac.mm
index 548ea1b..3e24ed9 100644
--- a/chrome/browser/metrics/power/power_details_provider_mac.mm
+++ b/chrome/browser/metrics/power/power_details_provider_mac.mm
@@ -18,17 +18,17 @@
   PowerDetailsProviderMac& operator=(const PowerDetailsProviderMac& rhs) =
       delete;
 
-  double GetMainScreenBrightnessLevel() override {
+  absl::optional<double> GetMainScreenBrightnessLevel() override {
     static const CFStringRef kDisplayBrightness =
         CFSTR(kIODisplayBrightnessKey);
     if (service_) {
-      float brightness = kInvalidScreenBrightness;
+      float brightness = 0;
       if (IODisplayGetFloatParameter(service_, kNilOptions, kDisplayBrightness,
                                      &brightness) == kIOReturnSuccess) {
-        return brightness;
+        return static_cast<double>(brightness);
       }
     }
-    return kInvalidScreenBrightness;
+    return absl::nullopt;
   }
 
  private:
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.cc b/chrome/browser/metrics/power/power_metrics_reporter.cc
index ddfccf7..164093e 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter.cc
+++ b/chrome/browser/metrics/power/power_metrics_reporter.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/metrics/power/power_metrics_reporter.h"
+
 #include <vector>
 
 #include "base/bind.h"
@@ -28,7 +29,7 @@
 constexpr const char* kBatterySamplingDelayHistogramName =
     "Power.BatterySamplingDelay";
 constexpr const char* kMainScreenBrightnessHistogramName =
-    "Power.MainScreenBrightness";
+    "Power.MainScreenBrightness2";
 constexpr const char* kMainScreenBrightnessAvailableHistogramName =
     "Power.MainScreenBrightnessAvailable";
 
@@ -197,8 +198,28 @@
   UsageScenarioDataStore::IntervalData interval_data =
       data_store_->ResetIntervalData();
 
+  absl::optional<int64_t> main_screen_brightness;
+  if (power_details_provider_.get()) {
+    absl::optional<double> brightness =
+        power_details_provider_->GetMainScreenBrightnessLevel();
+    if (brightness.has_value()) {
+      // Report the percentage as an integer as UMA doesn't allow reporting
+      // reals.
+      main_screen_brightness = brightness.value() * 100;
+      // The brightness value reported by the system sometimes exceeds 100%,
+      // allow values up to 150 to understand this better.
+      // An histogram with 50 buckets, a minimum of 1 and a maximum of 150 will
+      // have 43 buckets in the [1, 100] range and 7 in the 100+ range.
+      base::UmaHistogramCustomCounts(kMainScreenBrightnessHistogramName,
+                                     main_screen_brightness.value(), 1, 150,
+                                     50);
+    }
+  }
+  base::UmaHistogramBoolean(kMainScreenBrightnessAvailableHistogramName,
+                            main_screen_brightness.has_value());
+
   ReportUKMs(interval_data, metrics, interval_duration, discharge_mode,
-             discharge_rate_during_interval);
+             discharge_rate_during_interval, main_screen_brightness);
 
   std::vector<const char*> suffixes = GetSuffixes(interval_data);
   ReportCPUHistograms(interval_data, metrics, suffixes);
@@ -213,22 +234,6 @@
   ReportBatteryHistograms(interval_data, sampling_interval, interval_duration,
                           discharge_mode, discharge_rate_during_interval,
                           suffixes);
-
-  bool brightness_read_successfully = false;
-  if (power_details_provider_.get()) {
-    auto brightness = power_details_provider_->GetMainScreenBrightnessLevel();
-    if (brightness != PowerDetailsProvider::kInvalidScreenBrightness) {
-      // Report the percentage as an integer as UMA doesn't allow reporting
-      // reals.
-      int brightness_int = brightness * 100;
-      DCHECK_GE(100, brightness_int);
-      brightness_read_successfully = true;
-      base::UmaHistogramPercentage(kMainScreenBrightnessHistogramName,
-                                   brightness_int);
-    }
-  }
-  base::UmaHistogramBoolean(kMainScreenBrightnessAvailableHistogramName,
-                            brightness_read_successfully);
 }
 
 // static
@@ -248,7 +253,8 @@
     const performance_monitor::ProcessMonitor::Metrics& metrics,
     base::TimeDelta interval_duration,
     BatteryDischargeMode discharge_mode,
-    absl::optional<int64_t> discharge_rate_during_interval) const {
+    absl::optional<int64_t> discharge_rate_during_interval,
+    absl::optional<int64_t> main_screen_brightness) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(data_store_.MaybeValid());
 
@@ -315,6 +321,11 @@
       GetBucketForSample(interval_data.time_playing_audio));
   builder.SetOriginVisibilityTimeSeconds(
       GetBucketForSample(interval_data.longest_visible_origin_duration));
+  if (main_screen_brightness.has_value()) {
+    // The data should be reported with a 20% granularity.
+    builder.SetMainScreenBrightnessPercent(
+        ukm::GetLinearBucketMin(main_screen_brightness.value(), 20));
+  }
 
   builder.Record(ukm_recorder);
 }
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.h b/chrome/browser/metrics/power/power_metrics_reporter.h
index f850fd18..c9e282d 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter.h
+++ b/chrome/browser/metrics/power/power_metrics_reporter.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_METRICS_POWER_POWER_METRICS_REPORTER_H_
 
 #include <stdint.h>
-
 #include <utility>
 
 #include "base/memory/weak_ptr.h"
@@ -105,7 +104,8 @@
                   const performance_monitor::ProcessMonitor::Metrics& metrics,
                   base::TimeDelta interval_duration,
                   BatteryDischargeMode discharge_mode,
-                  absl::optional<int64_t> discharge_rate_during_interval) const;
+                  absl::optional<int64_t> discharge_rate_during_interval,
+                  absl::optional<int64_t> main_screen_brightness) const;
 
   void ReportUKMsAndHistograms(
       const performance_monitor::ProcessMonitor::Metrics& metrics,
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
index 8239ae0..d0cff7c 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
+++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -28,7 +28,7 @@
     "Power.BatteryDischargeMode";
 constexpr const char* kZeroWindowSuffix = ".ZeroWindow";
 constexpr const char* kMainScreenBrightnessHistogramName =
-    "Power.MainScreenBrightness";
+    "Power.MainScreenBrightness2";
 constexpr const char* kMainScreenBrightnessAvailableHistogramName =
     "Power.MainScreenBrightnessAvailable";
 
@@ -111,6 +111,28 @@
   IntervalData fake_data_;
 };
 
+class TestPowerDetailsProvider : public PowerDetailsProvider {
+ public:
+  TestPowerDetailsProvider() = default;
+  explicit TestPowerDetailsProvider(double return_value)
+      : brightness_to_return_(return_value) {}
+  TestPowerDetailsProvider(const TestPowerDetailsProvider& rhs) = delete;
+  TestPowerDetailsProvider& operator=(const TestPowerDetailsProvider& rhs) =
+      delete;
+  ~TestPowerDetailsProvider() override = default;
+
+  absl::optional<double> GetMainScreenBrightnessLevel() override {
+    return brightness_to_return_;
+  }
+
+  void set_brightness_to_return(absl::optional<double> brightness_to_return) {
+    brightness_to_return_ = brightness_to_return;
+  }
+
+ private:
+  absl::optional<double> brightness_to_return_;
+};
+
 // This doesn't use the typical {class being tested}Test name pattern because
 // there's already a PowerMetricsReporterTest class in the chromeos namespace
 // and this conflicts with it.
@@ -133,6 +155,8 @@
     base::RunLoop run_loop;
     power_metrics_reporter_ = std::make_unique<PowerMetricsReporter>(
         data_store_.AsWeakPtr(), std::move(battery_provider));
+    power_metrics_reporter_->set_power_details_provider_for_testing(
+        std::make_unique<TestPowerDetailsProvider>());
     power_metrics_reporter_->OnFirstSampleForTesting(run_loop.QuitClosure());
     run_loop.Run();
   }
@@ -288,6 +312,9 @@
       entries[0], UkmEntry::kOriginVisibilityTimeSecondsName,
       PowerMetricsReporter::GetBucketForSampleForTesting(
           fake_interval_data.longest_visible_origin_duration));
+  EXPECT_EQ(nullptr,
+            test_ukm_recorder_.GetEntryMetric(
+                entries[0], UkmEntry::kMainScreenBrightnessPercentName));
 
   histogram_tester_.ExpectUniqueSample(kBatteryDischargeRateHistogramName, 2500,
                                        1);
@@ -668,29 +695,26 @@
           kExpectedMetricsCollectionInterval * 2));
 }
 
-namespace {
+TEST_F(PowerMetricsReporterUnitTest, UKMBrightnessLevel) {
+  const double kFakeBrightnessLevel = 0.64;
+  power_metrics_reporter_->set_power_details_provider_for_testing(
+      std::make_unique<TestPowerDetailsProvider>(kFakeBrightnessLevel));
+  task_environment_.FastForwardBy(kExpectedMetricsCollectionInterval);
+  battery_states_.push(BatteryLevelProvider::BatteryState{
+      0, 0, 1.0, false, base::TimeTicks::Now()});
 
-class TestPowerDetailsProvider : public PowerDetailsProvider {
- public:
-  TestPowerDetailsProvider() = default;
-  TestPowerDetailsProvider(const TestPowerDetailsProvider& rhs) = delete;
-  TestPowerDetailsProvider& operator=(const TestPowerDetailsProvider& rhs) =
-      delete;
-  ~TestPowerDetailsProvider() override = default;
+  UsageScenarioDataStore::IntervalData fake_interval_data;
+  fake_interval_data.source_id_for_longest_visible_origin =
+      ukm::ConvertToSourceId(42, ukm::SourceIdType::NAVIGATION_ID);
+  data_store_.SetIntervalDataToReturn(fake_interval_data);
+  WaitForNextSample({});
 
-  double GetMainScreenBrightnessLevel() override {
-    return brightness_to_return_;
-  }
-
-  void set_brightness_to_return(double brightness_to_return) {
-    brightness_to_return_ = brightness_to_return;
-  }
-
- private:
-  double brightness_to_return_ = PowerDetailsProvider::kInvalidScreenBrightness;
-};
-
-}  // namespace
+  auto entries = test_ukm_recorder_.GetEntriesByName(
+      ukm::builders::PowerUsageScenariosIntervalData::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  test_ukm_recorder_.ExpectEntryMetric(
+      entries[0], UkmEntry::kMainScreenBrightnessPercentName, 60);
+}
 
 TEST_F(PowerMetricsReporterUnitTest, MainScreenBrightnessHistogram) {
   std::unique_ptr<PowerDetailsProvider> detail_provider =
diff --git a/chrome/browser/nearby_sharing/OWNERS b/chrome/browser/nearby_sharing/OWNERS
index c3ab36d..8d033d9 100644
--- a/chrome/browser/nearby_sharing/OWNERS
+++ b/chrome/browser/nearby_sharing/OWNERS
@@ -2,4 +2,3 @@
 hansberry@chromium.org
 knollr@chromium.org
 nohle@chromium.org
-vecore@google.com
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_storage_impl.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_storage_impl.cc
index e80fec91..9ef0c61 100644
--- a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_storage_impl.cc
+++ b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_storage_impl.cc
@@ -626,8 +626,7 @@
   }
 
   public_certificate_expirations_.reserve(dict->DictSize());
-  for (const std::pair<const std::string&, const base::Value&>& pair :
-       dict->DictItems()) {
+  for (const auto pair : dict->DictItems()) {
     absl::optional<std::string> id = DecodeString(pair.first);
     absl::optional<base::Time> expiration = util::ValueToTime(pair.second);
     if (!id || !expiration)
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index 868a178..3f5d7c7 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/session/session_controller.h"
 #include "base/barrier_closure.h"
 #include "base/bind.h"
@@ -98,6 +99,12 @@
 constexpr base::TimeDelta kClearNearbyProcessUnexpectedShutdownCountDelay =
     base::TimeDelta::FromMinutes(1);
 
+bool IsBackgroundScanningFeatureEnabled() {
+  return base::FeatureList::IsEnabled(
+             features::kNearbySharingBackgroundScanning) &&
+         chromeos::features::IsBluetoothAdvertisementMonitoringEnabled();
+}
+
 std::string ReceiveSurfaceStateToString(
     NearbySharingService::ReceiveSurfaceState state) {
   switch (state) {
@@ -349,8 +356,7 @@
   observers_.Clear();
 
   StopAdvertising();
-  if (base::FeatureList::IsEnabled(
-          features::kNearbySharingBackgroundScanning)) {
+  if (IsBackgroundScanningFeatureEnabled()) {
     StopBackgroundScanning();
   }
   StopFastInitiationAdvertising();
@@ -1295,6 +1301,7 @@
     device::BluetoothDevice* device) {
   NS_LOG(VERBOSE) << __func__;
 
+  devices_attempting_to_share_.insert(device->GetAddress());
   // This shows a notification indicating that a device nearby is attempting to
   // share. When the notification is clicked it will take the user through the
   // onboarding flow if needed and then enable high visibility mode.
@@ -1305,6 +1312,10 @@
     device::BluetoothLowEnergyScanSession* scan_session,
     device::BluetoothDevice* device) {
   NS_LOG(VERBOSE) << __func__;
+  devices_attempting_to_share_.erase(device->GetAddress());
+  if (devices_attempting_to_share_.size() != 0) {
+    return;
+  }
 
   // This will just dismiss the "onboarding" notification, it does not have any
   // effect on the actual onboarding or high visibility UI.
@@ -1851,8 +1862,7 @@
 
 void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() {
   InvalidateAdvertisingState();
-  if (base::FeatureList::IsEnabled(
-          features::kNearbySharingBackgroundScanning)) {
+  if (IsBackgroundScanningFeatureEnabled()) {
     InvalidateBackgroundScanning();
   }
 }
@@ -2119,10 +2129,10 @@
     return;
   }
 
-  if (!HasAvailableConnectionMediums()) {
-    NS_LOG(VERBOSE) << __func__
-                    << ": Stopping background scanning because both bluetooth "
-                       "and wifi are disabled.";
+  if (!IsBluetoothPowered()) {
+    NS_LOG(VERBOSE)
+        << __func__
+        << ": Stopping background scanning because bluetooth is powered down.";
     StopBackgroundScanning();
     return;
   }
@@ -2192,7 +2202,8 @@
     NS_LOG(VERBOSE) << __func__ << ": Ignoring, not background scanning.";
     return;
   }
-
+  devices_attempting_to_share_.clear();
+  nearby_notification_manager_->CloseOnboarding();
   background_scan_session_.reset();
   NS_LOG(VERBOSE) << __func__ << ": Stopped background scanning.";
 }
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
index 0f3d021..3839ba5 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -15,6 +15,7 @@
 #include "base/callback_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
@@ -536,6 +537,8 @@
   // remote devices that are attempting to share.
   std::unique_ptr<device::BluetoothLowEnergyScanSession>
       background_scan_session_ = nullptr;
+  // Set of remote devices that are emitting fast init advertisements.
+  base::flat_set<std::string> devices_attempting_to_share_;
 
   int recent_nearby_process_unexpected_shutdown_count_ = 0;
   base::OneShotTimer clear_recent_nearby_process_shutdown_count_timer_;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
index e11373c..41003743 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "ash/constants/ash_features.h"
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -374,7 +375,8 @@
       : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
     scoped_feature_list_.InitWithFeatures(
         /*enabled_features=*/{features::kNearbySharing,
-                              features::kNearbySharingBackgroundScanning},
+                              features::kNearbySharingBackgroundScanning,
+                              ash::features::kBluetoothAdvertisementMonitoring},
         /*disabled_features=*/{});
     RegisterNearbySharingPrefs(prefs_.registry());
   }
diff --git a/chrome/browser/net/dns_probe_browsertest.cc b/chrome/browser/net/dns_probe_browsertest.cc
index 89184b0..a0259cd 100644
--- a/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chrome/browser/net/dns_probe_browsertest.cc
@@ -6,6 +6,7 @@
 #include <set>
 
 #include "base/bind.h"
+#include "base/enterprise_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
@@ -16,6 +17,8 @@
 #include "chrome/browser/net/dns_probe_test_util.h"
 #include "chrome/browser/net/net_error_tab_helper.h"
 #include "chrome/browser/net/secure_dns_config.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -27,9 +30,13 @@
 #include "components/embedder_support/pref_names.h"
 #include "components/error_page/common/net_error_info.h"
 #include "components/google/core/common/google_util.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/core/common/policy_map.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -384,13 +391,41 @@
 class DnsProbeCurrentSecureConfigFailingProbesTest
     : public DnsProbeBrowserTest {
  protected:
+  void SetUpInProcessBrowserTestFixture() override {
+    // Normal boilerplate to setup a MockConfigurationPolicyProvider.
+    ON_CALL(policy_provider_, IsInitializationComplete(testing::_))
+        .WillByDefault(testing::Return(true));
+    ON_CALL(policy_provider_, IsFirstPolicyLoadComplete(testing::_))
+        .WillByDefault(testing::Return(true));
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+        &policy_provider_);
+  }
+
   void SetUpOnMainThread() override {
 #if defined(OS_WIN)
     // Mark as not enterprise managed to prevent the secure DNS mode from
     // being downgraded to off.
     base::win::ScopedDomainStateForTesting scoped_domain(false);
+    EXPECT_FALSE(base::IsMachineExternallyManaged());
 #endif
 
+    // Set the mocked policy provider to act as if no policies are in use by
+    // updating to an empty PolicyMap. Done to prevent potential unintended
+    // Secure DNS downgrade.
+    policy_provider_.UpdateChromePolicy(policy::PolicyMap());
+
+    // Override parental-controls detection to not detect anything, to prevent a
+    // potential Secure DNS downgrade of off. Trigger an update to network
+    // service to ensure the override takes effect if parental controls have
+    // already been read.
+    StubResolverConfigReader* config_reader =
+        SystemNetworkContextManager::GetStubResolverConfigReader();
+    config_reader->OverrideParentalControlsForTesting(
+        /*parental_controls_override=*/false);
+    config_reader->UpdateNetworkService(/*record_metrics=*/false);
+    content::FlushNetworkServiceInstanceForTesting();
+
+    // Update prefs to enable Secure DNS in secure mode.
     PrefService* local_state = g_browser_process->local_state();
     local_state->SetString(prefs::kDnsOverHttpsMode,
                            SecureDnsConfig::kModeSecure);
@@ -405,6 +440,8 @@
           FakeHostResolver::kOneAddressResponse}});
     DnsProbeBrowserTest::SetUpOnMainThread();
   }
+
+  testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
 };
 
 // Test Fixture for tests where the DNS probes should fail to connect to a DNS
@@ -446,14 +483,8 @@
   ExpectDisplayingErrorPage("DNS_PROBE_FINISHED_BAD_CONFIG");
 }
 
-#if defined(OS_WIN)
-// https://crbug.com/1226818 Test is flaky on WIN builders.
-#define MAYBE_BadSecureConfig DISABLED_BadSecureConfig
-#else
-#define MAYBE_BadSecureConfig BadSecureConfig
-#endif
 IN_PROC_BROWSER_TEST_F(DnsProbeCurrentSecureConfigFailingProbesTest,
-                       MAYBE_BadSecureConfig) {
+                       BadSecureConfig) {
   NavigateToDnsError();
 
   EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());
diff --git a/chrome/browser/notifications/scheduler/notification_schedule_service_factory.h b/chrome/browser/notifications/scheduler/notification_schedule_service_factory.h
index d1223ad..0c8317d 100644
--- a/chrome/browser/notifications/scheduler/notification_schedule_service_factory.h
+++ b/chrome/browser/notifications/scheduler/notification_schedule_service_factory.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/no_destructor.h"
 #include "components/keyed_service/core/simple_keyed_service_factory.h"
 
 class SimpleFactoryKey;
diff --git a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
index c5ce4ba..46936121 100644
--- a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
+++ b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
@@ -513,6 +513,21 @@
                          testing::Values(true, false));
 
 IN_PROC_BROWSER_TEST_P(SecurePaymentConfirmationCreationTestWithParameter,
+                       CredentialType) {
+  ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
+  NavigateTo("a.com", "/secure_payment_confirmation.html");
+  RespondToFutureEnrollments(/*confirm=*/true);
+
+  EXPECT_EQ(
+      base::FeatureList::IsEnabled(features::kSecurePaymentConfirmationAPIV2)
+          ? "PublicKeyCredential"
+          : "PaymentCredential",
+      content::EvalJs(GetActiveWebContents(),
+                      content::JsReplace("createCredentialAndReturnItsType($1)",
+                                         GetDefaultIconURL())));
+}
+
+IN_PROC_BROWSER_TEST_P(SecurePaymentConfirmationCreationTestWithParameter,
                        CreatePaymentCredential) {
   ReplaceFidoDiscoveryFactory(/*should_succeed=*/true);
   NavigateTo("a.com", "/secure_payment_confirmation.html");
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index fd20087..6bce467 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1028,6 +1028,12 @@
   RunTestsInJsModule("viewer_properties_dialog_test.js", "document_info.pdf");
 }
 
+IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, PostMessageProxy) {
+  // Although this test file does not require a PDF to be loaded, loading the
+  // elements without loading a PDF is difficult.
+  RunTestsInJsModule("post_message_proxy_test.js", "test.pdf");
+}
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Printing) {
   RunTestsInJsModule("printing_icon_test.js", "test.pdf");
diff --git a/chrome/browser/platform_keys/extension_key_permissions_service.cc b/chrome/browser/platform_keys/extension_key_permissions_service.cc
index 50a5ac3..094f2d5 100644
--- a/chrome/browser/platform_keys/extension_key_permissions_service.cc
+++ b/chrome/browser/platform_keys/extension_key_permissions_service.cc
@@ -397,7 +397,7 @@
   if (!key_permissions_service_map)
     return permissions;
 
-  for (const auto& item : key_permissions_service_map->DictItems()) {
+  for (const auto item : key_permissions_service_map->DictItems()) {
     const auto& app_id = item.first;
     const auto& key_permission = item.second;
     const base::DictionaryValue* key_permissions_service_for_app = nullptr;
diff --git a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
index 3e8342c..cb2fd5a8b 100644
--- a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
@@ -12,8 +12,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
@@ -21,6 +20,7 @@
 #include "components/policy/core/common/policy_switches.h"
 #include "components/policy/core/common/policy_test_utils.h"
 #include "components/policy/proto/device_management_backend.pb.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_test.h"
 #include "net/base/net_errors.h"
@@ -143,7 +143,7 @@
 
 // Tests the cloud policy stack using a URLRequestJobFactory::ProtocolHandler
 // to intercept requests and produce canned responses.
-class CloudPolicyManagerTest : public InProcessBrowserTest {
+class CloudPolicyManagerTest : public PlatformBrowserTest {
  protected:
   CloudPolicyManagerTest() {}
   ~CloudPolicyManagerTest() override {}
@@ -159,6 +159,8 @@
   }
 
   void SetUpOnMainThread() override {
+    PlatformBrowserTest::SetUpOnMainThread();
+
     ASSERT_TRUE(PolicyServiceIsEmpty(g_browser_process->policy_service()))
         << "Pre-existing policies in this machine will make this test fail.";
 
@@ -175,10 +177,9 @@
 #else
     // Mock a signed-in user. This is used by the UserCloudPolicyStore to pass
     // the username to the UserCloudPolicyValidator.
-    auto* identity_manager =
-        IdentityManagerFactory::GetForProfile(browser()->profile());
-    signin::SetPrimaryAccount(identity_manager, "user@example.com",
-                              signin::ConsentLevel::kSync);
+    identity_test_env_ = std::make_unique<signin::IdentityTestEnvironment>();
+    identity_test_env_->MakePrimaryAccountAvailable(
+        "user@example.com", signin::ConsentLevel::kSync);
 
     ASSERT_TRUE(policy_manager());
     policy_manager()->Connect(
@@ -192,15 +193,17 @@
   void TearDownOnMainThread() override {
     // Verify that all the expected requests were handled.
     EXPECT_EQ(0, test_url_loader_factory_->NumPending());
+    identity_test_env_.reset();
   }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   UserCloudPolicyManagerChromeOS* policy_manager() {
-    return browser()->profile()->GetUserCloudPolicyManagerChromeOS();
+    return chrome_test_utils::GetProfile(this)
+        ->GetUserCloudPolicyManagerChromeOS();
   }
 #else
   UserCloudPolicyManager* policy_manager() {
-    return browser()->profile()->GetUserCloudPolicyManager();
+    return chrome_test_utils::GetProfile(this)->GetUserCloudPolicyManager();
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
@@ -237,6 +240,7 @@
     policy_manager()->core()->client()->RemoveObserver(&observer);
   }
 
+  std::unique_ptr<signin::IdentityTestEnvironment> identity_test_env_;
   std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory_;
 };
 
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc
index b3d7233..630888d 100644
--- a/chrome/browser/policy/extension_policy_browsertest.cc
+++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -1444,10 +1444,9 @@
   void SetUpInProcessBrowserTestFixture() override {
     ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
 
-    EXPECT_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
-    EXPECT_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
   }
 
@@ -1489,7 +1488,7 @@
   }
 
  private:
-  MockConfigurationPolicyProvider provider_;
+  testing::NiceMock<MockConfigurationPolicyProvider> provider_;
 };
 
 // Extension without update_url in manifest gets updated through update_url in
diff --git a/chrome/browser/policy/policy_network_browsertest.cc b/chrome/browser/policy/policy_network_browsertest.cc
index 2468c32..efec0c6 100644
--- a/chrome/browser/policy/policy_network_browsertest.cc
+++ b/chrome/browser/policy/policy_network_browsertest.cc
@@ -148,10 +148,9 @@
   void SetUpInProcessBrowserTestFixture() override {
     QuicTestBase::SetUpInProcessBrowserTestFixture();
     base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableQuic);
-    ON_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillByDefault(testing::Return(true));
-    ON_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillByDefault(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
 
     BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
     PolicyMap values;
@@ -168,7 +167,7 @@
   }
 
  private:
-  MockConfigurationPolicyProvider provider_;
+  testing::NiceMock<MockConfigurationPolicyProvider> provider_;
   DISALLOW_COPY_AND_ASSIGN(QuicAllowedPolicyTestBase);
 };
 
@@ -291,7 +290,9 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(QuicAllowedPolicyIsTrue, QuicAllowedForProfile) {
+// TODO(crbug.com/1228869): Flaky on multiple platforms
+IN_PROC_BROWSER_TEST_F(QuicAllowedPolicyIsTrue,
+                       DISABLED_QuicAllowedForProfile) {
   EXPECT_TRUE(IsQuicEnabled(browser()->profile()));
 
   // If using the network service, crash the service, and make sure QUIC is
diff --git a/chrome/browser/policy/policy_prefs_browsertest.cc b/chrome/browser/policy/policy_prefs_browsertest.cc
index 0c1bea6..e1549d6 100644
--- a/chrome/browser/policy/policy_prefs_browsertest.cc
+++ b/chrome/browser/policy/policy_prefs_browsertest.cc
@@ -72,10 +72,9 @@
 
  protected:
   void SetUpInProcessBrowserTestFixture() override {
-    EXPECT_CALL(*GetMockPolicyProvider(), IsInitializationComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
-    EXPECT_CALL(*GetMockPolicyProvider(), IsFirstPolicyLoadComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
+    GetMockPolicyProvider()->SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     BrowserPolicyConnector::SetPolicyProviderForTesting(
         GetMockPolicyProvider());
   }
@@ -96,7 +95,9 @@
     // On Desktop, removal of observers from those lists is triggered by the
     // destructors of the classes above, but those same destructors are never
     // invoked on Android.
-    static base::NoDestructor<MockConfigurationPolicyProvider> provider;
+    static base::NoDestructor<
+        testing::NiceMock<MockConfigurationPolicyProvider>>
+        provider;
     return provider.get();
 #else
     // On non-Android platforms, the mock provider cleanup will be triggered
@@ -107,7 +108,7 @@
   }
 
 #if !defined(OS_ANDROID)
-  MockConfigurationPolicyProvider provider_;
+  testing::NiceMock<MockConfigurationPolicyProvider> provider_;
 #endif  // !defined(OS_ANDROID)
 };
 
diff --git a/chrome/browser/policy/policy_startup_browsertest.cc b/chrome/browser/policy/policy_startup_browsertest.cc
index f373d94d..61f5e37 100644
--- a/chrome/browser/policy/policy_startup_browsertest.cc
+++ b/chrome/browser/policy/policy_startup_browsertest.cc
@@ -26,10 +26,9 @@
   void SetUpInProcessBrowserTestFixture() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kMakeDefaultBrowser);
-    ON_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillByDefault(testing::Return(true));
-    ON_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillByDefault(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
 
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 
diff --git a/chrome/browser/policy/policy_test_utils.cc b/chrome/browser/policy/policy_test_utils.cc
index eb5b6ffb..f1060c4 100644
--- a/chrome/browser/policy/policy_test_utils.cc
+++ b/chrome/browser/policy/policy_test_utils.cc
@@ -101,10 +101,8 @@
 
 void PolicyTest::SetUpInProcessBrowserTestFixture() {
   base::CommandLine::ForCurrentProcess()->AppendSwitch("noerrdialogs");
-  EXPECT_CALL(provider_, IsInitializationComplete(_))
-      .WillRepeatedly(Return(true));
-  EXPECT_CALL(provider_, IsFirstPolicyLoadComplete(_))
-      .WillRepeatedly(Return(true));
+  provider_.SetDefaultReturns(true /* is_initialization_complete_return */,
+                              true /* is_first_policy_load_complete_return */);
   BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 }
 
diff --git a/chrome/browser/policy/policy_test_utils.h b/chrome/browser/policy/policy_test_utils.h
index c498f34..e5b60665 100644
--- a/chrome/browser/policy/policy_test_utils.h
+++ b/chrome/browser/policy/policy_test_utils.h
@@ -113,7 +113,7 @@
 
   void FlushBlacklistPolicy();
 
-  MockConfigurationPolicyProvider provider_;
+  testing::NiceMock<MockConfigurationPolicyProvider> provider_;
 };
 
 }  // namespace policy
diff --git a/chrome/browser/policy/profile_policy_connector_unittest.cc b/chrome/browser/policy/profile_policy_connector_unittest.cc
index c7efc1cf..b112376 100644
--- a/chrome/browser/policy/profile_policy_connector_unittest.cc
+++ b/chrome/browser/policy/profile_policy_connector_unittest.cc
@@ -224,11 +224,10 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 TEST_F(ProfilePolicyConnectorTest, IsProfilePolicy) {
-  MockConfigurationPolicyProvider mock_platform_provider;
-  EXPECT_CALL(mock_platform_provider, IsInitializationComplete(_))
-      .WillRepeatedly(Return(true));
-  EXPECT_CALL(mock_platform_provider, IsFirstPolicyLoadComplete(_))
-      .WillRepeatedly(Return(true));
+  testing::NiceMock<MockConfigurationPolicyProvider> mock_platform_provider;
+  mock_platform_provider.SetDefaultReturns(
+      true /* is_initialization_complete_return */,
+      true /* is_first_policy_load_complete_return */);
 
   ProfilePolicyConnector connector;
   connector.SetPlatformPolicyProviderForTesting(&mock_platform_provider);
diff --git a/chrome/browser/policy/site_isolation_policy_browsertest.cc b/chrome/browser/policy/site_isolation_policy_browsertest.cc
index 596f270..5ef0689f 100644
--- a/chrome/browser/policy/site_isolation_policy_browsertest.cc
+++ b/chrome/browser/policy/site_isolation_policy_browsertest.cc
@@ -77,10 +77,9 @@
     // to the renderer via a command-line. Setting the policy in the test
     // itself or in SetUpOnMainThread works for update-able policies, but
     // is too late for this one.
-    ON_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillByDefault(testing::Return(true));
-    ON_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillByDefault(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 
     policy::PolicyMap values;
@@ -115,10 +114,9 @@
     // to the renderer via a command-line. Setting the policy in the test
     // itself or in SetUpOnMainThread works for update-able policies, but
     // is too late for this one.
-    ON_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillByDefault(testing::Return(true));
-    ON_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillByDefault(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
 
     policy::PolicyMap values;
diff --git a/chrome/browser/policy/test/audio_process_high_priority_enabled_browsertest.cc b/chrome/browser/policy/test/audio_process_high_priority_enabled_browsertest.cc
index 57244cc..b85057bf 100644
--- a/chrome/browser/policy/test/audio_process_high_priority_enabled_browsertest.cc
+++ b/chrome/browser/policy/test/audio_process_high_priority_enabled_browsertest.cc
@@ -27,8 +27,9 @@
  public:
   // InProcessBrowserTest implementation:
   void SetUp() override {
-    EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
+    policy_provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     policy::PolicyMap values;
     if (GetParam().has_value()) {
       values.Set(policy::key::kAudioProcessHighPriorityEnabled,
@@ -44,7 +45,7 @@
   }
 
  private:
-  policy::MockConfigurationPolicyProvider policy_provider_;
+  testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
 };
 
 IN_PROC_BROWSER_TEST_P(AudioProcessHighPriorityEnabledTest, IsRespected) {
diff --git a/chrome/browser/policy/test/audio_sandbox_enabled_browsertest.cc b/chrome/browser/policy/test/audio_sandbox_enabled_browsertest.cc
index ef6fd0c..469e3ad 100644
--- a/chrome/browser/policy/test/audio_sandbox_enabled_browsertest.cc
+++ b/chrome/browser/policy/test/audio_sandbox_enabled_browsertest.cc
@@ -26,8 +26,9 @@
  public:
   // InProcessBrowserTest implementation:
   void SetUp() override {
-    EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
-        .WillRepeatedly(testing::Return(true));
+    policy_provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     policy::PolicyMap values;
     if (GetParam().has_value()) {
       values.Set(policy::key::kAudioSandboxEnabled,
@@ -43,7 +44,7 @@
   }
 
  private:
-  policy::MockConfigurationPolicyProvider policy_provider_;
+  testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
 };
 
 IN_PROC_BROWSER_TEST_P(AudioSandboxEnabledTest, IsRespected) {
diff --git a/chrome/browser/policy/test/restore_on_startup_policy_browsertest.cc b/chrome/browser/policy/test/restore_on_startup_policy_browsertest.cc
index 4e22287..e86ca5b 100644
--- a/chrome/browser/policy/test/restore_on_startup_policy_browsertest.cc
+++ b/chrome/browser/policy/test/restore_on_startup_policy_browsertest.cc
@@ -57,14 +57,6 @@
   RestoreOnStartupPolicyTest() = default;
   ~RestoreOnStartupPolicyTest() override = default;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    // TODO(nkostylev): Investigate if we can remove this switch.
-    command_line->AppendSwitch(switches::kCreateBrowserOnStartupForTests);
-    PolicyTest::SetUpCommandLine(command_line);
-  }
-#endif
-
   void SetUpInProcessBrowserTestFixture() override {
     PolicyTest::SetUpInProcessBrowserTestFixture();
     // Set early policies now, before the browser is created.
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 03f79ce6..43db9e6 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -636,6 +636,11 @@
 const char kSuggestionsBlocklist[] = "suggestions.blacklist";
 const char kSuggestionsData[] = "suggestions.data";
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+// Deprecated 07/2021.
+const char kExtensionCheckupOnStartup[] = "extensions.checkup_on_startup";
+#endif
+
 // Register local state used only for migration (clearing or moving to a new
 // key).
 void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -816,6 +821,10 @@
 
   registry->RegisterStringPref(kSuggestionsBlocklist, std::string());
   registry->RegisterStringPref(kSuggestionsData, std::string());
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  registry->RegisterBooleanPref(kExtensionCheckupOnStartup, false);
+#endif
 }
 
 }  // namespace
@@ -1600,6 +1609,11 @@
   profile_prefs->ClearPref(kSuggestionsBlocklist);
   profile_prefs->ClearPref(kSuggestionsData);
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // Added 2021/07.
+  profile_prefs->ClearPref(kExtensionCheckupOnStartup);
+#endif
+
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
 }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 45c85cd0..710d933 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1103,7 +1103,7 @@
         GetUmaValueMax(UmaEnumIdLookupType::ContextSpecificEnumId));
   } else if ((!params_.selection_text.empty() ||
               params_.opened_from_highlight) &&
-              params_.media_type == ContextMenuDataMediaType::kNone) {
+             params_.media_type == ContextMenuDataMediaType::kNone) {
     // Probably just text.
     UMA_HISTOGRAM_EXACT_LINEAR(
         "ContextMenu.SelectedOptionDesktop.SelectedText", enum_id,
@@ -2041,8 +2041,16 @@
 }
 
 void RenderViewContextMenu::AppendLensRegionSearchItem() {
+  int resource_id = IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH;
+  if (lens::features::kRegionSearchUseMenuItemAltText1.Get()) {
+    resource_id = IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT1;
+  } else if (lens::features::kRegionSearchUseMenuItemAltText2.Get()) {
+    resource_id = IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT2;
+  } else if (lens::features::kRegionSearchUseMenuItemAltText3.Get()) {
+    resource_id = IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT3;
+  }
   menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH,
-                                  IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH);
+                                  resource_id);
 }
 
 // Menu delegate functions -----------------------------------------------------
@@ -3347,7 +3355,8 @@
   translate::TranslateManager* manager =
       chrome_translate_client->GetTranslateManager();
   DCHECK(manager);
-  manager->InitiateManualTranslation(true, true);
+  manager->ShowTranslateUI(/*auto_translate=*/true,
+                           /*triggered_from_menu=*/true);
 }
 
 void RenderViewContextMenu::ExecLanguageSettings(int event_flags) {
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
index c17e2d85..ab08121 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -460,12 +460,10 @@
 
   // Allow |contents1_| to display notifications, this should cause the
   // |used_in_bg| bit to change to true.
-
-  const GURL kTestURL("https://foo.com/");
-  NotificationPermissionContext::UpdatePermission(profile(), kTestURL,
-                                                  CONTENT_SETTING_ALLOW);
-  content::WebContentsTester::For(contents1_.get())
-      ->SetLastCommittedURL(kTestURL);
+  NotificationPermissionContext::UpdatePermission(
+      profile(),
+      contents1_.get()->GetMainFrame()->GetLastCommittedOrigin().GetURL(),
+      CONTENT_SETTING_ALLOW);
 
   // Adding/Removing the tab for scoring will cause the callback to be called a
   // few times, ignore this.
@@ -479,9 +477,6 @@
   iter = policy_->tab_data_.find(contents1_.get());
   EXPECT_TRUE(iter != policy_->tab_data_.end());
   EXPECT_TRUE(iter->second->UsedInBg());
-
-  NotificationPermissionContext::UpdatePermission(profile(), kTestURL,
-                                                  CONTENT_SETTING_DEFAULT);
 }
 
 TEST_F(SessionRestorePolicyTest, MultipleAllTabsDoneCallbacks) {
@@ -635,20 +630,20 @@
 
   base::RunLoop run_loop;
   performance_manager::PerformanceManager::CallOnGraph(
-      FROM_HERE,
-      base::BindOnce(
-          [](base::WeakPtr<performance_manager::PageNode> page_node,
-             base::OnceClosure closure) {
-            EXPECT_TRUE(page_node);
-            auto* impl = performance_manager::GetSiteDataImplForPageNode(
-                page_node.get());
-            EXPECT_TRUE(impl);
-            impl->NotifyUpdatesTitleInBackground();
-            std::move(closure).Run();
-          },
-          performance_manager::PerformanceManager::
-              GetPrimaryPageNodeForWebContents(contents1_.get()),
-          run_loop.QuitClosure()));
+      FROM_HERE, base::BindOnce(
+                     [](base::WeakPtr<performance_manager::PageNode> page_node,
+                        base::OnceClosure closure) {
+                       EXPECT_TRUE(page_node);
+                       auto* impl =
+                           performance_manager::GetSiteDataImplForPageNode(
+                               page_node.get());
+                       EXPECT_TRUE(impl);
+                       impl->NotifyUpdatesTitleInBackground();
+                       std::move(closure).Run();
+                     },
+                     performance_manager::PerformanceManager::
+                         GetPrimaryPageNodeForWebContents(contents1_.get()),
+                     run_loop.QuitClosure()));
   run_loop.Run();
 
   // Adding/Removing the tab for scoring will cause the callback to be called a
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.h b/chrome/browser/resource_coordinator/tab_manager_features.h
index 2cb377d..9f07a8a 100644
--- a/chrome/browser/resource_coordinator/tab_manager_features.h
+++ b/chrome/browser/resource_coordinator/tab_manager_features.h
@@ -7,7 +7,6 @@
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
-#include "base/no_destructor.h"
 #include "base/system/sys_info.h"
 #include "base/time/time.h"
 
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index fd7c2fda..7e391ef 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -118,7 +118,6 @@
         "commander:closure_compile",
         "discards:closure_compile",
         "download_internals:closure_compile",
-        "download_shelf:closure_compile",
         "federated_learning:closure_compile",
         "feedback_webui/js:closure_compile",
         "gaia_auth_host:closure_compile",
diff --git a/chrome/browser/resources/bookmarks/command_manager.ts b/chrome/browser/resources/bookmarks/command_manager.ts
index ae44167..52737b6 100644
--- a/chrome/browser/resources/bookmarks/command_manager.ts
+++ b/chrome/browser/resources/bookmarks/command_manager.ts
@@ -43,15 +43,15 @@
 
 const BookmarksCommandManagerElementBase =
     mixinBehaviors([StoreClient], PolymerElement) as {
-  new (): PolymerElement & BookmarksStoreClientInterface &
-          StoreObserver<BookmarksPageState>
-}
+      new (): PolymerElement & BookmarksStoreClientInterface &
+      StoreObserver<BookmarksPageState>
+    };
 
 export interface BookmarksCommandManagerElement {
   $: {
-    dropdown: CrLazyRenderElement,
-    editDialog: CrLazyRenderElement,
-    openDialog: CrLazyRenderElement,
+    dropdown: CrLazyRenderElement<CrActionMenuElement>,
+    editDialog: CrLazyRenderElement<BookmarksEditDialogElement>,
+    openDialog: CrLazyRenderElement<CrDialogElement>,
   }
 }
 
@@ -177,7 +177,7 @@
     this.menuSource_ = source;
     this.menuIds_ = items || this.getState().selection.items;
 
-    const dropdown = (this.$.dropdown.get()) as CrActionMenuElement;
+    const dropdown = this.$.dropdown.get();
     // Ensure that the menu is fully rendered before trying to position it.
     flush();
     DialogFocusManager.getInstance().showDialog(
@@ -194,7 +194,7 @@
     this.menuSource_ = source;
     this.menuIds_ = this.getState().selection.items;
 
-    const dropdown = this.$.dropdown.get() as CrActionMenuElement;
+    const dropdown = this.$.dropdown.get();
     // Ensure that the menu is fully rendered before trying to position it.
     flush();
     DialogFocusManager.getInstance().showDialog(
@@ -206,7 +206,7 @@
   closeCommandMenu() {
     this.menuIds_ = new Set();
     this.menuSource_ = MenuSource.NONE;
-    (this.$.dropdown.get() as CrActionMenuElement).close();
+    this.$.dropdown.get().close();
   }
 
   ////////////////////////////////////////////////////////////////////////////
@@ -322,8 +322,7 @@
     switch (command) {
       case Command.EDIT: {
         const id = Array.from(itemIds)[0]!;
-        (this.$.editDialog.get() as BookmarksEditDialogElement)
-            .showEditDialog(state.nodes[id]!);
+        this.$.editDialog.get().showEditDialog(state.nodes[id]!);
         break;
       }
       case Command.COPY_URL:
@@ -424,12 +423,12 @@
         getToastManager().show(loadTimeData.getString('toastFolderSorted'));
         break;
       case Command.ADD_BOOKMARK:
-        (this.$.editDialog.get() as BookmarksEditDialogElement)
-            .showAddDialog(false, assert(state.selectedFolder));
+        this.$.editDialog.get().showAddDialog(
+            false, assert(state.selectedFolder));
         break;
       case Command.ADD_FOLDER:
-        (this.$.editDialog.get() as BookmarksEditDialogElement)
-            .showAddDialog(true, assert(state.selectedFolder));
+        this.$.editDialog.get().showAddDialog(
+            true, assert(state.selectedFolder));
         break;
       case Command.IMPORT:
         chrome.bookmarks.import();
@@ -536,8 +535,7 @@
     dialog.querySelector('[slot=body]')!.textContent =
         loadTimeData.getStringF('openDialogBody', urls.length);
 
-    DialogFocusManager.getInstance().showDialog(
-        this.$.openDialog.get() as CrDialogElement);
+    DialogFocusManager.getInstance().showDialog(this.$.openDialog.get());
   }
 
   /**
@@ -841,13 +839,13 @@
   }
 
   private onOpenCancelTap_() {
-    (this.$.openDialog.get() as CrDialogElement).cancel();
+    this.$.openDialog.get().cancel();
   }
 
   private onOpenConfirmTap_() {
     const confirmOpenCallback = assert(this.confirmOpenCallback_!);
     confirmOpenCallback();
-    (this.$.openDialog.get() as CrDialogElement).close();
+    this.$.openDialog.get().close();
   }
 
   static getInstance(): BookmarksCommandManagerElement {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
index fdfd178..915bf3a7 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
@@ -39,6 +39,9 @@
 
     /** @private {boolean} */
     this.navigationControlsEnabled_ = true;
+
+    /** @private {boolean} */
+    this.enhancedNetworkVoicesEnabled_ = true;
   }
 
   /**
@@ -228,7 +231,7 @@
       chrome.storage.sync.get(
           [
             'voice', 'rate', 'pitch', 'wordHighlight', 'highlightColor',
-            'backgroundShading', 'navigationControls'
+            'backgroundShading', 'navigationControls', 'enhancedNetworkVoices'
           ],
           (prefs) => {
             if (prefs['voice']) {
@@ -256,6 +259,14 @@
               chrome.storage.sync.set(
                   {'navigationControls': this.navigationControlsEnabled_});
             }
+            if (prefs['enhancedNetworkVoices'] !== undefined) {
+              this.enhancedNetworkVoicesEnabled_ =
+                  prefs['enhancedNetworkVoices'];
+            } else {
+              chrome.storage.sync.set({
+                'enhancedNetworkVoices': this.enhancedNetworkVoicesEnabled_
+              });
+            }
             if (prefs['rate'] && prefs['pitch']) {
               // Removes 'rate' and 'pitch' prefs after migrating data to global
               // TTS settings if appropriate.
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
index ae47c03..37a05a7 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
@@ -40,8 +40,22 @@
             window.speechSynthesis.onvoiceschanged = (function() {
               this.populateVoiceList_('localVoices');
             }.bind(this));
-            // TODO(crbug.com/1227589): add enhanced voice settings to prefs
-            // and sync the controls for those settings to preferences
+
+            this.syncSelectControlToPref_('localVoices', 'voice', 'voiceName');
+            this.syncCheckboxControlToPref_(
+                'naturalVoices', 'enhancedNetworkVoices', (checked) => {
+                  const voice =
+                      document.getElementById('naturalVoiceSelection');
+                  const preview =
+                      document.getElementById('naturalVoicePreview');
+                  const select = document.getElementById('naturalVoice');
+                  this.setElementVisible(voice, checked);
+                  this.setElementVisible(preview, checked);
+                  select.disabled = !checked;
+                });
+            // TODO(crbug.com/1227589): add enhanced voice and language
+            // selection to prefs and sync the controls for those settings to
+            // preferences.
           }
         });
 
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.js
index 38fcdf7..ec883943 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin_flow.js
@@ -240,7 +240,7 @@
     if (this.currentStep !== UIState.VALUE_PROP) {
       return;
     }
-    this.$.valueProp.showNextSettingZippy();
+    this.$.valueProp.showNextStep();
   },
 
   /**
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css
index f56411b..d528cc8 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css
@@ -6,10 +6,26 @@
   --oobe-adaptive-dialog-content-top-padding: 0;
 }
 
-#intro-text {
+.subtitle-text {
+  color: var(--google-grey-900);
+  font-size: 15px;
+  font-weight: 500;
+  line-height: 24px;
+}
+
+.subtitle-message-text {
   padding: 0 8px 16px 0;
 }
 
+.subtitle-message-text-minor {
+  color: var(--google-grey-900);
+  padding: 0 8px 16px 0;
+}
+
+.username-text {
+  padding-bottom: 30px;
+}
+
 #footer-text {
   padding-top: 16px;
 }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
index f739276..0fd3e36 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -29,7 +29,7 @@
       </div>
       <div slot="content" id="content-container"
           class="landscape-vertical-centered">
-        <div class="content" id="intro-text"></div>
+        <div class="content" id="subtitle-container"></div>
         <div hidden$="[[!newLayoutEnabled_]]">
           <div class="line" hidden$="[[isMinorMode_]]"></div>
         </div>
@@ -44,7 +44,7 @@
           </div>
           <div id="consents-container"></div>
         </div>
-        <div class="content" id="footer-text"></div>
+        <div class="content" id="footer-text" hidden$="[[isMinorMode_]]"></div>
       </div>
       <div slot="bottom-buttons">
         <oobe-text-button id="skip-button" on-click="onSkipTap_"
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
index 40f94332..ba5a773f8 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
@@ -296,7 +296,6 @@
     this.$['value-prop-dialog'].setAttribute(
         'aria-label', data['valuePropTitle']);
     this.$['title-text'].textContent = data['valuePropTitle'];
-    this.$['intro-text'].textContent = data['valuePropIntro'];
     this.$['user-image'].src = data['valuePropUserImage'];
     this.$['user-name'].textContent = data['valuePropIdentity'];
     this.$['next-button'].labelForAria = data['valuePropNextButton'];
@@ -314,7 +313,7 @@
   },
 
   /**
-   * Add a setting zippy with the provided data.
+   * Add subtitles and setting zippys with given data.
    */
   addSettingZippy(zippy_data) {
     if (this.settingZippyLoaded_) {
@@ -324,8 +323,10 @@
       return;
     }
 
-    // Clear `consents-container` to prevent setting zippys being added
-    // multiple times.
+    // Clear containers to prevent contents being added multiple times.
+    while (this.$['subtitle-container'].firstElementChild) {
+      this.$['subtitle-container'].firstElementChild.remove();
+    }
     while (this.$['consents-container'].firstElementChild) {
       this.$['consents-container'].firstElementChild.remove();
     }
@@ -336,6 +337,7 @@
     // first one and set `isMinorMode_` flag.
     this.isMinorMode_ = zippy_data[0][0]['isMinorMode'];
     for (var i in zippy_data) {
+      this.addSubtitle_(zippy_data[i][0], i);
       for (var j in zippy_data[i]) {
         var data = zippy_data[i][j];
         var zippy = document.createElement('setting-zippy');
@@ -354,30 +356,35 @@
 
         var title = document.createElement('div');
         title.slot = 'title';
-        title.innerHTML = this.sanitizer_.sanitizeHtml(data['title']);
+        title.innerHTML = this.sanitizer_.sanitizeHtml(data['name']);
         zippy.appendChild(title);
 
+        var content = document.createElement('div');
+        content.slot = 'content';
+
         var description = document.createElement('div');
-        description.slot = 'content';
         description.innerHTML =
             this.sanitizer_.sanitizeHtml(data['description']);
         description.innerHTML += '&ensp;';
 
         var learnMoreLink = document.createElement('a');
-        learnMoreLink.slot = 'content';
         learnMoreLink.textContent = data['popupLink'];
         learnMoreLink.setAttribute('href', 'javascript:void(0)');
         learnMoreLink.onclick = function(title, additionalInfo, focus) {
           this.lastFocusedElement = focus;
           this.showLearnMoreOverlay(title, additionalInfo);
         }.bind(this, data['title'], data['additionalInfo'], learnMoreLink);
-
         description.appendChild(learnMoreLink);
-        zippy.appendChild(description);
+        content.appendChild(description);
+
+        // TODO(https://crbug.com/1224850) Add additionalInfo in setting zippys
+        // and update content in learn more dialog.
+
+        zippy.appendChild(content);
         this.$['consents-container'].appendChild(zippy);
       }
     }
-    this.showSettingZippyForStep_(this.currentConsentStep_);
+    this.showContentForStep_(this.currentConsentStep_);
 
     this.settingZippyLoaded_ = true;
     if (this.consentStringLoaded_) {
@@ -386,6 +393,32 @@
   },
 
   /**
+   * Add a subtitle for step with given data.
+   */
+  addSubtitle_(data, step) {
+    var subtitle = document.createElement('div');
+    subtitle.setAttribute('step', step);
+    if (this.newLayoutEnabled_ && this.isMinorMode_) {
+      var title = document.createElement('div');
+      title.innerHTML = this.sanitizer_.sanitizeHtml(data['title']);
+      title.classList.add('subtitle-text');
+      subtitle.appendChild(title);
+
+      var username = document.createElement('div');
+      username.innerHTML = this.sanitizer_.sanitizeHtml(data['identity']);
+      username.classList.add('username-text');
+      subtitle.appendChild(username);
+    }
+    var message = document.createElement('div');
+    message.innerHTML = this.sanitizer_.sanitizeHtml(data['intro']);
+    message.classList.add(
+        this.isMinorMode_ ? 'subtitle-message-text-minor' :
+                            'subtitle-message-text');
+    subtitle.appendChild(message);
+    this.$['subtitle-container'].appendChild(subtitle);
+  },
+
+  /**
    * Handles event when all the page content has been loaded.
    */
   onPageLoaded() {
@@ -423,20 +456,24 @@
   },
 
   /**
-   * Update the screen to show the next setting zippy. This is called only for
-   * minor users as settings are unbundled.
+   * Update the screen to show the next settings with updated subtitle and
+   * setting zippy. This is called only for minor users as settings are
+   * unbundled.
    */
-  showNextSettingZippy() {
+  showNextStep() {
     this.currentConsentStep_ += 1;
-    this.showSettingZippyForStep_(this.currentConsentStep_);
+    this.showContentForStep_(this.currentConsentStep_);
     this.buttonsDisabled = false;
   },
 
   /**
-   * Update visibility of setting zippys for a given step.
+   * Update visibility of subtitles and setting zippys for a given step.
    * @param {number} step
    */
-  showSettingZippyForStep_(step) {
+  showContentForStep_(step) {
+    for (let subtitle of this.$['subtitle-container'].children) {
+      subtitle.hidden = subtitle.getAttribute('step') != step;
+    }
     for (let zippy of this.$['consents-container'].children) {
       zippy.hidden = zippy.getAttribute('step') != step;
     }
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
index 2749fe6..436a8a5 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -29,5 +29,7 @@
     "../../components/behaviors:multi_step_behavior",
     "../../components/behaviors:oobe_dialog_host_behavior",
     "../../components/behaviors:oobe_i18n_behavior",
+    "../../components/dialogs:oobe_adaptive_dialog",
+    "../../components/dialogs:oobe_modal_dialog",
   ]
 }
diff --git a/chrome/browser/resources/chromeos/login/screens/common/os_install.html b/chrome/browser/resources/chromeos/login/screens/common/os_install.html
index d5aed0f..45e04a1 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/os_install.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/os_install.html
@@ -15,6 +15,7 @@
 <link rel="import" href="/components/common_styles/common_styles.html">
 <link rel="import" href="/components/common_styles/oobe_dialog_host_styles.html">
 <link rel="import" href="/components/dialogs/oobe_adaptive_dialog.html">
+<link rel="import" href="/components/dialogs/oobe_modal_dialog.html">
 
 <dom-module id="os-install-element">
   <template>
@@ -30,6 +31,17 @@
       li:not(:last-child) {
         margin-bottom: 14px;
       }
+      #serviceLogsDialog {
+        --oobe-modal-dialog-content-slot-padding-bottom: 0;
+        --oobe-modal-dialog-content-slot-padding-end: 0;
+        --oobe-modal-dialog-content-slot-padding-start: 0;
+        --oobe-modal-dialog-title-slot-padding-bottom: 16px;
+        --oobe-modal-dialog-width: 512px;
+      }
+      #serviceLogsFrame {
+        padding-inline-end: 20px;
+        padding-inline-start: 20px;
+      }
     </style>
 
     <oobe-adaptive-dialog id="osInstallDialogIntro"
@@ -92,6 +104,10 @@
       <html-echo slot="subtitle" for-step="failed"
           content="[[getErrorFailedSubtitleHtml_(locale)]]">
       </html-echo>
+      <a slot="subtitle" id="serviceLogsLink" class="oobe-local-link"
+          on-click="onServiceLogsLinkClicked_" is="action-link">
+        [[i18nDynamic(locale, 'osInstallDialogErrorServiceLogsLink')]]
+      </a>
       </div>
       <div slot="content" for-step="failed"
           class="flex layout vertical center center-justified">
@@ -123,5 +139,19 @@
         </oobe-next-button>
       </div>
     </oobe-adaptive-dialog>
+
+    <oobe-modal-dialog id="serviceLogsDialog" ignore-popstate
+        on-close="focusServiceLogsLink_"
+        on-cancel="focusServiceLogsLink_">
+      <div slot="title">
+        [[i18nDynamic(locale, 'osInstallDialogServiceLogsTitle')]]
+      </div>
+      <webview slot="content" id="serviceLogsFrame" role="document"
+          allowTransparency class="focus-on-show flex oobe-tos-webview">
+      </webview>
+      <oobe-text-button id="closeServiceLogsDialog" slot="buttons" inverse
+          on-click="hideServiceLogsDialog_" text-key="oobeModalDialogClose">
+      </oobe-text-button>
+    </oobe-modal-dialog>
   </template>
 </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/screens/common/os_install.js b/chrome/browser/resources/chromeos/login/screens/common/os_install.js
index 94c99a517..23709e5 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/os_install.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/os_install.js
@@ -28,6 +28,7 @@
 
   EXTERNAL_API: [
     'showStep',
+    'setServiceLogs',
   ],
 
   UI_STEPS: UIState,
@@ -111,5 +112,60 @@
     return this.i18nAdvanced(
         'osInstallDialogErrorFailedSubtitle', {tags: ['p']});
   },
+
+  /**
+   * Shows service logs.
+   * @private
+   */
+  onServiceLogsLinkClicked_() {
+    this.$.serviceLogsDialog.showDialog();
+    this.$.closeServiceLogsDialog.focus();
+  },
+
+  /**
+   * On-click event handler for close button of the service logs dialog.
+   * @private
+   */
+  hideServiceLogsDialog_() {
+    this.$.serviceLogsDialog.hideDialog();
+    this.focusServiceLogsLink_();
+  },
+
+  /**
+   * @private
+   */
+  focusServiceLogsLink_() {
+    Polymer.RenderStatus.afterNextRender(
+        this, () => this.$.serviceLogsLink.focus());
+  },
+
+  /**
+   * @param {string} serviceLogs Logs to show as plain text.
+   */
+  setServiceLogs(serviceLogs) {
+    this.$.serviceLogsFrame.src = 'data:text/html;charset=utf-8,' +
+        encodeURIComponent('<style>' +
+                           'body {' +
+                           '  font-family: Roboto, sans-serif;' +
+                           '  color: RGBA(0,0,0,.87);' +
+                           '  font-size: 14sp;' +
+                           '  margin : 0;' +
+                           '  padding : 0;' +
+                           '  white-space: pre-wrap;' +
+                           '}' +
+                           '#logsContainer {' +
+                           '  overflow: auto;' +
+                           '  height: 99%;' +
+                           '  padding-left: 16px;' +
+                           '  padding-right: 16px;' +
+                           '}' +
+                           '#logsContainer::-webkit-scrollbar-thumb {' +
+                           '  border-radius: 10px;' +
+                           '}' +
+                           '</style>' +
+                           '<body><div id="logsContainer">' + serviceLogs +
+                           '</div>' +
+                           '</body>');
+  },
 });
 })();
diff --git a/chrome/browser/resources/download_shelf/BUILD.gn b/chrome/browser/resources/download_shelf/BUILD.gn
index 0e63e05..4f90ff9 100644
--- a/chrome/browser/resources/download_shelf/BUILD.gn
+++ b/chrome/browser/resources/download_shelf/BUILD.gn
@@ -4,24 +4,21 @@
 
 import("//chrome/browser/resources/tools/optimize_webui.gni")
 import("//chrome/common/features.gni")
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/preprocess_if_expr.gni")
 import("//tools/polymer/html_to_js.gni")
+import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
 import("//ui/webui/webui_features.gni")
 
 preprocess_folder = "preprocessed"
-preprocess_manifest = "preprocessed_manifest.json"
-preprocess_web_components_manifest = "preprocessed_gen_manifest.json"
-preprocess_mojo_manifest = "preprocessed_mojo_manifest.json"
 
 if (optimize_webui) {
   build_manifest = "build_manifest.json"
 
   optimize_webui("build") {
     host = "download-shelf.top-chrome"
-    input = rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir)
+    input = rebase_path("$target_gen_dir/tsc", root_build_dir)
     js_out_files = [ "download_shelf.rollup.js" ]
     js_module_in_files = [ "download_shelf.js" ]
     out_manifest = "$target_gen_dir/$build_manifest"
@@ -35,9 +32,7 @@
     ]
 
     deps = [
-      ":preprocess",
-      ":preprocess_mojo",
-      ":preprocess_web_components",
+      ":build_ts",
       "../../../../ui/webui/resources:preprocess",
     ]
   }
@@ -54,47 +49,34 @@
     manifest_files = [ "$target_gen_dir/$build_manifest" ]
     resource_path_rewrites = [ "download_shelf.rollup.js|download_shelf.js" ]
   } else {
-    deps = [
-      ":preprocess",
-      ":preprocess_mojo",
-      ":preprocess_web_components",
-    ]
-    manifest_files = [
-      "$target_gen_dir/$preprocess_manifest",
-      "$target_gen_dir/$preprocess_mojo_manifest",
-      "$target_gen_dir/$preprocess_web_components_manifest",
-    ]
+    deps = [ ":build_ts" ]
+    manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   }
 }
 
+copy("copy_mojo") {
+  deps = [ "//chrome/browser/ui/webui/download_shelf:mojo_bindings_webui_js" ]
+  sources = [ "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/download_shelf/download_shelf.mojom-webui.js" ]
+  outputs = [ "$target_gen_dir/$preprocess_folder/{{source_file_part}}" ]
+}
+
 preprocess_if_expr("preprocess") {
   in_folder = "./"
   out_folder = "$target_gen_dir/$preprocess_folder"
-  out_manifest = "$target_gen_dir/$preprocess_manifest"
   in_files = [
-    "download_shelf_api_proxy.js",
-    "download_shelf.js",
+    "download_shelf_api_proxy.ts",
+    "download_shelf.ts",
   ]
 }
 
-preprocess_if_expr("preprocess_mojo") {
-  deps = [ "//chrome/browser/ui/webui/download_shelf:mojo_bindings_webui_js" ]
-  in_folder =
-      "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/download_shelf/"
-  out_folder = "$target_gen_dir/$preprocess_folder"
-  out_manifest = "$target_gen_dir/$preprocess_mojo_manifest"
-  in_files = [ "download_shelf.mojom-webui.js" ]
-}
-
 preprocess_if_expr("preprocess_web_components") {
   deps = [ ":web_components" ]
   in_folder = target_gen_dir
   out_folder = "$target_gen_dir/$preprocess_folder"
-  out_manifest = "$target_gen_dir/$preprocess_web_components_manifest"
   in_files = [
-    "app.js",
-    "download_item.js",
-    "download_list.js",
+    "app.ts",
+    "download_item.ts",
+    "download_list.ts",
   ]
 }
 
@@ -115,67 +97,35 @@
   output_dir = "$root_gen_dir/chrome"
 }
 
-js_type_check("closure_compile") {
-  is_polymer3 = true
-  closure_flags = default_closure_args + mojom_js_args + [
-                    "js_module_root=" + rebase_path(".", root_build_dir),
-                    "js_module_root=" + rebase_path(
-                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/download_shelf",
-                            root_build_dir),
-                  ]
-  deps = [
-    ":app",
-    ":download_item",
-    ":download_list",
-    ":download_shelf_api_proxy",
-  ]
-}
-
-js_library("download_shelf_api_proxy") {
-  deps = [
-    "//chrome/browser/ui/webui/download_shelf:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:cr.m",
-  ]
-  externs_list = [ "$externs_path/chrome_extensions.js" ]
-}
-
-js_library("download_item") {
-  deps = [
-    ":download_shelf_api_proxy",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/chrome_extensions.js" ]
-}
-
-js_library("download_list") {
-  deps = [
-    ":download_item",
-    ":download_shelf_api_proxy",
-    "//ui/webui/resources/js:custom_element",
-  ]
-  externs_list = [ "$externs_path/metrics_private.js" ]
-}
-
-js_library("app") {
-  deps = [
-    ":download_list",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:icon.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-}
-
-js_library("download_shelf") {
-  deps = [ ":app" ]
-}
-
 html_to_js("web_components") {
   js_files = [
-    "app.js",
-    "download_item.js",
-    "download_list.js",
+    "app.ts",
+    "download_item.ts",
+    "download_list.ts",
+  ]
+}
+
+ts_library("build_ts") {
+  root_dir = "$target_gen_dir/$preprocess_folder"
+  out_dir = "$target_gen_dir/tsc"
+  tsconfig_base = "tsconfig_base.json"
+  in_files = [
+    "app.ts",
+    "download_item.ts",
+    "download_list.ts",
+    "download_shelf.mojom-webui.js",
+    "download_shelf.ts",
+    "download_shelf_api_proxy.ts",
+  ]
+  deps = [ "//ui/webui/resources:library" ]
+  definitions = [
+    "//tools/typescript/definitions/chrome_downloads.d.ts",
+    "//tools/typescript/definitions/chrome_send.d.ts",
+    "//tools/typescript/definitions/metrics_private.d.ts",
+  ]
+  extra_deps = [
+    ":copy_mojo",
+    ":preprocess",
+    ":preprocess_web_components",
   ]
 }
diff --git a/chrome/browser/resources/download_shelf/app.js b/chrome/browser/resources/download_shelf/app.ts
similarity index 85%
rename from chrome/browser/resources/download_shelf/app.js
rename to chrome/browser/resources/download_shelf/app.ts
index 81489e8..1680034 100644
--- a/chrome/browser/resources/download_shelf/app.js
+++ b/chrome/browser/resources/download_shelf/app.ts
@@ -19,19 +19,21 @@
     return `{__html_template__}`;
   }
 
+  private apiProxy_: DownloadShelfApiProxy;
+
   constructor() {
     super();
 
     /** @private {!DownloadShelfApiProxy} */
     this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance();
 
-    const showAllButton = this.$('#show-all-button');
+    const showAllButton = this.$('#show-all-button') as HTMLElement;
     showAllButton.innerText = loadTimeData.getString('showAll');
-    showAllButton.addEventListener('click', e => this.onShowAll_());
+    showAllButton.addEventListener('click', () => this.onShowAll_());
 
     const closeButton = this.$('#close-button');
     closeButton.setAttribute('aria-label', loadTimeData.getString('close'));
-    closeButton.addEventListener('click', e => this.onClose_());
+    closeButton.addEventListener('click', () => this.onClose_());
   }
 
   /** @private */
diff --git a/chrome/browser/resources/download_shelf/download_item.js b/chrome/browser/resources/download_shelf/download_item.ts
similarity index 69%
rename from chrome/browser/resources/download_shelf/download_item.js
rename to chrome/browser/resources/download_shelf/download_item.ts
index 68db414..d19f678 100644
--- a/chrome/browser/resources/download_shelf/download_item.js
+++ b/chrome/browser/resources/download_shelf/download_item.ts
@@ -14,51 +14,45 @@
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
-import {DangerType, DownloadItem, DownloadMode, DownloadState, MixedContentStatus} from './download_shelf.mojom-webui.js';
+import {DownloadItem, DownloadMode, DownloadState} from './download_shelf.mojom-webui.js';
 import {DownloadShelfApiProxy, DownloadShelfApiProxyImpl} from './download_shelf_api_proxy.js';
 
-/** @enum {string} */
-const DisplayMode = {
+enum DisplayMode {
   // Shows icon + filename + context menu button.
-  kNormal: 'normal',
+  kNormal = 'normal',
   // Shows icon + warning text + discard button + context menu button.
-  kWarn: 'warn',
+  kWarn = 'warn',
   // Shows icon + warning text + keep button + discard button.
-  kWarnKeep: 'warn-keep'
-};
+  kWarnKeep = 'warn-keep',
+}
 
 export class DownloadItemElement extends CustomElement {
   static get template() {
     return `{__html_template__}`;
   }
 
+  private item_: DownloadItem;
+  private downloadUpdated_: boolean = false;
+  private opening_: boolean = false;
+  opened: boolean;
+  private apiProxy_: DownloadShelfApiProxy;
+
+
   constructor() {
     super();
 
-    /** @private {DownloadItem} */
-    this.item_;
-
-    /** @private {boolean} */
-    this.downloadUpdated_ = false;
-
-    /** @private {boolean} */
-    this.opening_ = false;
-
-    /** @property {boolean} */
     this.opened = false;
-
-    /** @private {!DownloadShelfApiProxy} */
     this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance();
 
     this.$('#shadow-mask')
-        .addEventListener('click', e => this.onOpenButtonClick_(e));
+        .addEventListener('click', () => this.onOpenButtonClick_());
     this.$('#dropdown-button')
         .addEventListener('click', e => this.onDropdownButtonClick_(e));
-    const discardButton = this.$('#discard-button');
+    const discardButton = this.$('#discard-button') as HTMLElement;
     discardButton.innerText = loadTimeData.getString('discardButtonText');
-    discardButton.addEventListener('click', e => this.onDiscardButtonClick_(e));
+    discardButton.addEventListener('click', () => this.onDiscardButtonClick_());
     this.$('#keep-button')
-        .addEventListener('click', e => this.onKeepButtonClick_(e));
+        .addEventListener('click', () => this.onKeepButtonClick_());
     this.addEventListener('contextmenu', e => this.onContextMenu_(e));
 
     this.$('.progress-indicator').addEventListener('animationend', () => {
@@ -67,15 +61,13 @@
     });
   }
 
-  /** @param {DownloadItem} item */
-  onDownloadUpdated(item) {
+  onDownloadUpdated(item: DownloadItem) {
     this.downloadUpdated_ = true;
     this.item_ = item;
     this.update_();
   }
 
-  /** @param {DownloadItem} value */
-  set item(value) {
+  set item(value: DownloadItem) {
     if (this.item_ === value) {
       return;
     }
@@ -83,16 +75,11 @@
     this.update_();
   }
 
-  /** @return {DownloadItem} */
-  get item() {
+  get item(): DownloadItem {
     return this.item_;
   }
 
-  /**
-   * @return {string}
-   * @private
-   */
-  get clampedWarningText_() {
+  private get clampedWarningText_(): string {
     // Views uses ui/gfx/text_elider.cc to elide text given a maximum width.
     // For simplicity, we instead elide text by restricting text length.
     const maxFilenameLength = 19;
@@ -107,35 +94,33 @@
         filename, this.elideFilename_(filename, maxFilenameLength));
   }
 
-  /** @param {boolean} value */
-  set opening(value) {
+  set opening(value: boolean) {
     if (this.opening_ !== value) {
       this.opening_ = value;
       this.update_();
     }
   }
 
-  /** @private */
-  update_() {
+  private update_() {
     const item = this.item_;
     if (!item) {
       return;
     }
-    const downloadElement = this.$('.download-item');
+    const downloadElement = this.$('.download-item') as HTMLElement;
     const filePath = item.fileNameDisplayString;
     let fileName = filePath.substring(filePath.lastIndexOf('/') + 1);
     if (this.opening_) {
       fileName = loadTimeData.getStringF('downloadStatusOpeningText', fileName);
     }
-    this.$('#filename').innerText = fileName;
+    (this.$('#filename') as HTMLElement).innerText = fileName;
 
-    const statusTextElement = this.$('#status-text');
+    const statusTextElement = this.$('#status-text') as HTMLElement;
     const statusText = (!item.shouldPromoteOrigin || !item.originalUrl.url) ?
         item.statusText :
         new URL(item.originalUrl.url).origin;
     statusTextElement.innerText = statusText;
 
-    downloadElement.dataset.state = item.state;
+    downloadElement.dataset['state'] = item.state.toString();
     if (item.mode === DownloadMode.kNormal) {
       switch (item.state) {
         case DownloadState.kInProgress:
@@ -158,70 +143,66 @@
     }
 
     if (item.isPaused) {
-      downloadElement.dataset.paused = true;
+      downloadElement.dataset['paused'] = 'true';
     } else {
-      delete downloadElement.dataset.paused;
+      delete downloadElement.dataset['paused'];
     }
 
     this.apiProxy_.getFileIcon(item.id).then(icon => {
-      this.$('#file-icon').src = icon;
+      (this.$('#file-icon') as HTMLImageElement).src = icon;
     });
 
     if (item.mode === DownloadMode.kNormal) {
-      downloadElement.dataset.displayMode = DisplayMode.kNormal;
+      downloadElement.dataset['displayMode'] = DisplayMode.kNormal;
     } else if (
         item.mode === DownloadMode.kDangerous ||
         item.mode === DownloadMode.kMixedContentWarn) {
-      downloadElement.dataset.displayMode = DisplayMode.kWarnKeep;
+      downloadElement.dataset['displayMode'] = DisplayMode.kWarnKeep;
     } else {
-      downloadElement.dataset.displayMode = DisplayMode.kWarn;
+      downloadElement.dataset['displayMode'] = DisplayMode.kWarn;
     }
 
-    this.$('#keep-button').innerText = item.warningConfirmButtonText;
-    this.$('#warning-text').innerText = this.clampedWarningText_;
+    (this.$('#keep-button') as HTMLElement).innerText =
+        item.warningConfirmButtonText;
+    (this.$('#warning-text') as HTMLElement).innerText =
+        this.clampedWarningText_;
 
     this.downloadUpdated_ = false;
   }
 
-  /** @param {number} value */
-  set progress(value) {
-    this.$('.progress')
+  set progress(value: number) {
+    (this.$('.progress') as HTMLElement)
         .style.setProperty('--download-progress', value.toString());
   }
 
-  /** @param {!Event} e */
-  onContextMenu_(e) {
+  private onContextMenu_(e: MouseEvent) {
     this.apiProxy_.showContextMenu(
         this.item.id, e.clientX, e.clientY, Date.now());
   }
 
-  /** @param {!Event} e */
-  onDropdownButtonClick_(e) {
+  private onDropdownButtonClick_(e: Event) {
     // TODO(crbug.com/1182529): Switch to down caret icon when context menu is
     // open.
-    const rect = e.target.getBoundingClientRect();
+    const rect = (e.target as Element).getBoundingClientRect();
     this.apiProxy_.showContextMenu(
         this.item.id, rect.left, rect.top, Date.now());
   }
 
-  /** @param {!Event} e */
-  onDiscardButtonClick_(e) {
+  private onDiscardButtonClick_() {
     this.apiProxy_.discardDownload(this.item.id);
   }
 
-  /** @param {!Event} e */
-  onKeepButtonClick_(e) {
+  private onKeepButtonClick_() {
     this.apiProxy_.keepDownload(this.item.id);
   }
 
   /**
    * Elide a filename to a maximum length.
    * The extension of the filename will be kept if it has one.
-   * @param {string} s A filename.
-   * @param {number} maxlen The maximum length after elided.
-   * @private
+   * @param s A filename.
+   * @param maxlen The maximum length after elided.
    */
-  elideFilename_(s, maxlen) {
+  private elideFilename_(s: string, maxlen: number): string {
     assert(maxlen > 6);
 
     if (s.length <= maxlen) {
@@ -238,8 +219,7 @@
     }
   }
 
-  /** @param {!Event} e */
-  onOpenButtonClick_(e) {
+  private onOpenButtonClick_() {
     if (this.opening_) {
       return;
     }
@@ -252,3 +232,9 @@
 }
 
 customElements.define('download-item', DownloadItemElement);
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'download-item': DownloadItemElement;
+  }
+}
diff --git a/chrome/browser/resources/download_shelf/download_list.js b/chrome/browser/resources/download_shelf/download_list.ts
similarity index 74%
rename from chrome/browser/resources/download_shelf/download_list.js
rename to chrome/browser/resources/download_shelf/download_list.ts
index 5f160ff..740ceea 100644
--- a/chrome/browser/resources/download_shelf/download_list.js
+++ b/chrome/browser/resources/download_shelf/download_list.ts
@@ -8,40 +8,30 @@
 
 import './download_item.js';
 
-import {assert} from 'chrome://resources/js/assert.m.js';
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
 import {listenOnce} from 'chrome://resources/js/util.m.js';
 
+import {DownloadItemElement} from './download_item.js';
 import {DownloadItem} from './download_shelf.mojom-webui.js';
 import {DownloadShelfApiProxy, DownloadShelfApiProxyImpl} from './download_shelf_api_proxy.js';
 
-/** @type {number} */
-const PROGRESS_UPDATE_INTERVAL = 500;
-
 export class DownloadListElement extends CustomElement {
   static get template() {
     return `{__html_template__}`;
   }
 
+  private elements_: Array<DownloadItemElement> = [];
+  private items_: Array<DownloadItem> = [];
+  private apiProxy_: DownloadShelfApiProxy;
+  private listElement_: HTMLElement;
+  private listenerIds_: Array<number> = [];
+  private resizeObserver_: ResizeObserver;
+
   constructor() {
     super();
 
-    /** @private {!Array} */
-    this.elements_ = [];
-
-    /** @private {!Array<!DownloadItem>} */
-    this.items_ = [];
-
-    /** @private {!DownloadShelfApiProxy} */
     this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance();
-
-    /** @private {!Element} */
-    this.listElement_ = assert(this.$('#download-list'));
-
-    /** @private {!Array<number>} */
-    this.listenerIds_ = [];
-
-    /** @private {ResizeObserver} */
+    this.listElement_ = this.$('#download-list') as HTMLElement;
     this.resizeObserver_ = new ResizeObserver(() => this.updateElements_());
     this.resizeObserver_.observe(this.listElement_);
 
@@ -58,31 +48,32 @@
     });
   }
 
-  /** @private */
-  addDownloadListeners_() {
+  private addDownloadListeners_(): void {
     const callbackRouter = this.apiProxy_.getCallbackRouter();
 
     // Triggers for downloads other than the first one, as the page handler will
     // not be ready by the first download.
     this.listenerIds_.push(
-        callbackRouter.onNewDownload.addListener((downloadItem) => {
-          this.items_.unshift(downloadItem);
-          this.updateElements_();
-          this.recordDownloadPaintTime_(
-              downloadItem.showDownloadStartTime, false);
-        }),
-        callbackRouter.onDownloadUpdated.addListener((downloadItem) => {
-          const index =
-              this.items_.findIndex(item => item.id === downloadItem.id);
-          if (index >= 0) {
-            this.items_[index] = downloadItem;
-            const element = this.elements_[index];
-            if (element) {
-              element.onDownloadUpdated(downloadItem);
-            }
-          }
-        }),
-        callbackRouter.onDownloadErased.addListener((downloadId) => {
+        callbackRouter.onNewDownload.addListener(
+            (downloadItem: DownloadItem) => {
+              this.items_.unshift(downloadItem);
+              this.updateElements_();
+              this.recordDownloadPaintTime_(
+                  downloadItem.showDownloadStartTime, false);
+            }),
+        callbackRouter.onDownloadUpdated.addListener(
+            (downloadItem: DownloadItem) => {
+              const index =
+                  this.items_.findIndex(item => item.id === downloadItem.id);
+              if (index >= 0) {
+                this.items_[index] = downloadItem;
+                const element = this.elements_[index];
+                if (element) {
+                  element.onDownloadUpdated(downloadItem);
+                }
+              }
+            }),
+        callbackRouter.onDownloadErased.addListener((downloadId: number) => {
           const index = this.items_.findIndex(item => item.id === downloadId);
           if (index >= 0) {
             this.items_.splice(index, 1);
@@ -92,7 +83,7 @@
             }
           }
         }),
-        callbackRouter.onDownloadOpened.addListener((downloadId) => {
+        callbackRouter.onDownloadOpened.addListener((downloadId: number) => {
           const element =
               this.elements_.find(element => element.item.id === downloadId);
           if (element) {
@@ -106,11 +97,8 @@
         }));
   }
 
-  /**
-   * @param {boolean} firstCall Whether this is the first call to the method.
-   * @private
-   */
-  getDownloads_(firstCall) {
+  /** @param firstCall Whether this is the first call to the method. */
+  private getDownloads_(firstCall: boolean) {
     this.apiProxy_.getDownloads().then(({downloadItems}) => {
       this.items_ = downloadItems;
 
@@ -132,8 +120,7 @@
     });
   }
 
-  /** @private */
-  clear_() {
+  private clear_() {
     while (this.listenerIds_.length) {
       this.apiProxy_.getCallbackRouter().removeListener(
           this.listenerIds_.shift());
@@ -148,13 +135,13 @@
   }
 
   /**
-   * @param {number} startTime The Unix time at which DoShowDownload() was
+   * @param startTime The Unix time at which DoShowDownload() was
    *     called on the download shelf. See:
    *     chrome/browser/ui/webui/download_shelf/download_shelf_ui.h
-   * @param {boolean} isFirstDownload
-   * @private
+   * @param isFirstDownload
    */
-  recordDownloadPaintTime_(startTime, isFirstDownload) {
+  private recordDownloadPaintTime_(
+      startTime: number, isFirstDownload: boolean) {
     window.requestAnimationFrame(() => {
       window.requestAnimationFrame(() => {
         const elapsedTime = Math.round(Date.now() - startTime);
@@ -166,8 +153,7 @@
     });
   }
 
-  /** @private */
-  updateElements_() {
+  private updateElements_() {
     const containerWidth = this.listElement_.offsetWidth;
     let currentWidth = 0;
     const itemCount = this.items_.length;
@@ -183,7 +169,7 @@
         }
         break;
       }
-      let downloadElement;
+      let downloadElement: DownloadItemElement;
       if (i < elementCount) /** Update existing elements inside viewport. */ {
         downloadElement = this.elements_[i];
         downloadElement.item = this.items_[i];
@@ -209,9 +195,8 @@
   /**
    * If all items are opened, automatically close the download shelf
    * when the mouse leaves the download shelf after some delay.
-   * @private
    */
-  autoClose_() {
+  private autoClose_() {
     if (this.elements_.every(element => element.opened)) {
       listenOnce(this, 'mouseleave', () => {
         setTimeout(() => {
@@ -225,3 +210,9 @@
 }
 
 customElements.define('download-list', DownloadListElement);
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'download-list': DownloadListElement;
+  }
+}
diff --git a/chrome/browser/resources/download_shelf/download_shelf.js b/chrome/browser/resources/download_shelf/download_shelf.ts
similarity index 82%
rename from chrome/browser/resources/download_shelf/download_shelf.js
rename to chrome/browser/resources/download_shelf/download_shelf.ts
index 5bdc2e9..4eae58e 100644
--- a/chrome/browser/resources/download_shelf/download_shelf.js
+++ b/chrome/browser/resources/download_shelf/download_shelf.ts
@@ -7,4 +7,4 @@
 export {DownloadShelfAppElement} from './app.js';
 export {DownloadListElement} from './download_list.js';
 export {DangerType, DownloadItem, DownloadMode, DownloadState, MixedContentStatus, PageCallbackRouter, PageRemote} from './download_shelf.mojom-webui.js';
-export {DownloadShelfApiProxy, DownloadShelfApiProxyImpl} from './download_shelf_api_proxy.js';
+export {DownloadShelfApiProxyImpl} from './download_shelf_api_proxy.js';
diff --git a/chrome/browser/resources/download_shelf/download_shelf_api_proxy.js b/chrome/browser/resources/download_shelf/download_shelf_api_proxy.js
deleted file mode 100644
index 12a8fa39a4..0000000
--- a/chrome/browser/resources/download_shelf/download_shelf_api_proxy.js
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
-
-import {DownloadItem, PageCallbackRouter, PageHandlerFactory, PageHandlerRemote} from './download_shelf.mojom-webui.js';
-
-/** @interface */
-export class DownloadShelfApiProxy {
-  /** @return {!PageCallbackRouter} */
-  getCallbackRouter() {}
-
-  doShowAll() {}
-
-  doClose() {}
-
-  /**
-   * @return {!Promise<{
-        downloadItems: !Array<!DownloadItem>,
-   *  }>}
-   */
-  getDownloads() {}
-
-  /**
-   * @param {number} downloadId
-   * @return {!Promise}
-   */
-  getFileIcon(downloadId) {}
-
-  /** @param {number} downloadId */
-  discardDownload(downloadId) {}
-
-  /** @param {number} downloadId */
-  keepDownload(downloadId) {}
-
-  /**
-   * @param {number} downloadId
-   * @param {number} clientX
-   * @param {number} clientY
-   * @param {number} timestamp
-   */
-  showContextMenu(downloadId, clientX, clientY, timestamp) {}
-
-  /**
-   * @param {number} downloadId
-   */
-  openDownload(downloadId) {}
-}
-
-/** @implements {DownloadShelfApiProxy} */
-export class DownloadShelfApiProxyImpl {
-  constructor() {
-    /** @type {!PageCallbackRouter} */
-    this.callbackRouter = new PageCallbackRouter();
-
-    /** @type {!PageHandlerRemote} */
-    this.handler = new PageHandlerRemote();
-
-    const factory = PageHandlerFactory.getRemote();
-    factory.createPageHandler(
-        this.callbackRouter.$.bindNewPipeAndPassRemote(),
-        this.handler.$.bindNewPipeAndPassReceiver());
-  }
-
-  /** @override */
-  getCallbackRouter() {
-    return this.callbackRouter;
-  }
-
-  /** @override */
-  doShowAll() {
-    this.handler.doShowAll();
-  }
-
-  /** @override */
-  doClose() {
-    this.handler.doClose();
-  }
-
-  /** @override */
-  getDownloads() {
-    return this.handler.getDownloads();
-  }
-
-  /** @override */
-  getFileIcon(downloadId) {
-    return new Promise(resolve => {
-      chrome.downloads.getFileIcon(downloadId, resolve);
-    });
-  }
-
-  /** @override */
-  discardDownload(downloadId) {
-    this.handler.discardDownload(downloadId);
-  }
-
-  /** @override */
-  keepDownload(downloadId) {
-    this.handler.keepDownload(downloadId);
-  }
-
-  /** @override */
-  showContextMenu(downloadId, clientX, clientY, timestamp) {
-    this.handler.showContextMenu(downloadId, clientX, clientY, timestamp);
-  }
-
-  /** @override */
-  openDownload(downloadId) {
-    this.handler.openDownload(downloadId);
-  }
-}
-
-addSingletonGetter(DownloadShelfApiProxyImpl);
diff --git a/chrome/browser/resources/download_shelf/download_shelf_api_proxy.ts b/chrome/browser/resources/download_shelf/download_shelf_api_proxy.ts
new file mode 100644
index 0000000..784ba9f5
--- /dev/null
+++ b/chrome/browser/resources/download_shelf/download_shelf_api_proxy.ts
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {DownloadItem, PageCallbackRouter, PageHandlerFactory, PageHandlerRemote} from './download_shelf.mojom-webui.js';
+
+export interface DownloadShelfApiProxy {
+  getCallbackRouter(): PageCallbackRouter;
+  doShowAll(): void;
+  doClose(): void;
+  getDownloads(): Promise<{downloadItems: DownloadItem[]}>;
+  getFileIcon(downloadId: number): Promise<string>;
+  discardDownload(downloadId: number): void;
+  keepDownload(downloadId: number): void;
+  showContextMenu(
+      downloadId: number, clientX: number, clientY: number,
+      timestamp: number): void;
+  openDownload(downloadId: number): void;
+}
+
+export class DownloadShelfApiProxyImpl implements DownloadShelfApiProxy {
+  private callbackRouter: PageCallbackRouter;
+  private handler: PageHandlerRemote;
+
+  constructor() {
+    this.callbackRouter = new PageCallbackRouter();
+    this.handler = new PageHandlerRemote();
+
+    const factory = PageHandlerFactory.getRemote();
+    factory.createPageHandler(
+        this.callbackRouter.$.bindNewPipeAndPassRemote(),
+        this.handler.$.bindNewPipeAndPassReceiver());
+  }
+
+  getCallbackRouter(): PageCallbackRouter {
+    return this.callbackRouter;
+  }
+
+  doShowAll(): void {
+    this.handler.doShowAll();
+  }
+
+  doClose(): void {
+    this.handler.doClose();
+  }
+
+  getDownloads(): Promise<{downloadItems: DownloadItem[]}> {
+    return this.handler.getDownloads();
+  }
+
+  getFileIcon(downloadId: number): Promise<string> {
+    return new Promise(resolve => {
+      chrome.downloads.getFileIcon(downloadId, resolve);
+    });
+  }
+
+  discardDownload(downloadId: number): void {
+    this.handler.discardDownload(downloadId);
+  }
+
+  keepDownload(downloadId: number): void {
+    this.handler.keepDownload(downloadId);
+  }
+
+  showContextMenu(
+      downloadId: number, clientX: number, clientY: number,
+      timestamp: number): void {
+    this.handler.showContextMenu(downloadId, clientX, clientY, timestamp);
+  }
+
+  openDownload(downloadId: number): void {
+    this.handler.openDownload(downloadId);
+  }
+
+  static getInstance(): DownloadShelfApiProxy {
+    return instance || (instance = new DownloadShelfApiProxyImpl());
+  }
+
+  static setInstance(obj: DownloadShelfApiProxy) {
+    instance = obj;
+  }
+}
+
+let instance: DownloadShelfApiProxy|null = null;
diff --git a/chrome/browser/resources/download_shelf/tsconfig_base.json b/chrome/browser/resources/download_shelf/tsconfig_base.json
new file mode 100644
index 0000000..895f374
--- /dev/null
+++ b/chrome/browser/resources/download_shelf/tsconfig_base.json
@@ -0,0 +1,10 @@
+{
+  "extends": "../../../../tools/typescript/tsconfig_base.json",
+  "compilerOptions": {
+    "allowJs": true,
+    "noUncheckedIndexedAccess": false,
+    "noUnusedLocals": false,
+    "strictNullChecks": false,
+    "strictPropertyInitialization": false
+  }
+}
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index 4ef2212e..81705a7 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -37,11 +37,7 @@
 generate_grd("build_grd") {
   grd_prefix = "extensions"
   out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
-  input_files = [
-    "checkup_image_dark.svg",
-    "checkup_image.svg",
-    "extensions.html",
-  ]
+  input_files = [ "extensions.html" ]
   input_files_base_dir = rebase_path(".", "//")
 
   if (optimize_webui) {
@@ -78,7 +74,6 @@
   in_folder = target_gen_dir
   out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = [
-    "checkup.ts",
     "code_section.ts",
     "activity_log/activity_log_history_item.ts",
     "activity_log/activity_log_history.ts",
@@ -123,7 +118,6 @@
 
 html_to_js("web_components_local") {
   js_files = [
-    "checkup.ts",
     "code_section.ts",
     "detail_view.ts",
     "drop_overlay.ts",
@@ -181,7 +175,6 @@
     "activity_log/activity_log.ts",
     "activity_log/activity_log_stream_item.ts",
     "activity_log/activity_log_stream.ts",
-    "checkup.ts",
     "code_section.ts",
     "detail_view.ts",
     "drag_and_drop_handler.ts",
diff --git a/chrome/browser/resources/extensions/checkup.html b/chrome/browser/resources/extensions/checkup.html
deleted file mode 100644
index 8b53fd1..0000000
--- a/chrome/browser/resources/extensions/checkup.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<style include="cr-shared-style iron-flex shared-style">
-  :host {
-    --checkup-card-margin: 24px;
-    --banner-img-height: 115px;
-    --banner-img-width: 298px;
-  }
-
-  #card {
-    background-color: var(--cr-card-background-color);
-    border-radius: var(--cr-card-border-radius);
-    box-shadow: var(--cr-card-shadow);
-    overflow: hidden;
-    padding: var(--checkup-card-margin);
-    transition: height var(--drawer-transition);
-  }
-
-  #banner-img {
-    background: url(checkup_image.svg);
-    background-repeat: no-repeat;
-    display: inline-block;
-    float: right;
-    /* Height and width match the dimensions of the banner image. */
-    height: var(--banner-img-height);
-    width: var(--banner-img-width);
-  }
-
-  #banner-description {
-    flex-basis: var(--extensions-card-width);
-    text-overflow: ellipsis;
-  }
-
-  #banner-title {
-    color: var(--cr-primary-text-color);
-    font-size: 123%;
-  }
-
-  /* 932px is the last screen width in which we can fit a banner that spans two
-     columns and can be calculated by adding 2 card widths of
-     var(--extensions-card-width) and the column gap var(--grid-gutter) and
-     maintain padding of 60px on either side of the content on this page
-     (see content-wrapper in item-list.html).*/
-  @media (max-width: 931px) {
-    #banner-img {
-      display: block;
-      float: initial;
-      margin: 12px auto 0;
-    }
-  }
-
-  @media (prefers-color-scheme: dark) {
-    #banner-img {
-      background: url(checkup_image_dark.svg);
-    }
-  }
-
-</style>
-<div id="card">
-  <div id="banner-title" class="cr-title-text">$i18n{checkupTitle}</div>
-  <div id="banner-img"></div>
-  <div id="banner-description" class="cr-secondary-text">
-    <p>$i18n{checkupBody1}</p>
-    <p>$i18n{checkupBody2}</p>
-  </div>
-</div>
diff --git a/chrome/browser/resources/extensions/checkup.ts b/chrome/browser/resources/extensions/checkup.ts
deleted file mode 100644
index 82cb764..0000000
--- a/chrome/browser/resources/extensions/checkup.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'chrome://resources/cr_components/managed_footnote/managed_footnote.js';
-import 'chrome://resources/cr_elements/shared_style_css.m.js';
-import './shared_style.js';
-
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-class ExtensionsCheckupElement extends PolymerElement {
-  static get is() {
-    return 'extensions-checkup';
-  }
-
-  static get template() {
-    return html`{__html_template__}`;
-  }
-}
-
-customElements.define(ExtensionsCheckupElement.is, ExtensionsCheckupElement);
diff --git a/chrome/browser/resources/extensions/checkup_image.svg b/chrome/browser/resources/extensions/checkup_image.svg
deleted file mode 100644
index 2965cae..0000000
--- a/chrome/browser/resources/extensions/checkup_image.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="270" height="117" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient x1="22.739%" y1="50%" x2="50%" y2="50%" id="a"><stop stop-color="#E8EAED" offset="0%"/><stop stop-color="#FFF" offset="100%"/></linearGradient><path id="b" d="M0 .195h94.65v14.023H0z"/><path id="d" d="M.062.195h136.716v14.023H.062z"/><path id="f" d="M0 116.114h217.344V.426H0z"/><path d="M35.238 19.048h-2.857v-7.62a3.808 3.808 0 0 0-3.81-3.809h-7.619V4.762A4.764 4.764 0 0 0 16.19 0a4.764 4.764 0 0 0-4.761 4.762v2.857h-7.62a3.792 3.792 0 0 0-3.79 3.81l-.01 7.238h2.848A5.146 5.146 0 0 1 8 23.81a5.146 5.146 0 0 1-5.143 5.142H.01L0 36.19A3.808 3.808 0 0 0 3.81 40h7.238v-2.857A5.146 5.146 0 0 1 16.19 32a5.146 5.146 0 0 1 5.143 5.143V40h7.238a3.808 3.808 0 0 0 3.81-3.81v-7.619h2.857A4.764 4.764 0 0 0 40 23.81a4.764 4.764 0 0 0-4.762-4.762z" id="h"/><path id="j" d="M0 0h12v12H0z"/></defs><g fill="none" fill-rule="evenodd"><path fill="url(#a)" transform="matrix(-1 0 0 1 57 0)" d="M0 109h57v7H0z"/><g transform="translate(51)"><path d="M.79 104.807V5.166a3.954 3.954 0 0 1 3.95-3.95h15.503v103.59H.79z" fill="#F8F9FA"/><path d="M21.033.426H4.74A4.74 4.74 0 0 0 0 5.166v100.43h21.033V.426zm-1.58 1.58v102.01H1.58V5.167a3.164 3.164 0 0 1 3.16-3.16h14.713z" fill="#E8EAED"/><path d="M7.801 104.807V5.166a3.954 3.954 0 0 1 3.95-3.95h123.73a3.954 3.954 0 0 1 3.95 3.95v99.64H7.801z" fill="#FFF"/><path d="M135.482.426H11.751a4.74 4.74 0 0 0-4.74 4.74v100.43h133.21V5.166a4.74 4.74 0 0 0-4.739-4.74m0 1.58a3.163 3.163 0 0 1 3.16 3.16v98.85H8.592V5.167a3.163 3.163 0 0 1 3.159-3.16h123.731" fill="#E8EAED"/><path d="M4.74 115.324a3.954 3.954 0 0 1-3.95-3.95v-8.493h93.07v12.443H4.74z" fill="#F8F9FA"/><g transform="translate(0 101.896)"><mask id="c" fill="#fff"><use xlink:href="#b"/></mask><path d="M94.65.195H0V9.48a4.74 4.74 0 0 0 4.739 4.74h89.91V.194zm-1.58 1.58v10.863H4.739a3.164 3.164 0 0 1-3.16-3.16V1.776H93.07z" fill="#E8EAED" mask="url(#c)"/></g><path d="M85.367 115.324a3.954 3.954 0 0 1-3.95-3.95v-8.493h135.137v8.493a3.954 3.954 0 0 1-3.95 3.95H85.367z" fill="#FFF"/><g transform="translate(80.565 101.896)"><mask id="e" fill="#fff"><use xlink:href="#d"/></mask><path d="M136.778.195H.062V9.48a4.74 4.74 0 0 0 4.74 4.74h127.237a4.74 4.74 0 0 0 4.74-4.74V.195zm-1.58 1.58v7.704a3.163 3.163 0 0 1-3.159 3.16H4.801a3.164 3.164 0 0 1-3.16-3.16V1.775h133.557z" fill="#E8EAED" mask="url(#e)"/></g><path d="M163.629 109.102h-29.287a2.884 2.884 0 0 1-2.884-2.884v-4.127h35.055v4.127a2.884 2.884 0 0 1-2.884 2.884" fill="#E8EAED"/><mask id="g" fill="#fff"><use xlink:href="#f"/></mask><path fill="#F8F9FA" mask="url(#g)" d="M18.318 94.29h110.597V11.734H18.318z"/><path d="M17.528 95.08h112.177V10.943H17.528V95.08zm1.58-1.58h109.018V12.522H19.108V93.5z" fill="#E8EAED" mask="url(#g)"/></g><g transform="translate(106 32)"><mask id="i" fill="#fff"><use xlink:href="#h"/></mask><use fill="#3C4043" fill-rule="nonzero" xlink:href="#h"/><g mask="url(#i)" fill="#1A73E8"><path d="M-3.81-1.905h46v46h-46z"/></g></g><path d="M162.83 24.905L166 24l-3.17-.906a5.714 5.714 0 0 1-3.924-3.924L158 16l-.906 3.17a5.714 5.714 0 0 1-3.924 3.924L150 24l3.17.905a5.714 5.714 0 0 1 3.924 3.925L158 32l.906-3.17a5.714 5.714 0 0 1 3.924-3.925m9.585 43.548L174 68l-1.585-.453a2.856 2.856 0 0 1-1.962-1.962L170 64l-.453 1.585a2.856 2.856 0 0 1-1.962 1.962L166 68l1.585.453a2.856 2.856 0 0 1 1.962 1.962L170 72l.453-1.585a2.856 2.856 0 0 1 1.962-1.962" fill="#FBBC04"/><g transform="translate(74 80)"><mask id="k" fill="#fff"><use xlink:href="#j"/></mask><path d="M9.623 6.68L12 6l-2.377-.68A4.284 4.284 0 0 1 6.68 2.378L6 0l-.68 2.377A4.284 4.284 0 0 1 2.379 5.32L0 6l2.378.68A4.283 4.283 0 0 1 5.32 9.623L6 12l.68-2.377A4.283 4.283 0 0 1 9.623 6.68" fill="#FBBC04" mask="url(#k)"/></g></g></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/extensions/item_list.html b/chrome/browser/resources/extensions/item_list.html
index 56b2f7b..8b74a37c 100644
--- a/chrome/browser/resources/extensions/item_list.html
+++ b/chrome/browser/resources/extensions/item_list.html
@@ -93,10 +93,6 @@
       <span>$i18n{noSearchResults}</span>
     </div>
     <div class="items-container" hidden="[[!shownExtensionsCount_]]">
-      <div id="checkup-container" hidden="[[!showCheckup_]]">
-        <extensions-checkup id="checkup" slot="view">
-        </extensions-checkup>
-      </div>
       <!-- Render only a few items first, to improve initial render time,
         then render the remaining items on a different frame. Value of 3
         was chosen by experimentation, and it is a good trade-off between
diff --git a/chrome/browser/resources/extensions/item_list.ts b/chrome/browser/resources/extensions/item_list.ts
index 28e38e6..a53863f 100644
--- a/chrome/browser/resources/extensions/item_list.ts
+++ b/chrome/browser/resources/extensions/item_list.ts
@@ -3,13 +3,11 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/cr_components/managed_footnote/managed_footnote.js';
-import './checkup.js';
 import './item.js';
 import './shared_style.js';
 
 import {CrContainerShadowBehavior} from 'chrome://resources/cr_elements/cr_container_shadow_behavior.m.js';
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
@@ -53,12 +51,7 @@
 
       maxColumns_: {
         type: Number,
-        value: () => loadTimeData.getBoolean('showCheckup') ? 2 : 3,
-      },
-
-      showCheckup_: {
-        type: Boolean,
-        value: () => loadTimeData.getBoolean('showCheckup'),
+        value: 3,
       },
 
       shownAppsCount_: {
@@ -80,7 +73,6 @@
   filter: string;
   private computedFilter_: string;
   private maxColumns_: number;
-  private showCheckup_: boolean;
   private shownAppsCount_: number;
   private shownExtensionsCount_: number;
 
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts
index 4c3f941..852c1b80 100644
--- a/chrome/browser/resources/history/app.ts
+++ b/chrome/browser/resources/history/app.ts
@@ -116,7 +116,7 @@
 
 export interface HistoryAppElement {
   $: {
-    'drawer': CrLazyRenderElement,
+    'drawer': CrLazyRenderElement<CrDrawerElement>,
     'history': HistoryListElement,
     'toolbar': HistoryToolbarElement,
   };
@@ -276,8 +276,7 @@
   }
 
   private onCrToolbarMenuTap_() {
-    const drawer = this.$.drawer.get() as CrDrawerElement;
-    drawer.toggle();
+    this.$.drawer.get().toggle();
   }
 
   /**
@@ -415,7 +414,7 @@
   }
 
   private hasDrawerChanged_() {
-    const drawer = this.$.drawer.getIfExists() as CrDrawerElement;
+    const drawer = this.$.drawer.getIfExists();
     if (!this.hasDrawer_ && drawer && drawer.open) {
       drawer.cancel();
     }
diff --git a/chrome/browser/resources/history/history_list.ts b/chrome/browser/resources/history/history_list.ts
index e9a15c3d..6a20739 100644
--- a/chrome/browser/resources/history/history_list.ts
+++ b/chrome/browser/resources/history/history_list.ts
@@ -49,8 +49,8 @@
   $: {
     'infinite-list': IronListElement,
     'scroll-threshold': IronScrollThresholdElement,
-    'dialog': CrLazyRenderElement,
-    'sharedMenu': CrLazyRenderElement,
+    'dialog': CrLazyRenderElement<CrDialogElement>,
+    'sharedMenu': CrLazyRenderElement<CrActionMenuElement>,
   };
 }
 
@@ -269,7 +269,7 @@
     if (this.queryState.searchTerm !== '') {
       browserService.recordAction('SearchResultRemove');
     }
-    (this.$.dialog.get() as CrDialogElement).showModal();
+    this.$.dialog.get().showModal();
 
     // TODO(dbeam): remove focus flicker caused by showModal() + focus().
     (this.shadowRoot!.querySelector('.action-button') as HTMLElement).focus();
@@ -341,7 +341,7 @@
    * Closes the overflow menu.
    */
   private closeMenu_() {
-    const menu = this.$.sharedMenu.getIfExists() as CrActionMenuElement;
+    const menu = this.$.sharedMenu.getIfExists();
     if (menu && menu.open) {
       this.actionMenuModel_ = null;
       menu.close();
@@ -355,15 +355,15 @@
     BrowserService.getInstance().recordAction('ConfirmRemoveSelected');
 
     this.deleteSelected_();
-    const dialog = assert(this.$.dialog.getIfExists()) as CrDialogElement;
-    dialog.close();
+    const dialog = assert(this.$.dialog.getIfExists());
+    dialog!.close();
   }
 
   private onDialogCancelTap_() {
     BrowserService.getInstance().recordAction('CancelRemoveSelected');
 
-    const dialog = assert(this.$.dialog.getIfExists()) as CrDialogElement;
-    dialog.close();
+    const dialog = assert(this.$.dialog.getIfExists());
+    dialog!.close();
   }
 
   /**
@@ -408,14 +408,13 @@
 
     const target = e.detail.target;
     this.actionMenuModel_ = e.detail;
-    const menu = this.$.sharedMenu.get() as CrActionMenuElement;
-    menu.showAt(target);
+    this.$.sharedMenu.get().showAt(target);
   }
 
   private onMoreFromSiteTap_() {
     BrowserService.getInstance().recordAction('EntryMenuShowMoreFromSite');
 
-    const menu = assert(this.$.sharedMenu.getIfExists());
+    assert(this.$.sharedMenu.getIfExists());
     this.fire_('change-query', {search: this.actionMenuModel_!.item.domain});
     this.actionMenuModel_ = null;
     this.closeMenu_();
@@ -436,7 +435,7 @@
     browserService.recordAction('EntryMenuRemoveFromHistory');
 
     assert(!this.pendingDelete);
-    const menu = assert(this.$.sharedMenu.getIfExists());
+    assert(this.$.sharedMenu.getIfExists());
     const itemData = this.actionMenuModel_!;
 
     this.deleteItems_([itemData.item]).then(() => {
diff --git a/chrome/browser/resources/history/synced_device_manager.ts b/chrome/browser/resources/history/synced_device_manager.ts
index bbbbb1e..43ac07d 100644
--- a/chrome/browser/resources/history/synced_device_manager.ts
+++ b/chrome/browser/resources/history/synced_device_manager.ts
@@ -44,7 +44,7 @@
 
 export interface HistorySyncedDeviceManagerElement {
   $: {
-    'menu': CrLazyRenderElement,
+    'menu': CrLazyRenderElement<CrActionMenuElement>,
   };
 }
 
@@ -177,16 +177,15 @@
   }
 
   private onOpenMenu_(e: CustomEvent<{tag: string, target: HTMLElement}>) {
-    const menu = this.$['menu'].get() as CrActionMenuElement;
     this.actionMenuModel_ = e.detail.tag;
-    menu.showAt(e.detail.target);
+    this.$['menu'].get().showAt(e.detail.target);
     BrowserService.getInstance().recordHistogram(
         SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.SHOW_SESSION_MENU,
         SyncedTabsHistogram.LIMIT);
   }
 
   private onOpenAllTap_() {
-    const menu = assert(this.$['menu'].getIfExists()) as CrActionMenuElement;
+    const menu = assert(this.$['menu'].getIfExists());
     const browserService = BrowserService.getInstance();
     browserService.recordHistogram(
         SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.OPEN_ALL,
diff --git a/chrome/browser/resources/pdf/controller.js b/chrome/browser/resources/pdf/controller.js
index 95dca320..5943d70 100644
--- a/chrome/browser/resources/pdf/controller.js
+++ b/chrome/browser/resources/pdf/controller.js
@@ -484,6 +484,17 @@
   }
 
   /**
+   * An event handler for handling message events received from the Unseasoned
+   * PDF plugin.
+   * TODO(crbug.com/1228987): Remove this method when a permanent postMessage()
+   * bridge is implemented for the Unseasoned viewer.
+   * @param {!Event} messageEvent a message event.
+   */
+  handleMessageForUnseasoned(messageEvent) {
+    this.handlePluginMessage_(messageEvent);
+  }
+
+  /**
    * An event handler for handling message events received from the plugin.
    * @param {!Event} messageEvent a message event.
    * @private
diff --git a/chrome/browser/resources/pdf/pdf_viewer_base.js b/chrome/browser/resources/pdf/pdf_viewer_base.js
index 23a3520..d9a9285 100644
--- a/chrome/browser/resources/pdf/pdf_viewer_base.js
+++ b/chrome/browser/resources/pdf/pdf_viewer_base.js
@@ -374,6 +374,21 @@
    * @param {!MessageObject} message The message to handle.
    */
   handleScriptingMessage(message) {
+    // TODO(crbug.com/1228987): Remove this message handler when a permanent
+    // postMessage() bridge is implemented for the Unseasoned viewer.
+    if (message.data.type === 'connect') {
+      const token = /** @type {!{token: string}} */ (message.data).token;
+      if (token === this.browserApi.getStreamInfo().streamUrl) {
+        const port = message.ports[0];
+        this.plugin_.postMessage = m => port.postMessage(m);
+        port.onmessage = e =>
+            PluginController.getInstance().handleMessageForUnseasoned(e);
+      } else {
+        this.dispatchEvent(new CustomEvent('connection-denied-for-testing'));
+      }
+      return;
+    }
+
     if (this.parentWindow_ !== message.source) {
       this.parentWindow_ = message.source;
       this.parentOrigin_ = message.origin;
diff --git a/chrome/browser/resources/read_later/BUILD.gn b/chrome/browser/resources/read_later/BUILD.gn
index 6197fbf..ab68375 100644
--- a/chrome/browser/resources/read_later/BUILD.gn
+++ b/chrome/browser/resources/read_later/BUILD.gn
@@ -145,6 +145,7 @@
   definitions = [
     "//tools/typescript/definitions/bookmarks.d.ts",
     "//tools/typescript/definitions/chrome_event.d.ts",
+    "//tools/typescript/definitions/metrics_private.d.ts",
   ]
   deps = [
     "//third_party/polymer/v3_0:library",
diff --git a/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts b/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts
index 0130584..b00d99b 100644
--- a/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts
+++ b/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts
@@ -75,7 +75,7 @@
 
   private onBookmarkClick_(event: RepeaterMouseEvent) {
     event.preventDefault();
-    this.bookmarksApi_.openBookmark(event.model.item.url!);
+    this.bookmarksApi_.openBookmark(event.model.item.url!, this.depth);
   }
 
   private onBookmarkContextMenu_(event: RepeaterMouseEvent) {
@@ -109,6 +109,10 @@
         open: this.open_,
       }
     }));
+
+    chrome.metricsPrivate.recordUserAction(
+        this.open_ ? 'SidePanel.Bookmarks.FolderOpen' :
+                     'SidePanel.Bookmarks.FolderClose');
   }
 
   private onOpenFoldersChanged_() {
diff --git a/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts b/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts
index 79e29d5..3fdf3d1 100644
--- a/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts
+++ b/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts
@@ -41,8 +41,8 @@
     }));
   }
 
-  openBookmark(url: string) {
-    this.handler.openBookmark({url});
+  openBookmark(url: string, depth: number) {
+    this.handler.openBookmark({url}, depth);
   }
 
   showContextMenu(id: string, x: number, y: number) {
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 01460344..41084e0 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -132,7 +132,6 @@
     "downloads_page/downloads_browser_proxy.js",
     "ensure_lazy_loaded.js",
     "extension_control_browser_proxy.js",
-    "global_scroll_target_behavior.js",
     "global_scroll_target_mixin.js",
     "hats_browser_proxy.js",
     "i18n_setup.js",
@@ -428,7 +427,6 @@
   deps = [
     ":base_mixin",
     ":extension_control_browser_proxy",
-    ":global_scroll_target_behavior",
     ":hats_browser_proxy",
     ":i18n_setup",
     ":lazy_load",
@@ -480,13 +478,6 @@
   deps = [ "//ui/webui/resources/js:load_time_data.m" ]
 }
 
-js_library("global_scroll_target_behavior") {
-  deps = [
-    ":router",
-    "//ui/webui/resources/js:promise_resolver.m",
-  ]
-}
-
 js_library("global_scroll_target_mixin") {
   deps = [
     ":router",
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index b9ea188e..9b2af00 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -213,6 +213,7 @@
     "chromeos/lazy_load.js",
     "chromeos/date_time_page/date_time_types.js",
     "chromeos/date_time_page/timezone_browser_proxy.js",
+    "chromeos/global_scroll_target_behavior.js",
     "chromeos/google_assistant_page/google_assistant_browser_proxy.js",
     "chromeos/guest_os/guest_os_browser_proxy.js",
     "chromeos/internet_page/cellular_setup_settings_delegate.js",
@@ -232,7 +233,6 @@
     "controls/pref_control_behavior.js",
     "controls/settings_boolean_control_behavior.js",
     "extension_control_browser_proxy.js",
-    "global_scroll_target_behavior.js",
     "i18n_setup.js",
     "languages_page/languages.js",
     "languages_page/languages_browser_proxy.js",
@@ -562,6 +562,7 @@
   is_polymer3 = true
   closure_flags = os_settings_closure_flags
   deps = [
+    ":global_scroll_target_behavior",
     ":lazy_load",
     ":metrics_recorder.m",
     ":os_icons.m",
@@ -594,6 +595,13 @@
   extra_deps = [ ":modulize" ]
 }
 
+js_library("global_scroll_target_behavior") {
+  deps = [
+    "..:router",
+    "//ui/webui/resources/js:promise_resolver.m",
+  ]
+}
+
 js_library("metrics_recorder.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/metrics_recorder.m.js" ]
   deps = [ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js_library_for_compile" ]
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
index 0d5a1467..c660693 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
@@ -90,8 +90,8 @@
 js_library("album_list") {
   deps = [
     ":constants",
+    "..:global_scroll_target_behavior",
     "..:os_route.m",
-    "../..:global_scroll_target_behavior",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
 }
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
index 53966b70..084c1609 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/album_list.js
@@ -19,7 +19,7 @@
 
 import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {GlobalScrollTargetBehavior} from '../../global_scroll_target_behavior.js';
+import {GlobalScrollTargetBehavior} from '../global_scroll_target_behavior.js';
 import {routes} from '../os_route.m.js';
 
 import {AmbientModeAlbum, AmbientModeTopicSource} from './constants.js';
diff --git a/chrome/browser/resources/settings/global_scroll_target_behavior.js b/chrome/browser/resources/settings/chromeos/global_scroll_target_behavior.js
similarity index 97%
rename from chrome/browser/resources/settings/global_scroll_target_behavior.js
rename to chrome/browser/resources/settings/chromeos/global_scroll_target_behavior.js
index 38156ed..7a487711 100644
--- a/chrome/browser/resources/settings/global_scroll_target_behavior.js
+++ b/chrome/browser/resources/settings/chromeos/global_scroll_target_behavior.js
@@ -15,7 +15,7 @@
  */
 
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
-import {Route, Router, RouteObserverBehavior} from './router.js';
+import {Route, Router, RouteObserverBehavior} from '../router.js';
 
   let scrollTargetResolver = new PromiseResolver();
 
diff --git a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.html b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.html
index 470e973..072e187 100644
--- a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.html
+++ b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.html
@@ -35,6 +35,7 @@
         label="$i18n{googleAssistantEnableHotword}"
         sub-label="$i18n{googleAssistantEnableHotwordDescription}"
         on-settings-boolean-control-change="onEnableHotwordChange_"
+        disabled="[[hotwordEnforcedForChild_]]"
         deep-link-focus-id$="[[Setting.kAssistantOkGoogle]]">
     </settings-toggle-button>
   </template>
diff --git a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
index ba03570..6b06ae4 100644
--- a/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
+++ b/chrome/browser/resources/settings/chromeos/google_assistant_page/google_assistant_page.js
@@ -113,6 +113,12 @@
       value: false,
     },
 
+    /** @private */
+    hotwordEnforcedForChild_: {
+      type: Boolean,
+      value: false,
+    },
+
     /** @private {DspHotwordState} */
     dspHotwordState_: Number,
 
@@ -252,6 +258,10 @@
 
     this.hotwordEnforced_ = hotwordEnabled.enforcement ===
         chrome.settingsPrivate.Enforcement.ENFORCED;
+
+    this.hotwordEnforcedForChild_ = this.hotwordEnforced_ &&
+        hotwordEnabled.controlledBy ===
+            chrome.settingsPrivate.ControlledBy.CHILD_RESTRICTION;
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
index d58af8c..397c7b3 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -143,8 +143,8 @@
 js_library("os_edit_dictionary_page.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.m.js" ]
   deps = [
+    "..:global_scroll_target_behavior",
     "..:os_route.m",
-    "../..:global_scroll_target_behavior",
     "../../languages_page:languages_browser_proxy",
     "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.html
index adb98042..04816ba 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_edit_dictionary_page.html
@@ -9,7 +9,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="../metrics_recorder.html">
 <link rel="import" href="../os_route.html">
-<link rel="import" href="../../global_scroll_target_behavior.html">
+<link rel="import" href="../global_scroll_target_behavior.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../../languages_page/languages_browser_proxy.html">
 
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 3f7e41c..c047087 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -242,7 +242,7 @@
                              "chrome/browser/resources/settings/chromeos/route_origin_behavior.html|RouteOriginBehaviorImpl,RouteOriginBehavior",
                              "chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.html|FontsBrowserProxy,FontsBrowserProxyImpl",
                              "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList",
-                             "chrome/browser/resources/settings/global_scroll_target_behavior.html|GlobalScrollTargetBehavior,setGlobalScrollTarget",
+                             "chrome/browser/resources/settings/chromeos/global_scroll_target_behavior.html|GlobalScrollTargetBehavior,setGlobalScrollTarget",
                              "chrome/browser/resources/settings/languages_page/languages_browser_proxy.html|LanguagesBrowserProxy,LanguagesBrowserProxyImpl",
                              "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxy,LifetimeBrowserProxyImpl",
                              "chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html|AccountManagerBrowserProxy,AccountManagerBrowserProxyImpl,Account",
@@ -384,7 +384,7 @@
   "chrome/browser/resources/settings/controls/settings_toggle_button.html",
   "chrome/browser/resources/settings/ensure_lazy_loaded.html",
   "chrome/browser/resources/settings/extension_control_browser_proxy.html",
-  "chrome/browser/resources/settings/global_scroll_target_behavior.html",
+  "chrome/browser/resources/settings/chromeos/global_scroll_target_behavior.html",
   "chrome/browser/resources/settings/i18n_setup.html",
   "chrome/browser/resources/settings/icons.html",
   "chrome/browser/resources/settings/languages_page/languages_browser_proxy.html",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
index c013b03..3f14c1d 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
@@ -14,7 +14,7 @@
 <link rel="import" href="../os_settings_menu/os_settings_menu.html">
 <link rel="import" href="../os_settings_main/os_settings_main.html">
 <link rel="import" href="../os_toolbar/os_toolbar.html">
-<link rel="import" href="../../global_scroll_target_behavior.html">
+<link rel="import" href="../global_scroll_target_behavior.html">
 <link rel="import" href="../../i18n_setup.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../os_page_visibility.html">
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
index 8d65d60..d5ad29c 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
@@ -134,7 +134,7 @@
       path_(std::move(path)),
       file_name_(std::move(file_name)),
       delay_opening_file_(delay_opening_file) {
-  set_filename(file_name_.AsUTF8Unsafe());
+  set_filename(path_.AsUTF8Unsafe());
   cached_data_.mime_type = std::move(mime_type);
 }
 
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
index ebb8abd..49b3159 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
@@ -296,7 +296,7 @@
       }));
   run_loop.Run();
 
-  EXPECT_EQ(request->filename(), "foo.doc");
+  EXPECT_EQ(request->filename(), file_path.AsUTF8Unsafe());
 }
 
 TEST_F(FileAnalysisRequestTest, CachesResults) {
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index 5e6fc6c..400f6c8 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -219,7 +219,7 @@
       /* delay_opening_file */ false,
       base::BindOnce(&DeepScanningRequest::OnScanComplete,
                      weak_ptr_factory_.GetWeakPtr()));
-  request->set_filename(item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
+  request->set_filename(item_->GetTargetFilePath().AsUTF8Unsafe());
 
   std::string raw_digest_sha256 = item_->GetHash();
   request->set_digest(
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
index 8caf8d27..7b491ff 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request_unittest.cc
@@ -1000,7 +1000,7 @@
                 ->last_request()
                 .request_data()
                 .filename(),
-            "download.exe");
+            download_path_.AsUTF8Unsafe());
   EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                 ->last_request()
                 .request_data()
diff --git a/chrome/browser/search/promos/promo_service.cc b/chrome/browser/search/promos/promo_service.cc
index 33282aa..5cfd5ae 100644
--- a/chrome/browser/search/promos/promo_service.cc
+++ b/chrome/browser/search/promos/promo_service.cc
@@ -15,7 +15,6 @@
 #include "base/strings/strcat.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/extensions/extension_checkup.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/webui_url_constants.h"
@@ -139,10 +138,6 @@
 PromoService::~PromoService() = default;
 
 void PromoService::Refresh() {
-  if (extensions::ShouldShowExtensionsCheckupPromo(profile_)) {
-    ServeExtensionCheckupPromo();
-    return;
-  }
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("promo_service", R"(
         semantics {
@@ -180,35 +175,6 @@
       1024 * 1024);
 }
 
-void PromoService::ServeExtensionCheckupPromo() {
-  const extensions::CheckupMessage checkup_message =
-      static_cast<extensions::CheckupMessage>(
-          base::GetFieldTrialParamByFeatureAsInt(
-              extensions_features::kExtensionsCheckup,
-              extensions_features::kExtensionsCheckupBannerMessageParameter,
-              static_cast<int>(extensions::CheckupMessage::NEUTRAL)));
-  UMA_HISTOGRAM_ENUMERATION("Extensions.Checkup.NtpPromoShown",
-                            checkup_message);
-  PromoData checkup_promo;
-  int promo_idr = -1;
-  switch (checkup_message) {
-    case extensions::CheckupMessage::PERFORMANCE:
-      promo_idr = IDS_EXTENSIONS_PROMO_PERFORMANCE;
-      break;
-    case extensions::CheckupMessage::PRIVACY:
-      promo_idr = IDS_EXTENSIONS_PROMO_PRIVACY;
-      break;
-    case extensions::CheckupMessage::NEUTRAL:
-      promo_idr = IDS_EXTENSIONS_PROMO_NEUTRAL;
-      break;
-  }
-  std::string promo_message = l10n_util::GetStringUTF8(promo_idr);
-  std::string promo_html = base::StrCat({"<div>", promo_message, "</div>"});
-  checkup_promo.promo_html = promo_html;
-  checkup_promo.can_open_extensions_page = true;
-  PromoDataLoaded(Status::OK_WITH_PROMO, checkup_promo);
-}
-
 void PromoService::OnLoadDone(std::unique_ptr<std::string> response_body) {
   if (!response_body) {
     // This represents network errors (i.e. the server did not provide a
diff --git a/chrome/browser/search/promos/promo_service.h b/chrome/browser/search/promos/promo_service.h
index d513e164..9989eb7 100644
--- a/chrome/browser/search/promos/promo_service.h
+++ b/chrome/browser/search/promos/promo_service.h
@@ -88,10 +88,6 @@
   // been blocked by the user.
   bool IsBlockedAfterClearingExpired(const std::string& promo_id) const;
 
-  // Updates |promo_data_| with the extensions checkup tool promo
-  // information.
-  void ServeExtensionCheckupPromo();
-
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   std::unique_ptr<network::SimpleURLLoader> simple_loader_;
 
diff --git a/chrome/browser/search/promos/promo_service_unittest.cc b/chrome/browser/search/promos/promo_service_unittest.cc
index 856c5e3..6cd222e 100644
--- a/chrome/browser/search/promos/promo_service_unittest.cc
+++ b/chrome/browser/search/promos/promo_service_unittest.cc
@@ -11,8 +11,6 @@
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/search/promos/promo_data.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
@@ -22,9 +20,6 @@
 #include "components/search/ntp_features.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "content/public/test/browser_task_environment.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_builder.h"
-#include "extensions/common/extension_features.h"
 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
@@ -52,22 +47,6 @@
         std::make_unique<PromoService>(test_shared_loader_factory_, &profile_);
   }
 
-  void SetUpExtensionTest() {
-    // Creates an extension system and adds one non policy-install extension.
-    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-    extensions::TestExtensionSystem* test_ext_system =
-        static_cast<extensions::TestExtensionSystem*>(
-            extensions::ExtensionSystem::Get(&profile_));
-    extensions::ExtensionService* service =
-        test_ext_system->CreateExtensionService(&command_line, base::FilePath(),
-                                                false);
-    EXPECT_TRUE(service->extensions_enabled());
-    service->Init();
-    scoped_refptr<const extensions::Extension> extension =
-        extensions::ExtensionBuilder("foo").Build();
-    service->AddExtension(extension.get());
-  }
-
   void SetUpResponseWithData(const GURL& load_url,
                              const std::string& response) {
     test_url_loader_factory_.SetInterceptor(base::BindLambdaForTesting(
@@ -338,26 +317,3 @@
   // All the invalid formats should've been removed from the pref.
   ASSERT_EQ(0u, prefs()->GetDictionary(prefs::kNtpPromoBlocklist)->DictSize());
 }
-
-TEST_F(PromoServiceTest, ServeExtensionsPromo) {
-  SetUpExtensionTest();
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeatureWithParameters(
-      extensions_features::kExtensionsCheckup,
-      {{extensions_features::kExtensionsCheckupEntryPointParameter,
-        extensions_features::kNtpPromoEntryPoint},
-       {extensions_features::kExtensionsCheckupBannerMessageParameter,
-        extensions_features::kPerformanceMessage}});
-
-  service()->Refresh();
-  base::RunLoop().RunUntilIdle();
-
-  PromoData promo;
-  promo.promo_html =
-      "<div>" + l10n_util::GetStringUTF8(IDS_EXTENSIONS_PROMO_PERFORMANCE) +
-      "</div>";
-  promo.can_open_extensions_page = true;
-
-  EXPECT_EQ(service()->promo_data(), promo);
-  EXPECT_EQ(service()->promo_status(), PromoService::Status::OK_WITH_PROMO);
-}
diff --git a/chrome/browser/share/core/share_targets.cc b/chrome/browser/share/core/share_targets.cc
index 1444802..e0c24a9 100644
--- a/chrome/browser/share/core/share_targets.cc
+++ b/chrome/browser/share/core/share_targets.cc
@@ -120,8 +120,12 @@
 }
 
 void ShareTargets::NotifyObserver(ShareTargetsObserver* observer) {
-  // This retrieves just the country code from the locale.
-  std::string locale = g_browser_process->GetApplicationLocale().substr(3, 2);
+  std::string locale = GLOBAL;
+  std::string app_locale = g_browser_process->GetApplicationLocale();
+  if (!app_locale.empty() && app_locale.size() == 5) {
+    // This retrieves just the country code from the locale.
+    locale = app_locale.substr(3, 2);
+  }
   auto it = targets_->map_target_locale_map().find(locale);
 
   if (it == targets_->map_target_locale_map().end()) {
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc
index 81cd310..78e7618 100644
--- a/chrome/browser/sync/sync_error_notifier_ash.cc
+++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -104,10 +104,7 @@
       sync_service, profile->GetPrefs()));
 
   BubbleViewParameters params;
-  params.title_id =
-      sync_service->GetUserSettings()->IsEncryptEverythingEnabled()
-          ? IDS_SYNC_ERROR_BUBBLE_VIEW_TITLE
-          : IDS_SYNC_ERROR_PASSWORDS_BUBBLE_VIEW_TITLE;
+  params.title_id = IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE;
   params.message_id =
       sync_service->GetUserSettings()->IsEncryptEverythingEnabled()
           ? IDS_SYNC_RECOVERABILITY_DEGRADED_FOR_EVERYTHING_ERROR_BUBBLE_VIEW_MESSAGE
diff --git a/chrome/browser/translate/android/translate_bridge.cc b/chrome/browser/translate/android/translate_bridge.cc
index 99e48b60..9164253 100644
--- a/chrome/browser/translate/android/translate_bridge.cc
+++ b/chrome/browser/translate/android/translate_bridge.cc
@@ -92,8 +92,8 @@
     // If the requested target language isn't supported, show the infobar but
     // don't start translating. If the infobar is already visible, this will
     // leave it in its current state.
-    manager->InitiateManualTranslation(/*auto_translate=*/false,
-                                       /*triggered_from_menu=*/false);
+    manager->ShowTranslateUI(/*auto_translate=*/false,
+                             /*triggered_from_menu=*/false);
   } else {
     // We don't check for source_language_code support because TranslatePage
     // handles that case already.
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc
index 9450e8b..226fe9d2 100644
--- a/chrome/browser/translate/chrome_translate_client.cc
+++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -306,8 +306,8 @@
     manual_translate_on_ready_ = true;
   } else {
     translate::TranslateManager* manager = GetTranslateManager();
-    manager->InitiateManualTranslation(/*auto_translate=*/true,
-                                       /*triggered_from_menu=*/true);
+    manager->ShowTranslateUI(/*auto_translate=*/true,
+                             /*triggered_from_menu=*/true);
   }
 }
 #endif
@@ -381,7 +381,7 @@
 #if defined(OS_ANDROID)
   // See ChromeTranslateClient::ManualTranslateOnReady
   if (manual_translate_on_ready_) {
-    GetTranslateManager()->InitiateManualTranslation(true);
+    GetTranslateManager()->ShowTranslateUI(/*auto_translate=*/true);
     manual_translate_on_ready_ = false;
   }
 #endif
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d2c7adaf..5b29702f 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -437,6 +437,8 @@
     "//components/content_settings/core/browser",
     "//components/content_settings/core/common",
     "//components/country_codes",
+    "//components/crash/core/app",
+    "//components/crash/core/browser",
     "//components/crx_file",
     "//components/data_reduction_proxy/core/browser",
     "//components/device_event_log",
@@ -633,14 +635,6 @@
     deps += [ "//chrome/browser/vr:vr_base" ]
   }
 
-  if (!is_fuchsia) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
-    deps += [
-      "//components/crash/core/app",
-      "//components/crash/core/browser",
-    ]
-  }
-
   if (is_win || is_android || is_linux || is_chromeos) {
     sources += [
       "webui/sandbox/sandbox_internals_ui.cc",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 2850876f..bc1e09b 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1824,6 +1824,9 @@
       <message name="IDS_SYNC_SETTINGS_NOT_CONFIRMED_TITLE" desc="Title of the error message shown when sync setup was not complete. [CHAR_LIMIT=60]">
         Initial sync setup not finished
       </message>
+      <message name="IDS_SYNC_NEEDS_VERIFICATION_TITLE" desc="Title of the error message shown when sync needs to verify the user.">
+        Sync needs to verify it's you
+      </message>
       <message name="IDS_HINT_ANDROID_SYNC_DISABLED" desc="Hint message to resolve Android system sync is disabled error.">
         Open Android settings and re-enable Android system sync to start Chrome sync
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SYNC_NEEDS_VERIFICATION_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SYNC_NEEDS_VERIFICATION_TITLE.png.sha1
new file mode 100644
index 0000000..21e97ee84
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SYNC_NEEDS_VERIFICATION_TITLE.png.sha1
@@ -0,0 +1 @@
+c0195cf6a99ccfc748bf227c0e4887641310c1c9
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index a41e088..f601b51 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1102,7 +1102,7 @@
             if (mHomeButton != null) mHomeButton.setTranslationY(0);
         }
 
-        if (!mUrlFocusChangeInProgress) {
+        if (!mUrlFocusChangeInProgress && mToolbarShadow != null) {
             mToolbarShadow.setAlpha(mUrlBar.hasFocus() ? 0.f : 1.f);
         }
 
@@ -1858,6 +1858,8 @@
     void onStartSurfaceStateChanged(boolean shouldBeVisible, boolean isShowingStartSurface) {
         super.onStartSurfaceStateChanged(shouldBeVisible, isShowingStartSurface);
 
+        updateVisualsForLocationBarState();
+
         // Update visibilities of toolbar layout, progress bar and shadow. When |shouldBeVisible| is
         // false, set INVISIBLE instead of Gone here because of re-inflation issue. See
         // https://crbug.com/1226970 for more information.
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 030be180..ef9d0908 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -347,7 +347,7 @@
   if (!apps)
     return std::string();
 
-  for (const auto& it : apps->DictItems()) {
+  for (const auto it : apps->DictItems()) {
     const base::Value& value = it.second;
     const base::Value* installed_package_name =
         value.FindKeyOfType(kPackageName, base::Value::Type::STRING);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
index d4277b9..4935ddb 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
@@ -162,7 +162,7 @@
                           std::unordered_set<std::string>* package_names) {
   const base::DictionaryValue* dictionary = profile->GetPrefs()->GetDictionary(
       app_list::ArcAppReinstallSearchProvider::kAppState);
-  for (const auto& it : dictionary->DictItems()) {
+  for (const auto it : dictionary->DictItems()) {
     if (it.second.is_dict()) {
       package_names->insert(it.first);
     }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
index 9284a09..f0ad72d 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
@@ -187,7 +187,7 @@
   // Store all Arc apps.
   // arc_apps_ and arc_packages_ can be nullptr in tests.
   if (arc_apps_ && arc_packages_) {
-    for (const auto& app : arc_apps_->DictItems()) {
+    for (const auto app : arc_apps_->DictItems()) {
       const base::Value* package_name_value = app.second.FindKey(kPackageName);
       if (!package_name_value) {
         continue;
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
index 6593a29..e7a8838 100644
--- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "ash/public/cpp/accelerators.h"
-#include "ash/shortcut_viewer/keyboard_shortcut_item.h"
+#include "ash/public/cpp/keyboard_shortcut_item.h"
 #include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "base/hash/md5.h"
 #include "base/macros.h"
@@ -106,15 +106,13 @@
   return MD5DigestToBase16(digest);
 }
 
-std::string AcceleratorIdToString(
-    const keyboard_shortcut_viewer::AcceleratorId& accelerator_id) {
+std::string AcceleratorIdToString(const ash::AcceleratorId& accelerator_id) {
   return base::StringPrintf("keycode=%d ", accelerator_id.keycode) +
          ModifiersToString(accelerator_id.modifiers);
 }
 
 std::string AcceleratorIdsToString(
-    const std::vector<keyboard_shortcut_viewer::AcceleratorId>&
-        accelerator_ids) {
+    const std::vector<ash::AcceleratorId>& accelerator_ids) {
   std::vector<std::string> msgs;
   for (const auto& id : accelerator_ids)
     msgs.emplace_back(AcceleratorIdToString(id));
@@ -142,10 +140,10 @@
 
  protected:
   // Ash accelerator ids.
-  std::set<keyboard_shortcut_viewer::AcceleratorId> ash_accelerator_ids_;
+  std::set<ash::AcceleratorId> ash_accelerator_ids_;
 
   // Chrome accelerator ids.
-  std::set<keyboard_shortcut_viewer::AcceleratorId> chrome_accelerator_ids_;
+  std::set<ash::AcceleratorId> chrome_accelerator_ids_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(KeyboardShortcutViewerMetadataTest);
@@ -185,7 +183,7 @@
 
 // Test that AcceleratorIds have no duplicates.
 TEST_F(KeyboardShortcutViewerMetadataTest, CheckAcceleratorIdsNoDuplicates) {
-  std::set<keyboard_shortcut_viewer::AcceleratorId> accelerator_ids;
+  std::set<ash::AcceleratorId> accelerator_ids;
   for (const auto& shortcut_item :
        keyboard_shortcut_viewer::GetKeyboardShortcutItemList()) {
     for (const auto& accelerator_id : shortcut_item.accelerator_ids) {
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_target_button.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_target_button.cc
index 694c7e6a..15cfdea 100644
--- a/chrome/browser/ui/ash/sharesheet/sharesheet_target_button.cc
+++ b/chrome/browser/ui/ash/sharesheet/sharesheet_target_button.cc
@@ -11,8 +11,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/ash/sharesheet/sharesheet_constants.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/font_list.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/layout/box_layout.h"
 
@@ -37,8 +37,9 @@
     image->SetImage(icon.value());
     return image;
   } else if (vector_icon != nullptr) {
-    return std::make_unique<views::ColorTrackingIconView>(
-        *vector_icon, sharesheet::kIconSize);
+    return std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+        *vector_icon, ui::NativeTheme::kColorId_DefaultIconColor,
+        sharesheet::kIconSize));
   }
   NOTREACHED();
   return nullptr;
diff --git a/chrome/browser/ui/bookmarks/bookmark_stats.h b/chrome/browser/ui/bookmarks/bookmark_stats.h
index 5a0ade9..67d05ab 100644
--- a/chrome/browser/ui/bookmarks/bookmark_stats.h
+++ b/chrome/browser/ui/bookmarks/bookmark_stats.h
@@ -44,6 +44,16 @@
   // System application menu (e.g. on Mac).
   BOOKMARK_LAUNCH_LOCATION_TOP_MENU = 7,
 
+  // Bookmarks top level folder (i.e. bookmarks bar, other bookmarks) within the
+  // side panel.
+  BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_FOLDER = 8,
+  // Bookmarks subfolder within the side panel.
+  BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_SUBFOLDER = 9,
+  // Reading list tab within the side panel.
+  BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_READING_LIST = 10,
+  // Reading list bubble in the bookmarks bar.
+  BOOKMARK_LAUNCH_LOCATION_READING_LIST_DIALOG = 11,
+
   BOOKMARK_LAUNCH_LOCATION_LIMIT  // Keep this last.
 };
 
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
index 7db1b58..8356b23 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -379,9 +379,8 @@
 }
 
 // Tests mouse lock then fullscreen.
-// TODO(crbug.com/913409): UAv2 seems to make this flaky.
 IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
-                       DISABLED_MouseLockThenFullscreen) {
+                       MouseLockThenFullscreen) {
   auto test_server_handle = embedded_test_server()->StartAndReturnHandle();
   ASSERT_TRUE(test_server_handle);
   ui_test_utils::NavigateToURL(
@@ -433,14 +432,10 @@
   ASSERT_TRUE(IsWindowFullscreenForTabOrPending());
 }
 
-// Flaky on Linux, CrOS: http://crbug.com/159000
-// Flaky on Windows; see https://crbug.com/791539.
-// Flaky on Mac: https://crbug.com/876617.
-
 // Tests mouse lock can be exited and re-entered by an application silently
 // with no UI distraction for users.
 IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
-                       DISABLED_MouseLockSilentAfterTargetUnlock) {
+                       MouseLockSilentAfterTargetUnlock) {
   SetWebContentsGrantedSilentMouseLockPermission();
   auto test_server_handle = embedded_test_server()->StartAndReturnHandle();
   ASSERT_TRUE(test_server_handle);
@@ -468,20 +463,7 @@
   // Unlock the mouse again by target.
   PressKeyAndWaitForMouseLockRequest(ui::VKEY_U);
   ASSERT_FALSE(IsMouseLocked());
-
-  // Lock from target, not user gesture, make sure it works.
-  PressKeyAndWaitForMouseLockRequest(ui::VKEY_D);
-  ASSERT_TRUE(IsMouseLocked());
   ASSERT_FALSE(IsExclusiveAccessBubbleDisplayed());
-
-  // Unlock by escape.
-  PressKeyAndWaitForMouseLockRequest(ui::VKEY_ESCAPE);
-  ASSERT_FALSE(IsMouseLocked());
-
-  // Lock the mouse with a user gesture, make sure we see bubble again.
-  PressKeyAndWaitForMouseLockRequest(ui::VKEY_1);
-  ASSERT_TRUE(IsExclusiveAccessBubbleDisplayed());
-  ASSERT_TRUE(IsMouseLocked());
 }
 
 // Tests mouse lock is exited on page navigation.
diff --git a/chrome/browser/ui/extensions/extension_action_test_helper.h b/chrome/browser/ui/extensions/extension_action_test_helper.h
index 8d75591..bcdcfa3 100644
--- a/chrome/browser/ui/extensions/extension_action_test_helper.h
+++ b/chrome/browser/ui/extensions/extension_action_test_helper.h
@@ -16,7 +16,6 @@
 
 class Browser;
 class ExtensionsContainer;
-class ToolbarActionsBar;
 
 namespace gfx {
 class Image;
@@ -84,9 +83,6 @@
   // is too small for the preferred width.
   virtual void SetWidth(int width) = 0;
 
-  // Returns the ToolbarActionsBar.
-  virtual ToolbarActionsBar* GetToolbarActionsBar() = 0;
-
   // Returns the associated ExtensionsContainer.
   virtual ExtensionsContainer* GetExtensionsContainer() = 0;
 
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index 1a3c320..3d7cd33 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -264,13 +264,14 @@
 }
 
 void ExtensionEnableFlow::InstallPromptDone(
-    ExtensionInstallPrompt::Result result) {
-  if (result == ExtensionInstallPrompt::Result::ACCEPTED) {
+    ExtensionInstallPrompt::DoneCallbackPayload payload) {
+  if (payload.result == ExtensionInstallPrompt::Result::ACCEPTED) {
     EnableExtension();
   } else {
     delegate_->ExtensionEnableFlowAborted(/*user_initiated=*/
-                                          result == ExtensionInstallPrompt::
-                                                        Result::USER_CANCELED);
+                                          payload.result ==
+                                          ExtensionInstallPrompt::Result::
+                                              USER_CANCELED);
     // |delegate_| may delete us.
   }
 }
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.h b/chrome/browser/ui/extensions/extension_enable_flow.h
index 2c2f88bf..c83c8cd 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.h
+++ b/chrome/browser/ui/extensions/extension_enable_flow.h
@@ -102,7 +102,7 @@
 
   void EnableExtension();
 
-  void InstallPromptDone(ExtensionInstallPrompt::Result result);
+  void InstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload payload);
 
   Profile* const profile_;
   const std::string extension_id_;
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 6cc8fb2..310e21d 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -1452,31 +1452,6 @@
   observer.Wait();
 }
 
-IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FitWindow) {
-  Browser::CreateParams params(Browser::TYPE_POPUP, browser()->profile(), true);
-  params.initial_bounds = gfx::Rect(0, 0, 250, 500);
-  Browser* popup = Browser::Create(params);
-  content::WindowedNotificationObserver observer(
-      content::NOTIFICATION_LOAD_STOP,
-      content::NotificationService::AllSources());
-  chrome::AddSelectedTabWithURL(
-      popup, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK);
-  // Wait for the page to finish loading.
-  observer.Wait();
-  popup->window()->Show();
-
-  // On GTK, bounds change is asynchronous.
-  base::RunLoop().RunUntilIdle();
-
-  EnsureFindBoxOpenForBrowser(popup);
-
-  // GTK adjusts FindBar size asynchronously.
-  base::RunLoop().RunUntilIdle();
-
-  ASSERT_LE(GetFindBarWidthForBrowser(popup),
-            popup->window()->GetBounds().width());
-}
-
 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest,
                        FindMovesOnTabClose_Issue1343052) {
   EnsureFindBoxOpen();
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index 49fd1cc..0e56b3d1 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -231,8 +231,7 @@
   size_t prefix_length =
       std::min(match.keyword.length() + 1, match.fill_into_edit.length());
   extensions::ExtensionOmniboxEventRouter::OnInputEntered(
-      controller_->GetWebContents(),
-      template_url->GetExtensionId(),
+      controller_->GetWebContents(), template_url->GetExtensionId(),
       base::UTF16ToUTF8(match.fill_into_edit.substr(prefix_length)),
       disposition);
 
@@ -250,9 +249,8 @@
   }
 }
 
-void ChromeOmniboxClient::OnFocusChanged(
-    OmniboxFocusState state,
-    OmniboxFocusChangeReason reason) {
+void ChromeOmniboxClient::OnFocusChanged(OmniboxFocusState state,
+                                         OmniboxFocusChangeReason reason) {
   if (!controller_->GetWebContents())
     return;
   if (auto* helper =
@@ -418,7 +416,8 @@
         ChromeTranslateClient::FromWebContents(contents);
     if (translate_client) {
       DCHECK_NE(nullptr, translate_client->GetTranslateManager());
-      translate_client->GetTranslateManager()->InitiateManualTranslation(true);
+      translate_client->GetTranslateManager()->ShowTranslateUI(
+          /*auto_translate=*/true);
     }
   }
 }
@@ -441,8 +440,7 @@
   }
 }
 
-void ChromeOmniboxClient::DoPrerender(
-    const AutocompleteMatch& match) {
+void ChromeOmniboxClient::DoPrerender(const AutocompleteMatch& match) {
   content::WebContents* web_contents = controller_->GetWebContents();
 
   // Don't prerender when DevTools is open in this tab.
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc
index 551180e..804e283 100644
--- a/chrome/browser/ui/search/search_ipc_router.cc
+++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -361,18 +361,6 @@
   delegate_->BlocklistPromo(promo_id);
 }
 
-void SearchIPCRouter::OpenExtensionsPage(double button,
-                                         bool alt_key,
-                                         bool ctrl_key,
-                                         bool meta_key,
-                                         bool shift_key) {
-  if (!policy_->ShouldProcessOpenExtensionsPage()) {
-    return;
-  }
-
-  delegate_->OpenExtensionsPage(button, alt_key, ctrl_key, meta_key, shift_key);
-}
-
 void SearchIPCRouter::set_delegate_for_testing(Delegate* delegate) {
   DCHECK(delegate);
   delegate_ = delegate;
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h
index 13d4ecb..2d662b7 100644
--- a/chrome/browser/ui/search/search_ipc_router.h
+++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -123,12 +123,6 @@
     virtual void OnConfirmThemeChanges() = 0;
 
     virtual void BlocklistPromo(const std::string& promo_id) = 0;
-
-    virtual void OpenExtensionsPage(double button,
-                                    bool alt_key,
-                                    bool ctrl_key,
-                                    bool meta_key,
-                                    bool shift_key) = 0;
   };
 
   // An interface to be implemented by consumers of SearchIPCRouter objects to
@@ -159,7 +153,6 @@
     virtual bool ShouldProcessOptOutOfSearchSuggestions() = 0;
     virtual bool ShouldProcessThemeChangeMessages() = 0;
     virtual bool ShouldProcessBlocklistPromo() = 0;
-    virtual bool ShouldProcessOpenExtensionsPage() = 0;
   };
 
   // Creates search::mojom::EmbeddedSearchClient connections on request.
@@ -245,11 +238,6 @@
   void RevertThemeChanges() override;
   void ConfirmThemeChanges() override;
   void BlocklistPromo(const std::string& promo_id) override;
-  void OpenExtensionsPage(double button,
-                          bool alt_key,
-                          bool ctrl_key,
-                          bool meta_key,
-                          bool shift_key) override;
   void set_embedded_search_client_factory_for_testing(
       std::unique_ptr<EmbeddedSearchClientFactory> factory) {
     embedded_search_client_factory_ = std::move(factory);
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
index d154b174..f436b7a 100644
--- a/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
+++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.cc
@@ -98,7 +98,3 @@
 bool SearchIPCRouterPolicyImpl::ShouldProcessBlocklistPromo() {
   return !is_incognito_ && search::IsInstantNTP(web_contents_);
 }
-
-bool SearchIPCRouterPolicyImpl::ShouldProcessOpenExtensionsPage() {
-  return !is_incognito_ && search::IsInstantNTP(web_contents_);
-}
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_impl.h b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
index 8b4aaa5..1e711b8 100644
--- a/chrome/browser/ui/search/search_ipc_router_policy_impl.h
+++ b/chrome/browser/ui/search/search_ipc_router_policy_impl.h
@@ -46,7 +46,6 @@
   bool ShouldProcessOptOutOfSearchSuggestions() override;
   bool ShouldProcessThemeChangeMessages() override;
   bool ShouldProcessBlocklistPromo() override;
-  bool ShouldProcessOpenExtensionsPage() override;
 
   // Used by unit tests.
   void set_is_incognito(bool is_incognito) {
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index 837dc1e..a5fdbe6d 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -91,12 +91,6 @@
   MOCK_METHOD0(OnRevertThemeChanges, void());
   MOCK_METHOD0(OnConfirmThemeChanges, void());
   MOCK_METHOD1(BlocklistPromo, void(const std::string& promo_id));
-  MOCK_METHOD5(OpenExtensionsPage,
-               void(double button,
-                    bool alt_key,
-                    bool ctrl_key,
-                    bool meta_key,
-                    bool shift_key));
 };
 
 class MockSearchIPCRouterPolicy : public SearchIPCRouter::Policy {
@@ -123,7 +117,6 @@
   MOCK_METHOD0(ShouldSendLocalBackgroundSelected, bool());
   MOCK_METHOD0(ShouldProcessThemeChangeMessages, bool());
   MOCK_METHOD0(ShouldProcessBlocklistPromo, bool());
-  MOCK_METHOD0(ShouldProcessOpenExtensionsPage, bool());
 };
 
 class MockEmbeddedSearchClientFactory
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 343626c4..aeb9bea 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -15,7 +15,6 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/extensions/extension_checkup.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/chrome_colors/chrome_colors_factory.h"
@@ -63,7 +62,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
-#include "extensions/common/extension_features.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/vector_icon_types.h"
@@ -454,31 +452,6 @@
   promo_service->BlocklistPromo(promo_id);
 }
 
-void SearchTabHelper::OpenExtensionsPage(double button,
-                                         bool alt_key,
-                                         bool ctrl_key,
-                                         bool meta_key,
-                                         bool shift_key) {
-  if (!search::DefaultSearchProviderIsGoogle(profile()))
-    return;
-  base::RecordAction(base::UserMetricsAction("Extensions.NtpPromoClicked"));
-  UMA_HISTOGRAM_ENUMERATION(
-      "Extensions.Checkup.NtpPromoClicked",
-      static_cast<extensions::CheckupMessage>(
-          base::GetFieldTrialParamByFeatureAsInt(
-              extensions_features::kExtensionsCheckup,
-              extensions_features::kExtensionsCheckupBannerMessageParameter,
-              static_cast<int>(extensions::CheckupMessage::NEUTRAL))));
-
-  WindowOpenDisposition disposition =
-      (button > 1) ? WindowOpenDisposition::NEW_FOREGROUND_TAB
-                   : ui::DispositionFromClick((button == 1.0), alt_key,
-                                              ctrl_key, meta_key, shift_key);
-  web_contents_->OpenURL(content::OpenURLParams(
-      GURL(chrome::kChromeUIExtensionsURL), content::Referrer(), disposition,
-      ui::PAGE_TRANSITION_LINK, false));
-}
-
 Profile* SearchTabHelper::profile() const {
   return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
 }
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index 9c96d5ed..239d9a8 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -122,11 +122,6 @@
   void OnRevertThemeChanges() override;
   void OnConfirmThemeChanges() override;
   void BlocklistPromo(const std::string& promo_id) override;
-  void OpenExtensionsPage(double button,
-                          bool alt_key,
-                          bool ctrl_key,
-                          bool meta_key,
-                          bool shift_key) override;
 
   // Overridden from InstantServiceObserver:
   void NtpThemeChanged(const NtpTheme& theme) override;
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 44b6a10..001ba5b6 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/buildflags.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
@@ -73,7 +72,6 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -96,7 +94,6 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
-#include "extensions/common/extension_features.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -2381,112 +2378,6 @@
 
 #endif  // defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX)
 
-class StartupBrowserCreatorExtensionsCheckupExperimentTest
-    : public extensions::ExtensionBrowserTest {
- public:
-  // ExtensionsBrowserTest opens about::blank via the command line, and
-  // command-line tabs supersede all others, except pinned tabs.
-  StartupBrowserCreatorExtensionsCheckupExperimentTest() {
-    set_open_about_blank_on_browser_launch(false);
-  }
-  StartupBrowserCreatorExtensionsCheckupExperimentTest(
-      const StartupBrowserCreatorExtensionsCheckupExperimentTest&) = delete;
-  StartupBrowserCreatorExtensionsCheckupExperimentTest& operator=(
-      const StartupBrowserCreatorExtensionsCheckupExperimentTest&) = delete;
-
-  void SetUp() override {
-    // Enable the extensions checkup experiment.
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        extensions_features::kExtensionsCheckup,
-        {{extensions_features::kExtensionsCheckupEntryPointParameter,
-          extensions_features::kStartupEntryPoint}});
-    extensions::ExtensionBrowserTest::SetUp();
-  }
-
-  void AddExtension() {
-    // Adds a non policy-installed extension to the extension registry.
-    const Extension* extension =
-        LoadExtension(test_data_dir_.AppendASCII("good.crx"));
-    ASSERT_TRUE(extension);
-
-    constexpr char kGoodExtensionId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
-    extensions::ExtensionRegistry* registry =
-        extensions::ExtensionRegistry::Get(profile());
-    EXPECT_TRUE(registry->enabled_extensions().GetByID(kGoodExtensionId));
-
-    extensions::ExtensionPrefs* prefs =
-        extensions::ExtensionPrefs::Get(profile());
-    EXPECT_TRUE(prefs->GetInstalledExtensionInfo(kGoodExtensionId));
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-// Test that when the extensions checkup experiment is enabled for the startup
-// entry point and a user has extensions installed, the user is directed to the
-// chrome://extensions page upon startup.
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorExtensionsCheckupExperimentTest,
-                       PRE_ExtensionsCheckup) {
-  AddExtension();
-}
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-// TODO(https://crbug.com/1196684): enable this test on Lacros.
-#define MAYBE_ExtensionsCheckup DISABLED_ExtensionsCheckup
-#else
-#define MAYBE_ExtensionsCheckup ExtensionsCheckup
-#endif
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorExtensionsCheckupExperimentTest,
-                       MAYBE_ExtensionsCheckup) {
-  // The new browser should have exactly two tabs (chrome://extensions page and
-  // the NTP).
-  TabStripModel* tab_strip = browser()->tab_strip_model();
-  content::WebContents* extensions_tab = tab_strip->GetWebContentsAt(0);
-
-  // Check that the tab showing the extensions page is the active tab.
-  EXPECT_EQ(extensions_tab, tab_strip->GetActiveWebContents());
-
-  // Check that both the extensions page and the ntp page are shown.
-  ASSERT_EQ(2, tab_strip->count());
-  EXPECT_EQ("chrome://extensions/?checkup=shown",
-            extensions_tab->GetLastCommittedURL());
-  EXPECT_EQ(chrome::kChromeUINewTabURL,
-            tab_strip->GetWebContentsAt(1)->GetLastCommittedURL());
-
-  // Once the user sees the extensions page upon startup, they should not see it
-  // again.
-  Browser* other_browser = CreateBrowser(browser()->profile());
-
-  // Make sure we are observing a new browser instance.
-  EXPECT_NE(other_browser, browser());
-
-  TabStripModel* other_tab_strip = other_browser->tab_strip_model();
-  ASSERT_EQ(1, other_tab_strip->count());
-  EXPECT_NE("chrome://extensions/?checkup=shown",
-            other_tab_strip->GetWebContentsAt(0)->GetLastCommittedURL());
-}
-
-// Test that when the extensions checkup experiment has been shown and the
-// browser is started again, the user is not directed to the
-// chrome://extensions page upon startup.
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorExtensionsCheckupExperimentTest,
-                       PRE_ExtensionsCheckupAlreadyShown) {
-  AddExtension();
-  extensions::ExtensionPrefs::Get(profile())
-      ->SetUserHasSeenExtensionsCheckupOnStartup(true);
-}
-
-IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorExtensionsCheckupExperimentTest,
-                       ExtensionsCheckupAlreadyShown) {
-  // The new browser should have exactly one tab (the NTP).
-  TabStripModel* tab_strip = browser()->tab_strip_model();
-
-  ASSERT_EQ(1, tab_strip->count());
-  EXPECT_EQ(chrome::kChromeUINewTabURL,
-            tab_strip->GetActiveWebContents()->GetLastCommittedURL());
-}
-
 // These tests are not applicable to Chrome OS as neither initial preferences
 // nor the onboarding promos exist there.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 831d42ba..8e9d983 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/extensions/extension_checkup.h"
 #include "chrome/browser/infobars/simple_alert_infobar_creator.h"
 #include "chrome/browser/obsolete_system/obsolete_system.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
@@ -386,14 +385,10 @@
     welcome_enabled = false;
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
-  bool serve_extensions_page =
-      extensions::ShouldShowExtensionsCheckupOnStartup(profile_);
-
   StartupTabs tabs = DetermineStartupTabs(
       StartupTabProviderImpl(), cmd_line_tabs, process_startup,
       is_incognito_or_guest, is_post_crash_launch,
-      has_incompatible_applications, promotional_tabs_enabled, welcome_enabled,
-      serve_extensions_page);
+      has_incompatible_applications, promotional_tabs_enabled, welcome_enabled);
 
   // Return immediately if we start an async restore, since the remainder of
   // that process is self-contained.
@@ -446,8 +441,7 @@
     bool is_post_crash_launch,
     bool has_incompatible_applications,
     bool promotional_tabs_enabled,
-    bool welcome_enabled,
-    bool serve_extensions_page) {
+    bool welcome_enabled) {
   // Only the New Tab Page or command line URLs may be shown in incognito mode.
   // A similar policy exists for crash recovery launches, to prevent getting the
   // user stuck in a crash loop.
@@ -512,11 +506,6 @@
     // Potentially add the New Tab Page. Onboarding content is designed to
     // replace (and eventually funnel the user to) the NTP.
     if (onboarding_tabs.empty()) {
-      // Potentially show the extensions page in addition to the NTP if the user
-      // is part of the extensions checkup experiment and they have not been
-      // redirected to the extensions page upon startup before.
-      AppendTabs(provider.GetExtensionCheckupTabs(serve_extensions_page),
-                 &tabs);
       // URLs from preferences are explicitly meant to override showing the NTP.
       if (prefs_tabs.empty()) {
         AppendTabs(provider.GetNewTabPageTabs(command_line_, profile_), &tabs);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.h b/chrome/browser/ui/startup/startup_browser_creator_impl.h
index a751afd..db58ee84 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.h
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.h
@@ -95,8 +95,6 @@
                            DetermineBrowserOpenBehavior_PostCrash);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorImplTest,
                            DetermineBrowserOpenBehavior_NotStartup);
-  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorImplTest,
-                           DetermineStartupTabs_ExtensionCheckupPage);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorImplTest, ShouldLaunch);
 
   enum class WelcomeRunType {
@@ -147,8 +145,7 @@
                                    bool is_post_crash_launch,
                                    bool has_incompatible_applications,
                                    bool promotional_tabs_enabled,
-                                   bool welcome_enabled,
-                                   bool serve_extensions_page);
+                                   bool welcome_enabled);
 
   // Begins an asynchronous session restore if current state allows it (e.g.,
   // this is not process startup) and SessionService indicates that one is
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
index 5c1cc1bb..a7f3e7132 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
@@ -28,7 +28,6 @@
 constexpr uint32_t kPreferencesTabs = 1 << 4;
 constexpr uint32_t kNewTabPageTabs = 1 << 5;
 constexpr uint32_t kPostCrashTab = 1 << 6;
-constexpr uint32_t kExtensionsCheckupTabs = 1 << 7;
 
 #if defined(OS_WIN)
 constexpr uint32_t kWelcomeBackTab = 1 << 8;
@@ -105,14 +104,6 @@
     return tabs;
   }
 
-  StartupTabs GetExtensionCheckupTabs(
-      bool serve_extensions_page) const override {
-    StartupTabs tabs;
-    if (options_ & kExtensionsCheckupTabs)
-      tabs.emplace_back(GURL("https://extensions/"), false);
-    return tabs;
-  }
-
  private:
   const uint32_t options_;
 };
@@ -131,7 +122,7 @@
                chrome::startup::IS_FIRST_RUN);
 
   StartupTabs output = impl.DetermineStartupTabs(
-      provider, StartupTabs(), true, false, false, false, true, true, false);
+      provider, StartupTabs(), true, false, false, false, true, true);
   ASSERT_EQ(4U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
   EXPECT_EQ("onboarding", output[1].url.host());
@@ -140,7 +131,7 @@
 
   // No extra onboarding content for managed starts.
   output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false,
-                                     false, false, false, true, false);
+                                     false, false, false, true);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
   EXPECT_EQ("prefs", output[1].url.host());
@@ -148,7 +139,7 @@
 
   // No onboarding if not enabled even if promo is allowed.
   output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false,
-                                     false, false, true, false, false);
+                                     false, false, true, false);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
   EXPECT_EQ("prefs", output[1].url.host());
@@ -166,7 +157,7 @@
                chrome::startup::IS_FIRST_RUN);
 
   StartupTabs output = impl.DetermineStartupTabs(
-      provider, StartupTabs(), true, true, false, false, true, true, false);
+      provider, StartupTabs(), true, true, false, false, true, true);
   ASSERT_EQ(1U, output.size());
   // Check for the actual NTP URL, rather than the sentinel returned by the
   // fake, because the Provider is ignored entirely when short-circuited by
@@ -186,7 +177,7 @@
 
   // Regular Crash Recovery case:
   StartupTabs output = impl.DetermineStartupTabs(
-      provider, StartupTabs(), true, false, true, false, true, true, false);
+      provider, StartupTabs(), true, false, true, false, true, true);
   ASSERT_EQ(1U, output.size());
   // Check for the actual NTP URL, rather than the sentinel returned by the
   // fake, because the Provider is ignored entirely when short-circuited by
@@ -195,7 +186,7 @@
 
   // Crash Recovery case with problem applications:
   output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false, true,
-                                     true, true, true, false);
+                                     true, true, true);
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(GURL("https://incompatible-applications"), output[0].url);
 }
@@ -211,7 +202,7 @@
                chrome::startup::IS_FIRST_RUN);
 
   StartupTabs output = impl.DetermineStartupTabs(
-      provider, StartupTabs(), true, false, false, false, true, true, false);
+      provider, StartupTabs(), true, false, false, false, true, true);
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ("distribution", output[0].url.host());
 }
@@ -229,7 +220,7 @@
   StartupTabs cmd_line_tabs = {StartupTab(GURL("https://cmd-line"), false)};
 
   StartupTabs output = impl.DetermineStartupTabs(
-      provider, cmd_line_tabs, true, false, false, false, true, true, false);
+      provider, cmd_line_tabs, true, false, false, false, true, true);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
   EXPECT_EQ("cmd-line", output[1].url.host());
@@ -240,19 +231,19 @@
 
   // Incognito
   output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, true, false,
-                                     false, true, true, false);
+                                     false, true, true);
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ("cmd-line", output[0].url.host());
 
   // Crash Recovery
   output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, false, true,
-                                     false, true, true, false);
+                                     false, true, true);
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ("cmd-line", output[0].url.host());
 
   // Crash Recovery with incompatible applications.
   output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true, false, true,
-                                     true, true, true, false);
+                                     true, true, true);
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ("cmd-line", output[0].url.host());
 }
@@ -268,28 +259,13 @@
 
   StartupTabs output =
       impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), true, false,
-                                false, false, true, true, false);
+                                false, false, true, true);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
   EXPECT_EQ("new-tab", output[1].url.host());
   EXPECT_EQ("pinned", output[2].url.host());
 }
 
-// If the user's preferences satisfy the conditions, show the extensions page
-// upon startup.
-TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_ExtensionCheckupPage) {
-  FakeStartupTabProvider provider(kNewTabPageTabs | kExtensionsCheckupTabs);
-  Creator impl(base::FilePath(),
-               base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
-
-  StartupTabs output = impl.DetermineStartupTabs(
-      provider, StartupTabs(), true, false, false, false, true, true, true);
-  ASSERT_EQ(2U, output.size());
-  EXPECT_EQ("extensions", output[0].url.host());
-  EXPECT_EQ("new-tab", output[1].url.host());
-}
-
 #if defined(OS_WIN)
 // The welcome back page should appear before any other session restore tabs.
 TEST(StartupBrowserCreatorImplTest, DetermineStartupTabs_WelcomeBackPage) {
@@ -301,7 +277,7 @@
 
   StartupTabs output =
       impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), true, false,
-                                false, false, true, true, false);
+                                false, false, true, true);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("welcome-back", output[0].url.host());
   EXPECT_EQ("prefs", output[1].url.host());
@@ -309,14 +285,14 @@
 
   // No welcome back for non-startup opens.
   output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), false,
-                                     false, false, false, true, true, false);
+                                     false, false, false, true, true);
   ASSERT_EQ(2U, output.size());
   EXPECT_EQ("prefs", output[0].url.host());
   EXPECT_EQ("pinned", output[1].url.host());
 
   // No welcome back for managed starts even if first run.
   output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), true,
-                                     false, false, false, false, true, false);
+                                     false, false, false, false, true);
   ASSERT_EQ(2U, output.size());
   EXPECT_EQ("prefs", output[0].url.host());
   EXPECT_EQ("pinned", output[1].url.host());
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index c9ac90a..440876d5 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -138,11 +138,6 @@
   return GetPostCrashTabsForState(has_incompatible_applications);
 }
 
-StartupTabs StartupTabProviderImpl::GetExtensionCheckupTabs(
-    bool serve_extensions_page) const {
-  return GetExtensionCheckupTabsForState(serve_extensions_page);
-}
-
 // static
 bool StartupTabProviderImpl::CanShowWelcome(bool is_signin_allowed,
                                             bool is_supervised_user,
@@ -245,19 +240,6 @@
 }
 
 // static
-StartupTabs StartupTabProviderImpl::GetExtensionCheckupTabsForState(
-    bool serve_extensions_page) {
-  StartupTabs tabs;
-  if (serve_extensions_page) {
-    tabs.emplace_back(
-        net::AppendQueryParameter(GURL(chrome::kChromeUIExtensionsURL),
-                                  "checkup", "shown"),
-        false);
-  }
-  return tabs;
-}
-
-// static
 GURL StartupTabProviderImpl::GetWelcomePageUrl(bool use_later_run_variant) {
   GURL url(chrome::kChromeUIWelcomeURL);
   return use_later_run_variant
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h
index 44d10654..79c2f56 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.h
+++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -61,10 +61,6 @@
   // applications exist.
   virtual StartupTabs GetPostCrashTabs(
       bool has_incompatible_applications) const = 0;
-
-  // Returns tabs related to the extension checkup promo (if applicable).
-  virtual StartupTabs GetExtensionCheckupTabs(
-      bool serve_extensions_page) const = 0;
 };
 
 class StartupTabProviderImpl : public StartupTabProvider {
@@ -136,10 +132,6 @@
   static StartupTabs GetPostCrashTabsForState(
       bool has_incompatible_applications);
 
-  // Determines if the extensions page should be shown.
-  static StartupTabs GetExtensionCheckupTabsForState(
-      bool serve_extensions_page);
-
   // Gets the URL for the Welcome page. If |use_later_run_variant| is true, a
   // URL parameter will be appended so as to access the variant page used when
   // onboarding occurs after the first Chrome execution (e.g., when creating an
@@ -175,8 +167,6 @@
                                 Profile* profile) const override;
   StartupTabs GetPostCrashTabs(
       bool has_incompatible_applications) const override;
-  StartupTabs GetExtensionCheckupTabs(
-      bool serve_extensions_page) const override;
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_STARTUP_TAB_PROVIDER_H_
diff --git a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
index 42e867ad..7acd174 100644
--- a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
@@ -244,13 +244,3 @@
   StartupTabs output = StartupTabProviderImpl().GetOnboardingTabs(incognito);
   EXPECT_TRUE(output.empty());
 }
-
-TEST(StartupTabProviderTest, GetNewTabPageTabsForState_ExtensionsCheckup) {
-  SessionStartupPref pref_default(SessionStartupPref::Type::DEFAULT);
-
-  StartupTabs output = StartupTabProviderImpl::GetExtensionCheckupTabsForState(
-      /*serve_extensions_page=*/true);
-
-  ASSERT_EQ(1U, output.size());
-  EXPECT_EQ("chrome://extensions/?checkup=shown", output[0].url);
-}
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index 7706291..39091adb 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -32,6 +32,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/favicon_size.h"
@@ -43,7 +44,6 @@
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/menu/menu_config.h"
@@ -125,8 +125,9 @@
 
 std::unique_ptr<views::ImageView> ImageViewFromVectorIcon(
     const gfx::VectorIcon& vector_icon) {
-  return std::make_unique<views::ColorTrackingIconView>(vector_icon,
-                                                        gfx::kFaviconSize);
+  return std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+      vector_icon, ui::NativeTheme::kColorId_DefaultIconColor,
+      gfx::kFaviconSize));
 }
 
 std::unique_ptr<views::ImageView> GetIconImageViewByName(
diff --git a/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc
index a8a06d7..b662e291 100644
--- a/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc
@@ -10,9 +10,10 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/vector_icons/vector_icons.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/vector_icon_utils.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/layout/box_layout.h"
 
 namespace autofill {
@@ -66,10 +67,10 @@
   layout->set_cross_axis_alignment(
       views::BoxLayout::CrossAxisAlignment::kCenter);
 
-  AddChildView(std::make_unique<views::ColorTrackingIconView>(
-      vector_icons::kErrorIcon,
-      gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon),
-      ui::NativeTheme::kColorId_AlertSeverityHigh));
+  AddChildView(
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+          vector_icons::kErrorIcon, ui::NativeTheme::kColorId_AlertSeverityHigh,
+          gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon))));
 
   auto* label = AddChildView(std::make_unique<views::Label>(
       controller_->GetDescription(),
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
index f10be8a..bd903f8 100644
--- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
@@ -25,6 +25,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -33,7 +34,6 @@
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
@@ -389,10 +389,10 @@
       views::BoxLayout::CrossAxisAlignment::kCenter);
 
   temporary_error->SetVisible(false);
-  temporary_error->AddChildView(std::make_unique<views::ColorTrackingIconView>(
-      vector_icons::kErrorIcon,
-      gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon),
-      ui::NativeTheme::kColorId_AlertSeverityHigh));
+  temporary_error->AddChildView(
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+          vector_icons::kErrorIcon, ui::NativeTheme::kColorId_AlertSeverityHigh,
+          gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon))));
 
   auto error_label = std::make_unique<views::Label>(
       std::u16string(), ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 39ba803..8b1d6042 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -117,6 +117,7 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/drag_utils.h"
+#include "ui/views/image_model_utils.h"
 #include "ui/views/metrics.h"
 #include "ui/views/view_constants.h"
 #include "ui/views/widget/tooltip_manager.h"
@@ -1300,9 +1301,10 @@
                                       ui::NativeTheme::kColorId_MenuIconColor);
   }
 
-  button_drag_utils::SetDragImage(node->url(), node->GetTitle(),
-                                  *icon.GetImage().ToImageSkia(), &press_pt,
-                                  *widget, data);
+  button_drag_utils::SetDragImage(
+      node->url(), node->GetTitle(),
+      views::GetImageSkiaFromImageModel(icon, GetNativeTheme()), &press_pt,
+      *widget, data);
   WriteBookmarkDragData(node, data);
 }
 
diff --git a/chrome/browser/ui/views/confirm_bubble_views.cc b/chrome/browser/ui/views/confirm_bubble_views.cc
index 84fb9e1..2e9dcb5 100644
--- a/chrome/browser/ui/views/confirm_bubble_views.cc
+++ b/chrome/browser/ui/views/confirm_bubble_views.cc
@@ -86,7 +86,7 @@
   return false;
 }
 
-void ConfirmBubbleViews::OnDialogInitialized() {
+void ConfirmBubbleViews::OnWidgetInitialized() {
   GetWidget()->GetRootView()->GetViewAccessibility().OverrideDescribedBy(
       label_);
 }
diff --git a/chrome/browser/ui/views/confirm_bubble_views.h b/chrome/browser/ui/views/confirm_bubble_views.h
index 8f16d26..04fdcac 100644
--- a/chrome/browser/ui/views/confirm_bubble_views.h
+++ b/chrome/browser/ui/views/confirm_bubble_views.h
@@ -37,12 +37,10 @@
  protected:
   ~ConfirmBubbleViews() override;
 
-  // views::WidgetDelegate implementation.
+  // views::DialogDelegateView:
   std::u16string GetWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
-
-  // views::DialogDelegateView implementation.
-  void OnDialogInitialized() override;
+  void OnWidgetInitialized() override;
 
  private:
   // The model to customize this bubble view.
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index c1ff14e7..615ffe8a 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -178,16 +178,67 @@
   }
 }
 
+std::u16string GetLabelForAudioCheckbox(DesktopMediaList::Type type) {
+  switch (type) {
+    case DesktopMediaList::Type::kScreen:
+      return l10n_util::GetStringUTF16(
+          IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_SCREEN);
+    case DesktopMediaList::Type::kWindow:
+      return l10n_util::GetStringUTF16(
+          IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_WINDOW);
+    case DesktopMediaList::Type::kWebContents:
+    case DesktopMediaList::Type::kCurrentTab:
+      return l10n_util::GetStringUTF16(
+          IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TAB);
+    case DesktopMediaList::Type::kNone:
+      break;
+  }
+  NOTREACHED();
+  return u"";
+}
+
+bool AreEquivalentTypesForAudioCheckbox(DesktopMediaList::Type lhs,
+                                        DesktopMediaList::Type rhs) {
+  if (lhs == DesktopMediaList::Type::kWebContents ||
+      lhs == DesktopMediaList::Type::kCurrentTab) {
+    return rhs == DesktopMediaList::Type::kWebContents ||
+           rhs == DesktopMediaList::Type::kCurrentTab;
+  } else {
+    return lhs == rhs;
+  }
+}
+
 }  // namespace
 
+bool DesktopMediaPickerDialogView::AudioSupported(DesktopMediaList::Type type) {
+  switch (type) {
+    case DesktopMediaList::Type::kScreen:
+      return DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform;
+    case DesktopMediaList::Type::kWindow:
+      return false;
+    case DesktopMediaList::Type::kWebContents:
+    case DesktopMediaList::Type::kCurrentTab:
+      return true;
+    case DesktopMediaList::Type::kNone:
+      break;
+  }
+  NOTREACHED();
+  return false;
+}
+
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::DisplaySurfaceCategory(
     DesktopMediaList::Type type,
-    std::unique_ptr<DesktopMediaListController> controller)
-    : type(type), controller(std::move(controller)) {}
+    std::unique_ptr<DesktopMediaListController> controller,
+    bool audio_checked)
+    : type(type),
+      controller(std::move(controller)),
+      audio_checked(audio_checked) {}
 
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::DisplaySurfaceCategory(
     DesktopMediaPickerDialogView::DisplaySurfaceCategory&& other)
-    : type(other.type), controller(std::move(other.controller)) {}
+    : type(other.type),
+      controller(std::move(other.controller)),
+      audio_checked(other.audio_checked) {}
 
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::
     ~DisplaySurfaceCategory() = default;
@@ -196,7 +247,9 @@
     const DesktopMediaPicker::Params& params,
     DesktopMediaPickerViews* parent,
     std::vector<std::unique_ptr<DesktopMediaList>> source_lists)
-    : web_contents_(params.web_contents), parent_(parent) {
+    : web_contents_(params.web_contents),
+      audio_requested_(params.request_audio),
+      parent_(parent) {
   SetModalType(params.modality);
   SetButtonLabel(ui::DIALOG_BUTTON_OK,
                  l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SHARE));
@@ -208,14 +261,6 @@
       },
       this));
 
-  if (params.request_audio) {
-    std::unique_ptr<views::Checkbox> audio_share_checkbox =
-        std::make_unique<views::Checkbox>(
-            l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE));
-    audio_share_checkbox->SetChecked(params.approve_audio_by_default);
-    audio_share_checkbox_ = SetExtraView(std::move(audio_share_checkbox));
-  }
-
   const ChromeLayoutProvider* const provider = ChromeLayoutProvider::Get();
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical,
@@ -273,8 +318,9 @@
             this, std::move(source_list));
         screen_scroll_view->SetContents(list_controller->CreateView(
             kGenericScreenStyle, kSingleScreenStyle, screen_title_text));
-        categories_.emplace_back(DesktopMediaList::Type::kScreen,
-                                 std::move(list_controller));
+        categories_.emplace_back(
+            DesktopMediaList::Type::kScreen, std::move(list_controller),
+            /*audio_checked=*/params.force_audio_checkboxes_to_default_checked);
 
         screen_scroll_view->ClipHeightTo(
             kGenericScreenStyle.item_size.height(),
@@ -304,8 +350,9 @@
             this, std::move(source_list));
         window_scroll_view->SetContents(list_controller->CreateView(
             kWindowStyle, kWindowStyle, window_title_text));
-        categories_.emplace_back(DesktopMediaList::Type::kWindow,
-                                 std::move(list_controller));
+        categories_.emplace_back(
+            DesktopMediaList::Type::kWindow, std::move(list_controller),
+            /*audio_checked=*/params.force_audio_checkboxes_to_default_checked);
 
         window_scroll_view->ClipHeightTo(kWindowStyle.item_size.height(),
                                          kWindowStyle.item_size.height() * 2);
@@ -328,7 +375,8 @@
         panes.push_back(
             std::make_pair(title, list_controller->CreateTabListView(title)));
         categories_.emplace_back(DesktopMediaList::Type::kWebContents,
-                                 std::move(list_controller));
+                                 std::move(list_controller),
+                                 /*audio_checked=*/true);
         break;
       }
       case DesktopMediaList::Type::kCurrentTab: {
@@ -349,7 +397,8 @@
         window_scroll_view->SetContents(list_controller->CreateView(
             kCurrentTabStyle, kCurrentTabStyle, title));
         categories_.emplace_back(DesktopMediaList::Type::kCurrentTab,
-                                 std::move(list_controller));
+                                 std::move(list_controller),
+                                 /*audio_checked=*/true);
         window_scroll_view->ClipHeightTo(
             kCurrentTabStyle.item_size.height(),
             kCurrentTabStyle.item_size.height() * 2);
@@ -383,7 +432,10 @@
 
   DCHECK(!categories_.empty());
 
-  OnSourceTypeSwitched(0);
+  previously_selected_category_ = GetSelectedTabIndex();
+  if (audio_requested_) {
+    SetAudioCheckboxAt(previously_selected_category_);
+  }
 
   // If |params.web_contents| is set and it's not a background page then the
   // picker will be shown modal to the web contents. Otherwise the picker is
@@ -444,31 +496,46 @@
 }
 
 void DesktopMediaPickerDialogView::TabSelectedAt(int index) {
-  OnSourceTypeSwitched(index);
+  SetAudioCheckboxAt(index);
   categories_[index].controller->FocusView();
   DialogModelChanged();
+  previously_selected_category_ = index;
 }
 
-void DesktopMediaPickerDialogView::OnSourceTypeSwitched(int index) {
-  // Set whether the checkbox is visible based on the source type.
-  if (audio_share_checkbox_) {
-    switch (categories_[index].type) {
-      case DesktopMediaList::Type::kScreen:
-        audio_share_checkbox_->SetVisible(
-            DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform);
-        break;
-      case DesktopMediaList::Type::kWindow:
-        audio_share_checkbox_->SetVisible(false);
-        break;
-      case DesktopMediaList::Type::kWebContents:
-      case DesktopMediaList::Type::kCurrentTab:
-        audio_share_checkbox_->SetVisible(true);
-        break;
-      case DesktopMediaList::Type::kNone:
-        NOTREACHED();
-        break;
+void DesktopMediaPickerDialogView::SetAudioCheckboxAt(int index) {
+  if (!audio_requested_) {
+    return;
+  }
+
+  if (audio_share_checkbox_ &&
+      AudioSupported(categories_[previously_selected_category_].type)) {
+    // Store pre-change audio checkbox state.
+    // Note: Current-tab and and any-tab are both tab-based captures,
+    // and therefore share their audio checkbox's state.
+    const bool checked = audio_share_checkbox_->GetChecked();
+    for (auto& category : categories_) {
+      if (AreEquivalentTypesForAudioCheckbox(
+              category.type, categories_[previously_selected_category_].type)) {
+        category.audio_checked = checked;
+      }
     }
   }
+
+  DisplaySurfaceCategory& category = categories_[index];
+
+  if (AudioSupported(categories_[index].type)) {
+    std::unique_ptr<views::Checkbox> audio_share_checkbox =
+        std::make_unique<views::Checkbox>(
+            GetLabelForAudioCheckbox(category.type));
+    audio_share_checkbox->SetVisible(AudioSupported(category.type));
+    audio_share_checkbox->SetChecked(category.audio_checked);
+    audio_share_checkbox_ = SetExtraView(std::move(audio_share_checkbox));
+  } else {
+    if (audio_share_checkbox_) {
+      audio_share_checkbox_->SetVisible(false);
+    }
+    audio_share_checkbox_ = nullptr;
+  }
 }
 
 int DesktopMediaPickerDialogView::GetSelectedTabIndex() const {
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
index bfce8d0..84ffa53 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -71,7 +71,8 @@
   struct DisplaySurfaceCategory {
     DisplaySurfaceCategory(
         DesktopMediaList::Type type,
-        std::unique_ptr<DesktopMediaListController> controller);
+        std::unique_ptr<DesktopMediaListController> controller,
+        bool audio_checked);
 
     DisplaySurfaceCategory(DisplaySurfaceCategory&& other);
 
@@ -79,8 +80,13 @@
 
     DesktopMediaList::Type type;
     std::unique_ptr<DesktopMediaListController> controller;
+    bool audio_checked;
   };
 
+  static bool AudioSupported(DesktopMediaList::Type type);
+
+  void SetAudioCheckboxAt(int index);
+
   void OnSourceTypeSwitched(int index);
 
   int GetSelectedTabIndex() const;
@@ -91,6 +97,7 @@
   DesktopMediaList::Type GetSelectedSourceListType() const;
 
   content::WebContents* const web_contents_;
+  const bool audio_requested_;
 
   DesktopMediaPickerViews* parent_;
 
@@ -100,6 +107,7 @@
 
   views::TabbedPane* tabbed_pane_ = nullptr;
   std::vector<DisplaySurfaceCategory> categories_;
+  int previously_selected_category_ = 0;
 
   DialogSource dialog_source_;
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
index c4d2ce0..d548128 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc
@@ -38,6 +38,11 @@
   }
 }
 
+bool DesktopMediaPickerViewsTestApi::AudioSupported(
+    DesktopMediaList::Type type) const {
+  return DesktopMediaPickerDialogView::AudioSupported(type);
+}
+
 void DesktopMediaPickerViewsTestApi::FocusAudioCheckbox() {
   picker_->dialog_->audio_share_checkbox_->RequestFocus();
 }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.h
index 3da154a..c7ea14a0 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.h
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.h
@@ -32,6 +32,8 @@
 
   void set_picker(DesktopMediaPickerViews* picker) { picker_ = picker; }
 
+  bool AudioSupported(DesktopMediaList::Type type) const;
+
   void FocusAudioCheckbox();
   void PressMouseOnSourceAtIndex(size_t index, bool double_click = false);
   void PressKeyOnSourceAtIndex(size_t index, const ui::KeyEvent& event);
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
index a661dd4..2cc5706 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -57,21 +57,39 @@
   bool closed_ = false;
 };
 
-const std::vector<DesktopMediaList::Type> kSourceTypes = {
-    DesktopMediaList::Type::kScreen, DesktopMediaList::Type::kWindow,
-    DesktopMediaList::Type::kWebContents};
+std::vector<DesktopMediaList::Type> GetSourceTypes(bool prefer_current_tab) {
+  std::vector<DesktopMediaList::Type> result{
+      DesktopMediaList::Type::kScreen, DesktopMediaList::Type::kWindow,
+      DesktopMediaList::Type::kWebContents};
+  if (prefer_current_tab) {
+    result.push_back(DesktopMediaList::Type::kCurrentTab);
+  }
+  return result;
+}
 
-const std::vector<DesktopMediaID::Type> kSourceIdTypes = {
-    DesktopMediaID::TYPE_SCREEN, DesktopMediaID::TYPE_WINDOW,
-    DesktopMediaID::TYPE_WEB_CONTENTS};
+DesktopMediaID::Type GetSourceIdType(DesktopMediaList::Type type) {
+  switch (type) {
+    case DesktopMediaList::Type::kScreen:
+      return DesktopMediaID::Type::TYPE_SCREEN;
+    case DesktopMediaList::Type::kWindow:
+      return DesktopMediaID::Type::TYPE_WINDOW;
+    case DesktopMediaList::Type::kWebContents:
+    case DesktopMediaList::Type::kCurrentTab:
+      return DesktopMediaID::Type::TYPE_WEB_CONTENTS;
+    case DesktopMediaList::Type::kNone:
+      return DesktopMediaID::Type::TYPE_NONE;
+  }
+  NOTREACHED();
+  return DesktopMediaID::Type::TYPE_NONE;
+}
 
-class DesktopMediaPickerViewsTest : public testing::Test {
+class DesktopMediaPickerViewsTestBase : public testing::Test {
  public:
-  DesktopMediaPickerViewsTest() : source_types_(kSourceTypes) {}
-  explicit DesktopMediaPickerViewsTest(
+  explicit DesktopMediaPickerViewsTestBase(
       const std::vector<DesktopMediaList::Type>& source_types)
       : source_types_(source_types) {}
-  ~DesktopMediaPickerViewsTest() override = default;
+
+  ~DesktopMediaPickerViewsTestBase() override = default;
 
   void SetUp() override {
 #if defined(OS_MAC)
@@ -117,7 +135,7 @@
 
     picker_views_->Show(
         picker_params, std::move(source_lists),
-        base::BindOnce(&DesktopMediaPickerViewsTest::OnPickerDone,
+        base::BindOnce(&DesktopMediaPickerViewsTestBase::OnPickerDone,
                        base::Unretained(this)));
     widget_destroyed_waiter_ =
         std::make_unique<views::test::WidgetDestroyedWaiter>(
@@ -142,6 +160,10 @@
     return picked_id_;
   }
 
+  const std::vector<DesktopMediaList::Type>& source_types() {
+    return source_types_;
+  }
+
  protected:
   content::BrowserTaskEnvironment task_environment_;
   views::ScopedViewsTestHelper test_helper_{
@@ -157,12 +179,25 @@
   std::unique_ptr<views::test::WidgetDestroyedWaiter> widget_destroyed_waiter_;
 };
 
+class DesktopMediaPickerViewsTest : public DesktopMediaPickerViewsTestBase,
+                                    public testing::WithParamInterface<bool> {
+ public:
+  DesktopMediaPickerViewsTest()
+      : DesktopMediaPickerViewsTestBase(GetSourceTypes(GetParam())) {}
+  ~DesktopMediaPickerViewsTest() override = default;
+
+  bool PreferCurrentTab() const { return GetParam(); }
+};
+
+INSTANTIATE_TEST_SUITE_P(All, DesktopMediaPickerViewsTest, ::testing::Bool());
+
 class DesktopMediaPickerDoubleClickTest
-    : public DesktopMediaPickerViewsTest,
+    : public DesktopMediaPickerViewsTestBase,
       public testing::WithParamInterface<
           std::pair<DesktopMediaList::Type, DesktopMediaID::Type>> {
  public:
-  DesktopMediaPickerDoubleClickTest() = default;
+  DesktopMediaPickerDoubleClickTest()
+      : DesktopMediaPickerViewsTestBase(GetSourceTypes(false)) {}
 };
 
 // Regression test for https://crbug.com/1102153 and https://crbug.com/1127496
@@ -193,17 +228,16 @@
                     std::make_pair(DesktopMediaList::Type::kWebContents,
                                    DesktopMediaID::TYPE_WEB_CONTENTS)));
 
-TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledWhenWindowClosed) {
+TEST_P(DesktopMediaPickerViewsTest, DoneCallbackCalledWhenWindowClosed) {
   GetPickerDialogView()->GetWidget()->Close();
   EXPECT_EQ(content::DesktopMediaID(), WaitForPickerDone());
 }
 
-TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledOnOkButtonPressed) {
+TEST_P(DesktopMediaPickerViewsTest, DoneCallbackCalledOnOkButtonPressed) {
   const DesktopMediaID kFakeId(DesktopMediaID::TYPE_WINDOW, 222);
 
   media_lists_[DesktopMediaList::Type::kWindow]->AddSourceByFullMediaID(
       kFakeId);
-  test_api_.GetAudioShareCheckbox()->SetChecked(true);
 
   EXPECT_FALSE(
       GetPickerDialogView()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
@@ -220,10 +254,9 @@
 
 // Verifies that a MediaSourceView is selected with mouse left click and
 // original selected MediaSourceView gets unselected.
-TEST_F(DesktopMediaPickerViewsTest, SelectMediaSourceViewOnSingleClick) {
-  for (size_t i = 0; i < kSourceTypes.size(); ++i) {
-    const auto source_type = kSourceTypes[i];
-    const auto source_id_type = kSourceIdTypes[i];
+TEST_P(DesktopMediaPickerViewsTest, SelectMediaSourceViewOnSingleClick) {
+  for (const DesktopMediaList::Type source_type : source_types()) {
+    const auto source_id_type = GetSourceIdType(source_type);
 
     test_api_.SelectTabForSourceType(source_type);
     media_lists_[source_type]->AddSourceByFullMediaID(
@@ -245,11 +278,13 @@
 }
 
 // Regression test for https://crbug.com/1102153
-TEST_F(DesktopMediaPickerViewsTest, DoneCallbackNotCalledOnDoubleTap) {
+TEST_P(DesktopMediaPickerViewsTest, DoneCallbackNotCalledOnDoubleTap) {
   const DesktopMediaID kFakeId(DesktopMediaID::TYPE_SCREEN, 222);
 
   test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
-  test_api_.GetAudioShareCheckbox()->SetChecked(false);
+  if (test_api_.AudioSupported(DesktopMediaList::Type::kScreen)) {
+    test_api_.GetAudioShareCheckbox()->SetChecked(false);
+  }
 
   media_lists_[DesktopMediaList::Type::kScreen]->AddSourceByFullMediaID(
       kFakeId);
@@ -257,17 +292,16 @@
   EXPECT_FALSE(picked_id().has_value());
 }
 
-TEST_F(DesktopMediaPickerViewsTest, CancelButtonAlwaysEnabled) {
+TEST_P(DesktopMediaPickerViewsTest, CancelButtonAlwaysEnabled) {
   EXPECT_TRUE(
       GetPickerDialogView()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
 }
 
 // Verifies that the MediaSourceView is added or removed when |media_list_| is
 // updated.
-TEST_F(DesktopMediaPickerViewsTest, AddAndRemoveMediaSource) {
-  for (size_t j = 0; j < kSourceTypes.size(); j++) {
-    const auto source_type = kSourceTypes[j];
-    const auto source_id_type = kSourceIdTypes[j];
+TEST_P(DesktopMediaPickerViewsTest, AddAndRemoveMediaSource) {
+  for (const DesktopMediaList::Type source_type : source_types()) {
+    const auto source_id_type = GetSourceIdType(source_type);
 
     test_api_.SelectTabForSourceType(source_type);
     // No media source at first.
@@ -288,10 +322,9 @@
 
 // Verifies that focusing the MediaSourceView marks it selected and the
 // original selected MediaSourceView gets unselected.
-TEST_F(DesktopMediaPickerViewsTest, FocusMediaSourceViewToSelect) {
-  for (size_t i = 0; i < kSourceIdTypes.size(); ++i) {
-    const auto source_type = kSourceTypes[i];
-    const auto source_id_type = kSourceIdTypes[i];
+TEST_P(DesktopMediaPickerViewsTest, FocusMediaSourceViewToSelect) {
+  for (const DesktopMediaList::Type source_type : source_types()) {
+    const auto source_id_type = GetSourceIdType(source_type);
 
     test_api_.SelectTabForSourceType(source_type);
     media_lists_[source_type]->AddSourceByFullMediaID(
@@ -303,9 +336,11 @@
     ASSERT_TRUE(test_api_.GetSelectedSourceId().has_value());
     EXPECT_EQ(10, test_api_.GetSelectedSourceId().value());
 
-    test_api_.FocusAudioCheckbox();
-    ASSERT_TRUE(test_api_.GetSelectedSourceId().has_value());
-    EXPECT_EQ(10, test_api_.GetSelectedSourceId().value());
+    if (test_api_.AudioSupported(source_type)) {
+      test_api_.FocusAudioCheckbox();
+      ASSERT_TRUE(test_api_.GetSelectedSourceId().has_value());
+      EXPECT_EQ(10, test_api_.GetSelectedSourceId().value());
+    }
 
     test_api_.FocusSourceAtIndex(1);
     ASSERT_TRUE(test_api_.GetSelectedSourceId().has_value());
@@ -313,10 +348,9 @@
   }
 }
 
-TEST_F(DesktopMediaPickerViewsTest, OkButtonDisabledWhenNoSelection) {
-  for (size_t i = 0; i < kSourceIdTypes.size(); ++i) {
-    const auto source_type = kSourceTypes[i];
-    const auto source_id_type = kSourceIdTypes[i];
+TEST_P(DesktopMediaPickerViewsTest, OkButtonDisabledWhenNoSelection) {
+  for (const DesktopMediaList::Type source_type : source_types()) {
+    const auto source_id_type = GetSourceIdType(source_type);
 
     test_api_.SelectTabForSourceType(source_type);
     media_lists_[source_type]->AddSourceByFullMediaID(
@@ -334,25 +368,113 @@
   }
 }
 
+TEST_P(DesktopMediaPickerViewsTest, AudioCheckboxDefaultStates) {
+  if (test_api_.AudioSupported(DesktopMediaList::Type::kScreen)) {
+    test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
+    EXPECT_FALSE(test_api_.GetAudioShareCheckbox()->GetChecked());
+  }
+
+  if (test_api_.AudioSupported(DesktopMediaList::Type::kWindow)) {
+    test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWindow);
+    EXPECT_FALSE(test_api_.GetAudioShareCheckbox()->GetChecked());
+  }
+
+  if (test_api_.AudioSupported(DesktopMediaList::Type::kWebContents)) {
+    test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWebContents);
+    EXPECT_TRUE(test_api_.GetAudioShareCheckbox()->GetChecked());
+  }
+
+  if (PreferCurrentTab() &&
+      test_api_.AudioSupported(DesktopMediaList::Type::kCurrentTab)) {
+    test_api_.SelectTabForSourceType(DesktopMediaList::Type::kCurrentTab);
+    EXPECT_TRUE(test_api_.GetAudioShareCheckbox()->GetChecked());
+  }
+}
+
+TEST_P(DesktopMediaPickerViewsTest, DistinctAudioCheckboxesHaveDistinctState) {
+  DesktopMediaList::Type source_1 = DesktopMediaList::Type::kWebContents;
+  DesktopMediaList::Type source_2 = DesktopMediaList::Type::kScreen;
+
+  DCHECK(test_api_.AudioSupported(source_1));
+  if (!test_api_.AudioSupported(source_2)) {
+    return;  // Cannot run this particular variant of the test on this platform.
+  }
+
+  // Record source_1's audio state.
+  test_api_.SelectTabForSourceType(source_1);
+  const bool init_source_1_state =
+      test_api_.GetAudioShareCheckbox()->GetChecked();
+
+  // Toggle the audio state of source_2.
+  test_api_.SelectTabForSourceType(source_2);
+  const bool init_source_2_state =
+      test_api_.GetAudioShareCheckbox()->GetChecked();
+  const bool source_2_state = !init_source_2_state;
+  test_api_.GetAudioShareCheckbox()->SetChecked(source_2_state);
+  ASSERT_EQ(test_api_.GetAudioShareCheckbox()->GetChecked(), source_2_state);
+
+  // The audio state of source_1 should remain unaffected.
+  test_api_.SelectTabForSourceType(source_1);
+  ASSERT_EQ(test_api_.GetAudioShareCheckbox()->GetChecked(),
+            init_source_1_state);
+}
+
+TEST_P(DesktopMediaPickerViewsTest, CurrentTabAndAnyTabShareAudioState) {
+  DesktopMediaList::Type source_1 = DesktopMediaList::Type::kWebContents;
+  DesktopMediaList::Type source_2 = DesktopMediaList::Type::kCurrentTab;
+
+  if (!PreferCurrentTab()) {
+    return;  // Irrelevant test.
+  }
+
+  DCHECK(test_api_.AudioSupported(source_1));
+  if (!test_api_.AudioSupported(source_2)) {
+    return;  // Cannot run this particular variant of the test on this platform.
+  }
+
+  // Record source_1's audio state.
+  test_api_.SelectTabForSourceType(source_1);
+  const bool init_state = test_api_.GetAudioShareCheckbox()->GetChecked();
+
+  // source_2 should have the same audio state.
+  test_api_.SelectTabForSourceType(source_2);
+  ASSERT_EQ(test_api_.GetAudioShareCheckbox()->GetChecked(), init_state);
+
+  // Toggle source_2's audio state.
+  const bool new_state = !init_state;
+  test_api_.GetAudioShareCheckbox()->SetChecked(new_state);
+  ASSERT_EQ(test_api_.GetAudioShareCheckbox()->GetChecked(), new_state);
+
+  // source_1's audio state should be affected.
+  test_api_.SelectTabForSourceType(source_1);
+  ASSERT_EQ(test_api_.GetAudioShareCheckbox()->GetChecked(), new_state);
+}
+
 // Verifies the visible status of audio checkbox.
-TEST_F(DesktopMediaPickerViewsTest, AudioCheckboxState) {
+// This test takes it as an article of faith that no checkbox is visible
+// when GetAudioShareCheckbox() returns false.
+TEST_P(DesktopMediaPickerViewsTest, AudioCheckboxVisibility) {
   test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
   EXPECT_EQ(DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform,
-            test_api_.GetAudioShareCheckbox()->GetVisible());
+            test_api_.GetAudioShareCheckbox() != nullptr);
 
   test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWindow);
-  EXPECT_FALSE(test_api_.GetAudioShareCheckbox()->GetVisible());
+  EXPECT_FALSE(test_api_.GetAudioShareCheckbox() != nullptr);
 
   test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWebContents);
-  EXPECT_TRUE(test_api_.GetAudioShareCheckbox()->GetVisible());
+  EXPECT_TRUE(test_api_.GetAudioShareCheckbox() != nullptr);
 }
 
 // Verifies that audio share information is recorded in the ID if the checkbox
 // is checked.
-TEST_F(DesktopMediaPickerViewsTest, DoneWithAudioShare) {
+TEST_P(DesktopMediaPickerViewsTest, DoneWithAudioShare) {
   constexpr DesktopMediaID kOriginId(DesktopMediaID::TYPE_WEB_CONTENTS, 222);
-  constexpr DesktopMediaID kResultId(DesktopMediaID::TYPE_WEB_CONTENTS, 222,
-                                     true);
+
+  DesktopMediaID result_id(DesktopMediaID::TYPE_WEB_CONTENTS, 222, true);
+  if (GetParam()) {
+    // Prefer-current-tab used, and therefore disable_local_echo=true.
+    result_id.web_contents_id.disable_local_echo = true;
+  }
 
   // This matches the real workflow that when a source is generated in
   // media_list, its |audio_share| bit is not set. The bit is set by the picker
@@ -365,13 +487,11 @@
   test_api_.FocusSourceAtIndex(0);
 
   GetPickerDialogView()->AcceptDialog();
-  EXPECT_EQ(kResultId, WaitForPickerDone());
+  EXPECT_EQ(result_id, WaitForPickerDone());
 }
 
-TEST_F(DesktopMediaPickerViewsTest, OkButtonEnabledDuringAcceptSpecific) {
-  constexpr DesktopMediaID kFakeId(
-      DesktopMediaID::TYPE_SCREEN, 222,
-      DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform);
+TEST_P(DesktopMediaPickerViewsTest, OkButtonEnabledDuringAcceptSpecific) {
+  constexpr DesktopMediaID kFakeId(DesktopMediaID::TYPE_SCREEN, 222);
 
   media_lists_[DesktopMediaList::Type::kWindow]->AddSourceByFullMediaID(
       kFakeId);
@@ -385,10 +505,11 @@
 
 // Creates a single pane DesktopMediaPickerViews that only has a tab list.
 class DesktopMediaPickerViewsSingleTabPaneTest
-    : public DesktopMediaPickerViewsTest {
+    : public DesktopMediaPickerViewsTestBase {
  public:
   DesktopMediaPickerViewsSingleTabPaneTest()
-      : DesktopMediaPickerViewsTest({DesktopMediaList::Type::kWebContents}) {}
+      : DesktopMediaPickerViewsTestBase(
+            {DesktopMediaList::Type::kWebContents}) {}
   ~DesktopMediaPickerViewsSingleTabPaneTest() override = default;
 
  protected:
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
index 6f1b0d2..4e1d63e 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/views/extensions/expandable_container_view.h"
 #include "chrome/browser/ui/views/extensions/extension_permissions_view.h"
 #include "chrome/common/buildflags.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
@@ -30,6 +31,7 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_urls.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -44,6 +46,7 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/separator.h"
 #include "ui/views/controls/textarea/textarea.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
@@ -339,6 +342,10 @@
   g_install_delay_in_ms = delay_in_ms;
 }
 
+bool ExtensionInstallDialogView::IsJustificationFieldVisibleForTesting() {
+  return justification_view_ != nullptr;
+}
+
 void ExtensionInstallDialogView::ResizeWidget() {
   GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize());
 }
@@ -444,11 +451,18 @@
 
   UpdateInstallResultHistogram(false);
   prompt_->OnDialogCanceled();
-  std::move(done_callback_).Run(ExtensionInstallPrompt::Result::USER_CANCELED);
+  std::move(done_callback_)
+      .Run(ExtensionInstallPrompt::DoneCallbackPayload(
+          ExtensionInstallPrompt::Result::USER_CANCELED));
 }
 
 void ExtensionInstallDialogView::OnDialogAccepted() {
   DCHECK(done_callback_);
+  bool expect_justification =
+      prompt_->type() ==
+          ExtensionInstallPrompt::PromptType::EXTENSION_REQUEST_PROMPT &&
+      base::FeatureList::IsEnabled(features::kExtensionWorkflowJustification);
+  DCHECK(expect_justification == !!justification_view_);
 
   UpdateInstallResultHistogram(true);
   prompt_->OnDialogAccepted();
@@ -459,7 +473,13 @@
               withhold_permissions_checkbox_->GetChecked()
           ? ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED
           : ExtensionInstallPrompt::Result::ACCEPTED;
-  std::move(done_callback_).Run(result);
+
+  std::move(done_callback_)
+      .Run(ExtensionInstallPrompt::DoneCallbackPayload(
+          result,
+          justification_view_
+              ? base::UTF16ToUTF8(justification_view_->GetJustificationText())
+              : std::string()));
 }
 
 bool ExtensionInstallDialogView::IsDialogButtonEnabled(
@@ -561,7 +581,11 @@
          std::make_unique<ExpandableContainerView>(details, content_width)});
   }
 
-  if (sections.empty()) {
+  const bool is_justification_field_enabled =
+      prompt_->type() ==
+          ExtensionInstallPrompt::PromptType::EXTENSION_REQUEST_PROMPT &&
+      base::FeatureList::IsEnabled(features::kExtensionWorkflowJustification);
+  if (sections.empty() && !is_justification_field_enabled) {
     // Use a smaller margin between the title area and buttons, since there
     // isn't any content.
     set_margins(gfx::Insets(ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -584,6 +608,19 @@
       extension_info_container->AddChildView(section.contents_view.release());
   }
 
+  // Add separate section for user justification. This section isn't added to
+  // the |sections| vector since it is later referenced to extract the textfield
+  // string.
+  if (is_justification_field_enabled) {
+    std::unique_ptr<views::Separator> separator =
+        std::make_unique<views::Separator>();
+    separator->SetColor(SK_ColorTRANSPARENT);
+    extension_info_container->AddChildView(std::move(separator));
+
+    justification_view_ = extension_info_container->AddChildView(
+        std::make_unique<ExtensionJustificationView>());
+  }
+
   scroll_view_ = new views::ScrollView();
   scroll_view_->SetHorizontalScrollBarMode(
       views::ScrollView::ScrollBarMode::kDisabled);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
index 0330f82..72e0399 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -21,7 +21,6 @@
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/view.h"
 
-// Forward-declarations
 class Profile;
 
 // Modal dialog that shows when the user attempts to install an extension. Also
@@ -63,6 +62,8 @@
   ExtensionInstallPromptShowParams* GetShowParamsForTesting();
   void ClickLinkForTesting();
 
+  bool IsJustificationFieldVisibleForTesting();
+
  private:
   // Forward-declaration.
   class ExtensionJustificationView;
@@ -114,6 +115,10 @@
 
   // Checkbox used to indicate if permissions should be withheld on install.
   views::Checkbox* withhold_permissions_checkbox_;
+
+  // The justification text field view where users enter their justification for
+  // requesting an extension.
+  ExtensionJustificationView* justification_view_ = nullptr;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_INSTALL_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
index da4cf65..5ac7863 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/path_service.h"
@@ -28,6 +29,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/grit/generated_resources.h"
@@ -137,7 +139,7 @@
     std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
   ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView(
       std::make_unique<ExtensionInstallPromptShowParams>(web_contents()),
-      ExtensionInstallPrompt::DoneCallback(), std::move(prompt));
+      base::DoNothing(), std::move(prompt));
 
   // Create the modal view around the install dialog view.
   views::Widget* modal = constrained_window::CreateBrowserModalDialogViews(
@@ -752,3 +754,109 @@
 
   CloseAndWait(delegate_view->GetWidget());
 }
+
+class ExtensionInstallDialogViewRequestTest
+    : public ExtensionInstallDialogViewTestBase {
+ public:
+  ExtensionInstallDialogViewRequestTest() {
+    feature_list_.InitAndEnableFeature(
+        features::kExtensionWorkflowJustification);
+  }
+  ExtensionInstallDialogViewRequestTest(
+      const ExtensionInstallDialogViewRequestTest&) = delete;
+  ExtensionInstallDialogViewRequestTest& operator=(
+      const ExtensionInstallDialogViewRequestTest&) = delete;
+
+ protected:
+  ExtensionInstallDialogView* CreateAndShowRequestPrompt(
+      ExtensionInstallPromptTestHelper* helper) {
+    PermissionMessages permissions;
+    permissions.push_back(
+        PermissionMessage(u"Permission message", PermissionIDSet()));
+    std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt =
+        CreatePrompt(ExtensionInstallPrompt::EXTENSION_REQUEST_PROMPT);
+    prompt->AddPermissionMessages(permissions);
+
+    auto dialog = std::make_unique<ExtensionInstallDialogView>(
+        std::make_unique<ExtensionInstallPromptShowParams>(web_contents()),
+        helper->GetCallback(), std::move(prompt));
+    ExtensionInstallDialogView* delegate_view = dialog.get();
+
+    views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
+        dialog.release(), nullptr,
+        platform_util::GetViewForWindow(
+            browser()->window()->GetNativeWindow()));
+    modal_dialog->Show();
+
+    return delegate_view;
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewRequestTest, NotifyDelegate) {
+  {
+    // User presses request. Note that we have to wait for the 0ms delay for
+    // the request button to become enabled, hence the RunLoop later.
+    ExtensionInstallDialogView::SetInstallButtonDelayForTesting(0);
+    ExtensionInstallPromptTestHelper helper;
+    ExtensionInstallDialogView* delegate_view =
+        CreateAndShowRequestPrompt(&helper);
+    EXPECT_TRUE(delegate_view->IsJustificationFieldVisibleForTesting());
+
+    base::RunLoop().RunUntilIdle();
+    delegate_view->AcceptDialog();
+    EXPECT_EQ(ExtensionInstallPrompt::Result::ACCEPTED, helper.result());
+    EXPECT_EQ(std::string(), helper.justification());
+  }
+  {
+    // User presses cancel.
+    ExtensionInstallPromptTestHelper helper;
+    ExtensionInstallDialogView* delegate_view =
+        CreateAndShowRequestPrompt(&helper);
+    EXPECT_TRUE(delegate_view->IsJustificationFieldVisibleForTesting());
+    delegate_view->CancelDialog();
+    EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, helper.result());
+    EXPECT_EQ(std::string(), helper.justification());
+  }
+  {
+    // Dialog is closed without the user explicitly choosing to proceed or
+    // cancel.
+    ExtensionInstallPromptTestHelper helper;
+    ExtensionInstallDialogView* delegate_view =
+        CreateAndShowRequestPrompt(&helper);
+    EXPECT_TRUE(delegate_view->IsJustificationFieldVisibleForTesting());
+    // Note that the close button isn't present, but the dialog can still be
+    // closed this way using Esc.
+    EXPECT_FALSE(delegate_view->ShouldShowCloseButton());
+    CloseAndWait(delegate_view->GetWidget());
+    // TODO(devlin): Should this be ABORTED?
+    EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, helper.result());
+    EXPECT_EQ(std::string(), helper.justification());
+  }
+}
+
+// Verifies that the "Request" button is disabled initially, but re-enabled
+// after a short time delay.
+IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewRequestTest,
+                       RequestButtonDelay) {
+  ExtensionInstallDialogView::SetInstallButtonDelayForTesting(0);
+  ExtensionInstallPromptTestHelper helper;
+  ExtensionInstallDialogView* delegate_view =
+      CreateAndShowRequestPrompt(&helper);
+
+  // Check that dialog and justification textfield are visible.
+  EXPECT_TRUE(delegate_view->GetVisible());
+  EXPECT_TRUE(delegate_view->IsJustificationFieldVisibleForTesting());
+
+  // Check initial button states.
+  EXPECT_FALSE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+  EXPECT_TRUE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_CANCEL));
+
+  // Check OK button state after timeout to verify that it is re-enabled.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(delegate_view->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK));
+
+  CloseAndWait(delegate_view->GetWidget());
+}
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_supervised_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_supervised_browsertest.cc
index 6602ba8..22e579c 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_supervised_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_supervised_browsertest.cc
@@ -126,7 +126,7 @@
       ExtensionInstallPrompt::GetDefaultShowDialogCallback());
   run_loop.Run();
   EXPECT_EQ(ExtensionInstallPrompt::Result::ACCEPTED, helper.result());
-  helper.ClearResultForTesting();
+  helper.ClearPayloadForTesting();
 
   histogram_tester.ExpectUniqueSample(SupervisedUserExtensionsMetricsRecorder::
                                           kExtensionInstallDialogHistogramName,
@@ -178,7 +178,7 @@
       ExtensionInstallPrompt::GetDefaultShowDialogCallback());
   run_loop.Run();
   EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, helper.result());
-  helper.ClearResultForTesting();
+  helper.ClearPayloadForTesting();
 
   histogram_tester.ExpectUniqueSample(SupervisedUserExtensionsMetricsRecorder::
                                           kExtensionInstallDialogHistogramName,
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc b/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc
index 34a4283..22ef95f 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc
@@ -183,15 +183,6 @@
       gfx::Size(width, extensions_container_->height()));
 }
 
-ToolbarActionsBar* ExtensionsMenuTestUtil::GetToolbarActionsBar() {
-  // TODO(https://crbug.com/984654): There is no associated ToolbarActionsBar
-  // with the ExtensionsMenu implementation. We should audit call sites, and
-  // determine whether the functionality is specific to the old implementation,
-  // or if callers should be updated to use the ExtensionsContainer interface.
-  NOTREACHED();
-  return nullptr;
-}
-
 ExtensionsContainer* ExtensionsMenuTestUtil::GetExtensionsContainer() {
   return extensions_container_;
 }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_test_util.h b/chrome/browser/ui/views/extensions/extensions_menu_test_util.h
index 31a12ce..8b6e968 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_test_util.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_test_util.h
@@ -38,7 +38,6 @@
   bool HasPopup() override;
   bool HidePopup() override;
   void SetWidth(int width) override;
-  ToolbarActionsBar* GetToolbarActionsBar() override;
   ExtensionsContainer* GetExtensionsContainer() override;
   void WaitForExtensionsContainerLayout() override;
   std::unique_ptr<ExtensionActionTestHelper> CreateOverflowBar(
diff --git a/chrome/browser/ui/views/find_bar_host.cc b/chrome/browser/ui/views/find_bar_host.cc
index fd601ed..0a48d7e9 100644
--- a/chrome/browser/ui/views/find_bar_host.cc
+++ b/chrome/browser/ui/views/find_bar_host.cc
@@ -37,13 +37,6 @@
 gfx::Rect GetLocationForFindBarView(gfx::Rect view_location,
                                     const gfx::Rect& dialog_bounds,
                                     const gfx::Rect& avoid_overlapping_rect) {
-  if (base::i18n::IsRTL()) {
-    int boundary = dialog_bounds.width() - view_location.width();
-    view_location.set_x(std::min(view_location.x(), boundary));
-  } else {
-    view_location.set_x(std::max(view_location.x(), dialog_bounds.x()));
-  }
-
   gfx::Rect new_pos = view_location;
 
   // The minimum space between the FindInPage window and the search result.
@@ -309,12 +302,8 @@
   // Ask the view how large an area it needs to draw on.
   gfx::Size prefsize = view()->GetPreferredSize();
 
-  // Limit width to the available area.
-  gfx::Insets insets = view()->GetInsets();
-  prefsize.set_width(
-      std::min(prefsize.width(), widget_bounds.width() + insets.width()));
-
   // Don't show the find bar if |widget_bounds| is not tall enough to fit.
+  gfx::Insets insets = view()->GetInsets();
   if (widget_bounds.height() < prefsize.height() - insets.height())
     return gfx::Rect();
 
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index b4b80e6..7d1af03 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -645,13 +645,14 @@
         web_app_frame_toolbar_->GetPreferredSize().width();
   }
 
+  auto insets = FrameBorderInsets(/*restored=*/false);
+
   caption_button_placeholder_container_->SetBounds(
-      container_x, FrameBorderInsets(/*restored=*/false).top(),
-      minimum_size_for_buttons_, height);
+      container_x, insets.top(), minimum_size_for_buttons_ - insets.width(),
+      height);
 
   web_app_frame_toolbar_->LayoutForWindowControlsOverlay(
-      gfx::Rect(x, FrameBorderInsets(/*restored=*/false).top(),
-                web_app_frame_toolbar_view_width, height));
+      gfx::Rect(x, insets.top(), web_app_frame_toolbar_view_width, height));
 
   int bounding_rect_width =
       web_app_frame_toolbar_->bounds().x() - available_space_leading_x_;
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc
index 38cc893..58a34bf 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.cc
+++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -136,7 +136,7 @@
   set_close_on_deactivate(error_->ShouldCloseOnDeactivate());
 }
 
-void GlobalErrorBubbleView::OnDialogInitialized() {
+void GlobalErrorBubbleView::OnWidgetInitialized() {
   views::LabelButton* ok_button = GetOkButton();
   if (ok_button && error_ && error_->ShouldAddElevationIconToAcceptButton()) {
     elevation_icon_setter_ = std::make_unique<ElevationIconSetter>(
diff --git a/chrome/browser/ui/views/global_error_bubble_view.h b/chrome/browser/ui/views/global_error_bubble_view.h
index 94acb5da..9889187 100644
--- a/chrome/browser/ui/views/global_error_bubble_view.h
+++ b/chrome/browser/ui/views/global_error_bubble_view.h
@@ -28,11 +28,11 @@
   GlobalErrorBubbleView& operator=(const GlobalErrorBubbleView&) = delete;
   ~GlobalErrorBubbleView() override;
 
-  // views::BubbleDialogDelegateView implementation.
+  // views::BubbleDialogDelegateView:
   void Init() override;
-  void OnDialogInitialized() override;
+  void OnWidgetInitialized() override;
 
-  // GlobalErrorBubbleViewBase implementation.
+  // GlobalErrorBubbleViewBase:
   void CloseBubbleView() override;
 
  private:
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
index c340b78..8d91136 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
@@ -30,13 +30,13 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_impl.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/throbber.h"
 #include "ui/views/layout/box_layout.h"
@@ -74,8 +74,10 @@
     return CreatePrimaryIconView(gfx::CreateVectorIcon(
         kGenericStopIcon, kPrimaryIconSize, gfx::kGoogleBlue500));
   } else if (sink.issue) {
-    auto icon = std::make_unique<views::ColorTrackingIconView>(
-        ::vector_icons::kInfoOutlineIcon, kPrimaryIconSize);
+    auto icon =
+        std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+            ::vector_icons::kInfoOutlineIcon,
+            ui::NativeTheme::kColorId_DefaultIconColor, kPrimaryIconSize));
     icon->SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder));
     return icon;
   } else if (sink.state == UIMediaSinkState::CONNECTING ||
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
index 332d5ba..e33245ef 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
@@ -98,10 +98,13 @@
     }
 
     views::View* anchor_view = nullptr;
+    Profile* profile =
+        use_off_the_record_profile_
+            ? profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true)
+            : profile_;
     if (is_version_two_) {
       auto* bubble = new PageInfoNewBubbleView(
-          anchor_view, gfx::Rect(), parent_, profile_, web_contents_,
-          GURL(kUrl),
+          anchor_view, gfx::Rect(), parent_, profile, web_contents_, GURL(kUrl),
           base::BindOnce(&PageInfoBubbleViewTestApi::OnPageInfoBubbleClosed,
                          base::Unretained(this), run_loop_.QuitClosure()));
       presenter_ = bubble->presenter_.get();
@@ -111,8 +114,7 @@
           &static_cast<PageInfoMainView*>(current_view())->selector_rows_;
     } else {
       auto* bubble = new PageInfoBubbleView(
-          anchor_view, gfx::Rect(), parent_, profile_, web_contents_,
-          GURL(kUrl),
+          anchor_view, gfx::Rect(), parent_, profile, web_contents_, GURL(kUrl),
           base::BindOnce(&PageInfoBubbleViewTestApi::OnPageInfoBubbleClosed,
                          base::Unretained(this), run_loop_.QuitClosure()));
       presenter_ = bubble->presenter_.get();
@@ -155,6 +157,12 @@
         PageInfoViewFactory::VIEW_ID_PAGE_INFO_SECURITY_DETAILS_LABEL));
   }
 
+  views::LabelButton* reset_permissions_button() {
+    DCHECK(is_version_two_);
+    return static_cast<views::LabelButton*>(bubble_delegate_->GetViewByID(
+        PageInfoViewFactory::VIEW_ID_PAGE_INFO_RESET_PERMISSIONS_BUTTON));
+  }
+
   PageInfoNavigationHandler* navigation_handler() {
     DCHECK(is_version_two_);
     return navigation_handler_;
@@ -174,11 +182,12 @@
 
   views::ToggleButton* GetToggleViewAt(int index) {
     DCHECK(is_version_two_);
-    const int kToggleViewIndex = 2;
-    return static_cast<views::ToggleButton*>(
-        GetPermissionToggleRowAt(index)
-            ->row_view_for_testing()
-            ->children()[kToggleViewIndex]);
+    return GetPermissionToggleRowAt(index)->toggle_button_;
+  }
+
+  views::Label* GetStateLabelAt(int index) {
+    DCHECK(is_version_two_);
+    return GetPermissionToggleRowAt(index)->state_label_;
   }
 
   // Returns the number of cookies shown on the link or button to open the
@@ -206,10 +215,9 @@
   }
 
   std::u16string GetPermissionLabelTextAt(int index) {
-    return is_version_two_ ? GetPermissionToggleRowAt(index)
-                                 ->row_view_for_testing()
-                                 ->title_->GetText()
-                           : GetPermissionSelectorAt(index)->label_->GetText();
+    return is_version_two_
+               ? GetPermissionToggleRowAt(index)->row_view_->title_->GetText()
+               : GetPermissionSelectorAt(index)->label_->GetText();
   }
 
   std::u16string GetPermissionComboboxTextAt(int index) {
@@ -277,6 +285,11 @@
 
   void WaitForBubbleClose() { run_loop_.Run(); }
 
+  void SetOffTheRecordProfile() {
+    use_off_the_record_profile_ = true;
+    CreateView();
+  }
+
  private:
   void OnPageInfoBubbleClosed(base::RepeatingCallback<void()> quit_closure,
                               views::Widget::ClosedReason closed_reason,
@@ -301,6 +314,7 @@
   absl::optional<bool> reload_prompt_;
   absl::optional<views::Widget::ClosedReason> closed_reason_;
   bool is_version_two_;
+  bool use_off_the_record_profile_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleViewTestApi);
 };
@@ -477,6 +491,9 @@
   // Initially, no permissions are shown because they are all set to default.
   size_t num_expected_children = 0;
   EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
+  if (is_page_info_v2_enabled()) {
+    EXPECT_FALSE(api_->reset_permissions_button());
+  }
 
   num_expected_children += is_page_info_v2_enabled()
                                ? list.size()
@@ -486,6 +503,9 @@
   EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
 
   if (is_page_info_v2_enabled()) {
+    EXPECT_TRUE(api_->reset_permissions_button()->GetVisible());
+    EXPECT_TRUE(api_->reset_permissions_button()->GetEnabled());
+    EXPECT_EQ(u"Reset permission", api_->reset_permissions_button()->GetText());
     PermissionToggleRowView* toggle_view = api_->GetPermissionToggleRowAt(0);
     EXPECT_TRUE(toggle_view);
   } else {
@@ -524,7 +544,19 @@
     EXPECT_EQ(u"Allow", api_->GetPermissionComboboxTextAt(0));
   }
 
-  if (!is_page_info_v2_enabled()) {
+  if (is_page_info_v2_enabled()) {
+    const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                               ui::EventTimeForNow(), 0, 0);
+    views::test::ButtonTestApi(api_->reset_permissions_button())
+        .NotifyClick(event);
+    // After resetting permissions, button doesn't disappear but is disabled.
+    EXPECT_TRUE(api_->reset_permissions_button()->GetVisible());
+    EXPECT_FALSE(api_->reset_permissions_button()->GetEnabled());
+
+    // In the ask state, the toggle is in the off state, indicating that
+    // permission isn't granted.
+    EXPECT_FALSE(api_->GetPermissionToggleIsOnAt(0));
+  } else {
     // User cannot set permission to default on the main page in the v2.
     // Setting to the default via the UI should keep the button around.
     api_->SimulateUserSelectingComboboxItemAt(0, 0);
@@ -542,6 +574,82 @@
   EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
 }
 
+// Test resetting blocked in Incognito permission.
+TEST_P(PageInfoBubbleViewTest, ResetBlockedInIncognitoPermission) {
+  if (!is_page_info_v2_enabled()) {
+    return;
+  }
+
+  api_->SetOffTheRecordProfile();
+
+  PermissionInfoList list(1);
+  list.back().type = ContentSettingsType::NOTIFICATIONS;
+  list.back().source = content_settings::SETTING_SOURCE_POLICY;
+  list.back().setting = CONTENT_SETTING_BLOCK;
+
+  // Initially, no permissions are shown because they are all set to default.
+  size_t num_expected_children = 0;
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
+  EXPECT_FALSE(api_->reset_permissions_button());
+
+  num_expected_children = list.size();
+  api_->SetPermissionInfo(list);
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
+
+  // Because permission is autoblocked, no reset button initially is shown.
+  EXPECT_FALSE(api_->reset_permissions_button()->GetVisible());
+  EXPECT_FALSE(api_->reset_permissions_button()->GetEnabled());
+
+  // Autoblocked permissions don't have toggles or state labels.
+  EXPECT_FALSE(api_->GetToggleViewAt(0));
+  EXPECT_FALSE(api_->GetStateLabelAt(0));
+
+  // Verify labels match the settings on the PermissionInfoList.
+  EXPECT_EQ(u"Notifications", api_->GetPermissionLabelTextAt(0));
+
+  PageInfo::PermissionInfo window_placement_permission;
+  window_placement_permission.type = ContentSettingsType::WINDOW_PLACEMENT;
+  window_placement_permission.setting = CONTENT_SETTING_ALLOW;
+  window_placement_permission.default_setting = CONTENT_SETTING_ASK;
+  window_placement_permission.source = content_settings::SETTING_SOURCE_USER;
+  list.push_back(window_placement_permission);
+
+  num_expected_children = list.size();
+  api_->SetPermissionInfo(list);
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(num_expected_children));
+
+  // Because a non-managed permission was added, reset button is visible and
+  // enabled.
+  EXPECT_TRUE(api_->reset_permissions_button()->GetVisible());
+  EXPECT_TRUE(api_->reset_permissions_button()->GetEnabled());
+  // Although there are only one resettable permission, multiple rows are
+  // shown. Because of that use plural version of the "permission" word.
+  EXPECT_EQ(u"Reset permissions", api_->reset_permissions_button()->GetText());
+
+  // User managed permissions have toggles. |camera_permission| is allowed and
+  // the toggle must be on.
+  EXPECT_TRUE(api_->GetToggleViewAt(1));
+  EXPECT_TRUE(api_->GetPermissionToggleIsOnAt(1));
+
+  const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                             ui::EventTimeForNow(), 0, 0);
+  views::test::ButtonTestApi(api_->reset_permissions_button())
+      .NotifyClick(event);
+  // After resetting permissions, button doesn't disappear but is disabled.
+  EXPECT_TRUE(api_->reset_permissions_button()->GetVisible());
+  EXPECT_FALSE(api_->reset_permissions_button()->GetEnabled());
+
+  // Show state label for user managed permission, indicating that permission
+  // is in the default ask state now. Autoblocked permission doesn't change.
+  EXPECT_FALSE(api_->GetStateLabelAt(0));
+  EXPECT_EQ(u"Can ask to open and place windows on your screens",
+            api_->GetStateLabelAt(1)->GetText());
+
+  // In the ask state, the toggle is in the off state, indicating that
+  // permission isn't granted.
+  EXPECT_FALSE(api_->GetPermissionToggleIsOnAt(1));
+}
+
 // Test UI construction and reconstruction with USB devices.
 TEST_P(PageInfoBubbleViewTest, SetPermissionInfoWithUsbDevice) {
   if (!is_page_info_v2_enabled()) {
@@ -583,6 +691,54 @@
   EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
 }
 
+// Test resetting USB devices permission.
+TEST_P(PageInfoBubbleViewTest, ResetPermissionInfoWithUsbDevice) {
+  if (!is_page_info_v2_enabled()) {
+    return;
+  }
+
+  constexpr size_t kExpectedChildren = 0;
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(kExpectedChildren));
+  EXPECT_FALSE(api_->reset_permissions_button());
+
+  const auto origin = url::Origin::Create(GURL(kUrl));
+
+  // Connect the UsbChooserContext with FakeUsbDeviceManager.
+  device::FakeUsbDeviceManager usb_device_manager;
+  mojo::PendingRemote<device::mojom::UsbDeviceManager> usb_manager;
+  usb_device_manager.AddReceiver(usb_manager.InitWithNewPipeAndPassReceiver());
+  UsbChooserContext* store =
+      UsbChooserContextFactory::GetForProfile(web_contents_helper_->profile());
+  store->SetDeviceManagerForTesting(std::move(usb_manager));
+
+  auto device_info = usb_device_manager.CreateAndAddDevice(
+      0, 0, "Google", "Gizmo", "1234567890");
+  store->GrantDevicePermission(origin, *device_info);
+
+  PermissionInfoList list;
+  api_->SetPermissionInfo(list);
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(kExpectedChildren + 1));
+  EXPECT_TRUE(api_->reset_permissions_button()->GetVisible());
+  EXPECT_TRUE(api_->reset_permissions_button()->GetEnabled());
+  EXPECT_EQ(u"Reset permission", api_->reset_permissions_button()->GetText());
+
+  const auto& chosen_object_children = api_->GetChosenObjectChildren();
+  EXPECT_EQ(3u, chosen_object_children.size());
+
+  views::Label* label = GetChosenObjectTitle(chosen_object_children);
+  EXPECT_EQ(u"Gizmo", label->GetText());
+
+  const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                             ui::EventTimeForNow(), 0, 0);
+  views::test::ButtonTestApi(api_->reset_permissions_button())
+      .NotifyClick(event);
+  api_->SetPermissionInfo(list);
+  EXPECT_TRUE(api_->ValidatePermissionsChildrenCount(kExpectedChildren));
+  EXPECT_EQ(api_->permissions_view()->children().size(), 0u);
+  EXPECT_FALSE(api_->reset_permissions_button());
+  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
+}
+
 namespace {
 
 constexpr char kWebUsbPolicySetting[] = R"(
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc
index c3c8d321f..790865b 100644
--- a/chrome/browser/ui/views/page_info/page_info_main_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc
@@ -235,6 +235,8 @@
   reset_button_->SetProperty(
       views::kMarginsKey,
       gfx::Insets(controls_spacing, side_offset, controls_spacing, 0));
+  reset_button_->SetID(
+      PageInfoViewFactory::VIEW_ID_PAGE_INFO_RESET_PERMISSIONS_BUTTON);
 
   // If a permission is in a non-default state or chooser object is present,
   // show reset button.
@@ -250,7 +252,12 @@
   reset_button_->SetEnabled(false);
   int num_permissions = 0;
   for (const auto& permission : permission_info_list) {
-    if (permission.setting != CONTENT_SETTING_DEFAULT) {
+    const bool is_permission_user_managed =
+        permission.source == content_settings::SETTING_SOURCE_USER &&
+        (ui_delegate_->ShouldShowAllow(permission.type) ||
+         ui_delegate_->ShouldShowAsk(permission.type));
+    if (is_permission_user_managed &&
+        permission.setting != CONTENT_SETTING_DEFAULT) {
       reset_button_->SetEnabled(true);
       reset_button_->SetVisible(true);
     }
diff --git a/chrome/browser/ui/views/page_info/page_info_new_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_new_bubble_view.cc
index ae3591f21..36a1829 100644
--- a/chrome/browser/ui/views/page_info/page_info_new_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_new_bubble_view.cc
@@ -68,10 +68,14 @@
 }
 
 void PageInfoNewBubbleView::OpenSecurityPage() {
+  presenter_->RecordPageInfoAction(
+      PageInfo::PageInfoAction::PAGE_INFO_SECURITY_DETAILS_OPENED);
   page_container_->SwitchToPage(view_factory_->CreateSecurityPageView());
 }
 
 void PageInfoNewBubbleView::OpenPermissionPage(ContentSettingsType type) {
+  presenter_->RecordPageInfoAction(
+      PageInfo::PageInfoAction::PAGE_INFO_PERMISSION_DIALOG_OPENED);
   page_container_->SwitchToPage(view_factory_->CreatePermissionPageView(type));
 }
 
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.h b/chrome/browser/ui/views/page_info/page_info_view_factory.h
index 7958f99..f44b04b 100644
--- a/chrome/browser/ui/views/page_info/page_info_view_factory.h
+++ b/chrome/browser/ui/views/page_info/page_info_view_factory.h
@@ -44,6 +44,7 @@
     VIEW_ID_PAGE_INFO_BACK_BUTTON,
     VIEW_ID_PAGE_INFO_CLOSE_BUTTON,
     VIEW_ID_PAGE_INFO_CURRENT_VIEW,
+    VIEW_ID_PAGE_INFO_RESET_PERMISSIONS_BUTTON,
   };
 
   // Creates a separator view with padding on top and bottom. Use with flex
diff --git a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc
index 5ac922b..68770db 100644
--- a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc
+++ b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc
@@ -113,6 +113,7 @@
         IDS_PAGE_INFO_PERMISSIONS_SUBPAGE_BUTTON_TOOLTIP));
     views::InstallCircleHighlightPathGenerator(subpage_button.get());
     subpage_button->SetMinimumImageSize({icon_size, icon_size});
+    subpage_button->SetFlipCanvasOnPaintForRTLUI(false);
     row_view_->AddControl(std::move(subpage_button));
   } else {
     // If there is a permission that supports one time grants, offset all other
@@ -163,13 +164,17 @@
     state_label_ = nullptr;
   }
 
-  // Add explanation for the permission state if needed. This would be shown
-  // if permission is in allowed once or default states or if it is
+  // Add explanation for the user-managed permission state if needed. This would
+  // be shown if permission is in allowed once or default states or if it is
   // automatically blocked.
-  std::u16string state_text =
-      PageInfoUI::PermissionMainPageStateToUIString(delegate_, permission_);
-  if (!state_text.empty()) {
-    state_label_ = row_view_->AddSecondaryLabel(state_text);
+  if (permission_.source == content_settings::SETTING_SOURCE_USER &&
+      (delegate_->ShouldShowAllow(permission_.type) ||
+       delegate_->ShouldShowAsk(permission_.type))) {
+    std::u16string state_text =
+        PageInfoUI::PermissionMainPageStateToUIString(delegate_, permission_);
+    if (!state_text.empty()) {
+      state_label_ = row_view_->AddSecondaryLabel(state_text);
+    }
   }
 }
 
diff --git a/chrome/browser/ui/views/page_info/permission_toggle_row_view.h b/chrome/browser/ui/views/page_info/permission_toggle_row_view.h
index 7395c36..ddea35a 100644
--- a/chrome/browser/ui/views/page_info/permission_toggle_row_view.h
+++ b/chrome/browser/ui/views/page_info/permission_toggle_row_view.h
@@ -18,6 +18,10 @@
 class ToggleButton;
 }  // namespace views
 
+namespace test {
+class PageInfoBubbleViewTestApi;
+}  // namespace test
+
 // A view that shows a permission that a site is able to access, and
 // allows the user to control via toggle whether that access is granted. Has a
 // button that opens a subpage with more controls.
@@ -36,9 +40,9 @@
   void PermissionChanged();
   void ResetPermission();
 
-  PageInfoRowView* row_view_for_testing() { return row_view_; }
-
  private:
+  friend class test::PageInfoBubbleViewTestApi;
+
   void OnToggleButtonPressed();
   void InitForUserSource(bool should_show_spacer_view);
   void InitForManagedSource(ChromePageInfoUiDelegate* delegate);
diff --git a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
index 971ef12..f5c8f19 100644
--- a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
@@ -20,6 +20,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
@@ -30,7 +31,7 @@
 #include "ui/gfx/text_constants.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/layout_provider.h"
@@ -231,8 +232,10 @@
 
   from_view = AddChildView(std::move(from_image));
 
-  auto arrow_view = std::make_unique<views::ColorTrackingIconView>(
-      kChevronRightIcon, gfx::kFaviconSize);
+  auto arrow_view =
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+          kChevronRightIcon, ui::NativeTheme::kColorId_DefaultIconColor,
+          gfx::kFaviconSize));
   arrow_view->SetFlipCanvasOnPaintForRTLUI(true);
   AddChildView(std::move(arrow_view));
 
diff --git a/chrome/browser/ui/views/passwords/password_items_view.cc b/chrome/browser/ui/views/passwords/password_items_view.cc
index d02457d..cf944b01 100644
--- a/chrome/browser/ui/views/passwords/password_items_view.cc
+++ b/chrome/browser/ui/views/passwords/password_items_view.cc
@@ -23,6 +23,7 @@
 #include "components/password_manager/core/common/password_manager_ui.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/models/simple_combobox_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/favicon_size.h"
@@ -35,7 +36,6 @@
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/md_text_button.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
@@ -195,8 +195,10 @@
 
   if (parent_->favicon_.IsEmpty()) {
     // Use a globe fallback until the actual favicon is loaded.
-    layout->AddView(std::make_unique<views::ColorTrackingIconView>(
-        kGlobeIcon, gfx::kFaviconSize));
+    layout->AddView(
+        std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+            kGlobeIcon, ui::NativeTheme::kColorId_DefaultIconColor,
+            gfx::kFaviconSize)));
   } else {
     layout->AddView(std::make_unique<views::ImageView>())
         ->SetImage(parent_->favicon_.AsImageSkia());
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
index 8bedfb1..516198b 100644
--- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -41,6 +41,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
@@ -52,7 +53,6 @@
 #include "ui/gfx/vector_icon_utils.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/md_text_button.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/styled_label.h"
@@ -279,9 +279,11 @@
   std::unique_ptr<PaymentRequestRowView> CreateWithChevron(
       std::unique_ptr<views::View> content_view,
       std::unique_ptr<views::View> extra_content_view) {
-    auto chevron = std::make_unique<views::ColorTrackingIconView>(
-        vector_icons::kSubmenuArrowIcon,
-        gfx::GetDefaultSizeOfVectorIcon(vector_icons::kSubmenuArrowIcon));
+    auto chevron =
+        std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+            vector_icons::kSubmenuArrowIcon,
+            ui::NativeTheme::kColorId_DefaultIconColor,
+            gfx::GetDefaultSizeOfVectorIcon(vector_icons::kSubmenuArrowIcon)));
     chevron->SetCanProcessEventsWithinSubtree(false);
     std::unique_ptr<PaymentRequestRowView> section = CreatePaymentSheetRow(
         GetPressedCallback(), section_name_, accessible_content_,
diff --git a/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc b/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc
index 769d552..d12e2da 100644
--- a/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc
+++ b/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc
@@ -20,9 +20,9 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/text_elider.h"
 #include "ui/views/controls/button/checkbox.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/flex_layout.h"
@@ -74,10 +74,11 @@
 
   // File icon.
   auto checkbox = std::make_unique<views::Checkbox>();
-  auto* icon =
-      files_view->AddChildView(std::make_unique<views::ColorTrackingIconView>(
+  auto* icon = files_view->AddChildView(
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
           vector_icons::kDescriptionIcon,
-          checkbox->GetImage(views::Button::STATE_NORMAL).width()));
+          ui::NativeTheme::kColorId_DefaultIconColor,
+          checkbox->GetImage(views::Button::STATE_NORMAL).width())));
   const int icon_margin = views::LayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_RELATED_LABEL_HORIZONTAL);
   icon->SetProperty(views::kMarginsKey, gfx::Insets(0, 0, 0, icon_margin));
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc
index 24ee0c1..1620232 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc
@@ -30,6 +30,7 @@
 #include "extensions/common/constants.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/text_constants.h"
@@ -38,7 +39,6 @@
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/md_text_button.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
@@ -209,9 +209,9 @@
 
   constexpr int kPermissionIconSize = 18;
   auto* icon = line_container->AddChildView(
-      std::make_unique<views::ColorTrackingIconView>(
+      std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
           permissions::GetIconId(request->GetRequestType()),
-          kPermissionIconSize));
+          ui::NativeTheme::kColorId_DefaultIconColor, kPermissionIconSize)));
   icon->SetVerticalAlignment(views::ImageView::Alignment::kLeading);
 
   auto* label = line_container->AddChildView(
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
index 0b45413..52fe61e 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
@@ -16,20 +16,21 @@
 #include "components/sync/protocol/sync.pb.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/models/image_model.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
+#include "ui/views/controls/image_view.h"
 
 namespace send_tab_to_self {
 
 namespace {
 
-std::unique_ptr<views::ColorTrackingIconView> CreateIcon(
+std::unique_ptr<views::ImageView> CreateIcon(
     const sync_pb::SyncEnums::DeviceType device_type) {
   static constexpr int kPrimaryIconSize = 20;
-  auto icon = std::make_unique<views::ColorTrackingIconView>(
+  auto icon = std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
       device_type == sync_pb::SyncEnums::TYPE_PHONE ? kHardwareSmartphoneIcon
                                                     : kHardwareComputerIcon,
-      kPrimaryIconSize);
+      ui::NativeTheme::kColorId_DefaultIconColor, kPrimaryIconSize));
   constexpr auto kPrimaryIconBorder = gfx::Insets(6);
   icon->SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder));
   return icon;
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.cc
index d3eaf43..5cd76d98 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.cc
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.cc
@@ -16,15 +16,18 @@
 #include "components/send_tab_to_self/send_tab_to_self_entry.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/image_model.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/views/controls/button/button_controller.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 
 namespace send_tab_to_self {
 
 SendTabToSelfToolbarIconView::SendTabToSelfToolbarIconView(
     BrowserView* browser_view)
-    : ColorTrackingIconView(kSendTabToSelfIcon, gfx::kFaviconSize),
+    : ImageView(ui::ImageModel::FromVectorIcon(
+          kSendTabToSelfIcon,
+          ui::NativeTheme::kColorId_DefaultIconColor,
+          gfx::kFaviconSize)),
       browser_(browser_view->browser()) {
   SetAccessibleName(l10n_util::GetStringUTF16(
       IDS_TOOLBAR_BUTTON_SEND_TAB_TO_SELF_BUTTON_A11Y_NAME));
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h
index 4f0d1a6..d1f54b35 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h
@@ -8,7 +8,7 @@
 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_toolbar_icon_controller_delegate.h"
 #include "components/send_tab_to_self/send_tab_to_self_entry.h"
 #include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
+#include "ui/views/controls/image_view.h"
 
 class Browser;
 class BrowserView;
@@ -19,7 +19,7 @@
 // of its parent ToolbarView. The icon is made visible when there is a received
 // STTS notification.
 class SendTabToSelfToolbarIconView
-    : public views::ColorTrackingIconView,
+    : public views::ImageView,
       public SendTabToSelfToolbarIconControllerDelegate {
  public:
   explicit SendTabToSelfToolbarIconView(BrowserView* browser_view);
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
index ce42840..08b0b80 100644
--- a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
+++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
@@ -23,13 +23,13 @@
 #include "components/url_formatter/elide_url.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/box_layout.h"
@@ -244,11 +244,12 @@
   LogSharingDevicesToShow(data_.prefix, kSharingUiDialog, data_.devices.size());
   size_t index = 0;
   for (const auto& device : data_.devices) {
-    auto icon = std::make_unique<views::ColorTrackingIconView>(
-        device->device_type() == sync_pb::SyncEnums::TYPE_TABLET
-            ? kTabletIcon
-            : kHardwareSmartphoneIcon,
-        kPrimaryIconSize);
+    auto icon =
+        std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+            device->device_type() == sync_pb::SyncEnums::TYPE_TABLET
+                ? kTabletIcon
+                : kHardwareSmartphoneIcon,
+            ui::NativeTheme::kColorId_DefaultIconColor, kPrimaryIconSize));
 
     auto* dialog_button =
         button_list->AddChildView(std::make_unique<HoverButton>(
@@ -266,8 +267,9 @@
   for (const auto& app : data_.apps) {
     std::unique_ptr<views::ImageView> icon;
     if (app.vector_icon) {
-      icon = std::make_unique<views::ColorTrackingIconView>(*app.vector_icon,
-                                                            kPrimaryIconSize);
+      icon = std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+          *app.vector_icon, ui::NativeTheme::kColorId_DefaultIconColor,
+          kPrimaryIconSize));
     } else {
       icon = std::make_unique<views::ImageView>();
       icon->SetImage(app.image.AsImageSkia());
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
index d91f6fc2e..7211cd5 100644
--- a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
@@ -10,7 +10,8 @@
 #include "chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/views/controls/color_tracking_icon_view.h"
+#include "ui/base/models/image_model.h"
+#include "ui/views/controls/image_view.h"
 
 namespace sharing_hub {
 
@@ -19,10 +20,11 @@
 static constexpr int kPrimaryIconSize = 20;
 constexpr auto kPrimaryIconBorder = gfx::Insets(6);
 
-std::unique_ptr<views::ColorTrackingIconView> CreateIconFromVector(
+std::unique_ptr<views::ImageView> CreateIconFromVector(
     const gfx::VectorIcon& vector_icon) {
-  auto icon = std::make_unique<views::ColorTrackingIconView>(vector_icon,
-                                                             kPrimaryIconSize);
+  auto icon = std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
+      vector_icon, ui::NativeTheme::kColorId_DefaultIconColor,
+      kPrimaryIconSize));
   icon->SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder));
   return icon;
 }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_context.h b/chrome/browser/ui/views/tabs/tab_drag_context.h
index be57fc9..f27add9 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_context.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_context.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/models/list_selection_model.h"
@@ -56,6 +57,12 @@
   virtual std::unique_ptr<TabDragController> ReleaseDragController()
       WARN_UNUSED_RESULT = 0;
 
+  // Set a callback to be called with the controller upon assignment by
+  // OwnDragController(controller). Allows tests to get the TabDragController
+  // instance as soon as its assigned.
+  virtual void SetDragControllerCallbackForTesting(
+      base::OnceCallback<void(TabDragController*)> callback) = 0;
+
   // Destroys the current TabDragController. This cancel the existing drag
   // operation.
   virtual void DestroyDragController() = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 3282f992..cf8c0e1 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -19,7 +19,6 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -40,8 +39,6 @@
 #include "chrome/browser/ui/views/tabs/tab_style_views.h"
 #include "chrome/browser/ui/views/tabs/window_finder.h"
 #include "components/tab_groups/tab_group_id.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -659,6 +656,11 @@
                                                              : NORMAL);
 }
 
+void TabDragController::SetDragLoopDoneCallbackForTesting(
+    base::OnceClosure callback) {
+  drag_loop_done_callback_ = std::move(callback);
+}
+
 void TabDragController::InitDragData(TabSlotView* view,
                                      TabDragData* drag_data) {
   TRACE_EVENT0("views", "TabDragController::InitDragData");
@@ -1489,6 +1491,10 @@
           ? views::Widget::MoveLoopEscapeBehavior::kHide
           : views::Widget::MoveLoopEscapeBehavior::kDontHide;
 
+  // Pull into a local to avoid use-after-free if RunMoveLoop deletes |this|.
+  base::OnceClosure drag_loop_done_callback =
+      std::move(drag_loop_done_callback_);
+
   // This code isn't set up to handle nested run loops. Nested run loops may
   // lead to all sorts of interesting crashes, and generally indicate a bug
   // lower in the stack. This is a CHECK() as there may be security
@@ -1497,10 +1503,10 @@
   in_move_loop_ = true;
   views::Widget::MoveLoopResult result = move_loop_widget_->RunMoveLoop(
       drag_offset, move_loop_source, escape_behavior);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE,
-      content::NotificationService::AllBrowserContextsAndSources(),
-      content::NotificationService::NoDetails());
+  // Note: |this| can be deleted here!
+
+  if (drag_loop_done_callback)
+    std::move(drag_loop_done_callback).Run();
 
   if (!ref)
     return;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index 6cbf15f..8ae123f 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/timer/timer.h"
@@ -144,6 +145,9 @@
   // Complete the current drag session.
   void EndDrag(EndDragReason reason);
 
+  // Set a callback to be called when the nested drag loop finishes.
+  void SetDragLoopDoneCallbackForTesting(base::OnceClosure callback);
+
  private:
   friend class TabDragControllerTest;
 
@@ -705,6 +709,9 @@
   int attach_x_;
   int attach_index_;
 
+  // Called when the loop in RunMoveLoop finishes. Only for tests.
+  base::OnceClosure drag_loop_done_callback_;
+
   std::unique_ptr<KeyEventTracker> key_event_tracker_;
 
   std::unique_ptr<SourceTabStripEmptinessTracker>
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 8aab35f..8e856b9f 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -164,30 +164,33 @@
 
 }  // namespace
 
-class QuitDraggingObserver : public content::NotificationObserver {
+class QuitDraggingObserver {
  public:
-  QuitDraggingObserver() {
-    registrar_.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE,
-                   content::NotificationService::AllSources());
+  explicit QuitDraggingObserver(TabStrip* tab_strip) {
+    tab_strip->GetDragContext()->SetDragControllerCallbackForTesting(
+        base::BindOnce(&QuitDraggingObserver::OnDragControllerSet,
+                       weak_ptr_factory_.GetWeakPtr()));
   }
+
   QuitDraggingObserver(const QuitDraggingObserver&) = delete;
   QuitDraggingObserver& operator=(const QuitDraggingObserver&) = delete;
-  ~QuitDraggingObserver() override = default;
-
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override {
-    DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, type);
-    run_loop_.QuitWhenIdle();
-  }
+  ~QuitDraggingObserver() = default;
 
   // The observer should be constructed prior to initiating the drag. To prevent
   // misuse via constructing a temporary object, Wait is marked lvalue-only.
   void Wait() & { run_loop_.Run(); }
 
  private:
-  content::NotificationRegistrar registrar_;
+  void OnDragControllerSet(TabDragController* controller) {
+    controller->SetDragLoopDoneCallbackForTesting(base::BindOnce(
+        &QuitDraggingObserver::Quit, weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void Quit() { run_loop_.QuitWhenIdle(); }
+
   base::RunLoop run_loop_;
+
+  base::WeakPtrFactory<QuitDraggingObserver> weak_ptr_factory_{this};
 };
 
 void SetID(WebContents* web_contents, int id) {
@@ -646,7 +649,7 @@
                         base::OnceClosure task,
                         int tab = 0,
                         int drag_x_offset = 0) {
-    test::QuitDraggingObserver observer;
+    test::QuitDraggingObserver observer(tab_strip);
     // Move to the tab and drag it enough so that it detaches.
     const gfx::Point tab_0_center =
         GetCenterInScreenCoordinates(tab_strip->tab_at(tab));
@@ -661,7 +664,7 @@
                                   base::OnceClosure task,
                                   tab_groups::TabGroupId group,
                                   int drag_x_offset = 0) {
-    test::QuitDraggingObserver observer;
+    test::QuitDraggingObserver observer(tab_strip);
     // Move to the tab and drag it enough so that it detaches.
     const gfx::Point group_header_center =
         GetCenterInScreenCoordinates(tab_strip->group_header(group));
@@ -2863,7 +2866,7 @@
 void DragWindowAndVerifyOffset(DetachToBrowserTabDragControllerTest* test,
                                TabStrip* tab_strip,
                                int tab_index) {
-  test::QuitDraggingObserver observer;
+  test::QuitDraggingObserver observer(tab_strip);
   // Move to the tab and drag it enough so that it detaches.
   const gfx::Point tab_center =
       GetCenterInScreenCoordinates(tab_strip->tab_at(tab_index));
@@ -4485,8 +4488,8 @@
   // minimizing the window. See https://crbug.com/902897 for the details.
   ui::GestureConfiguration::GetInstance()->set_min_fling_velocity(1);
 
-  test::QuitDraggingObserver observer;
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
+  test::QuitDraggingObserver observer(tab_strip);
   const gfx::Point tab_0_center =
       GetCenterInScreenCoordinates(tab_strip->tab_at(0));
   const gfx::Vector2d detach(0, GetDetachY(tab_strip));
@@ -4525,7 +4528,7 @@
 
   // Sends events to the server without waiting for its reply, which will cause
   // extra touch events before PerformWindowMove starts handling events.
-  test::QuitDraggingObserver observer;
+  test::QuitDraggingObserver observer(tab_strip);
   base::SimpleTestTickClock clock;
   clock.SetNowTicks(base::TimeTicks::Now());
   ui::SetEventTickClockForTesting(&clock);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 5820644..daed33f 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -444,6 +444,8 @@
     drag_controller_->Init(this, source, dragging_views, gfx::Point(x, y),
                            event.x(), std::move(selection_model), move_behavior,
                            EventSourceFromEvent(event));
+    if (drag_controller_set_callback_)
+      std::move(drag_controller_set_callback_).Run(drag_controller_.get());
   }
 
   void ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
@@ -521,6 +523,8 @@
     DCHECK(controller);
     DCHECK(!drag_controller_);
     drag_controller_ = std::move(controller);
+    if (drag_controller_set_callback_)
+      std::move(drag_controller_set_callback_).Run(drag_controller_.get());
   }
 
   void DestroyDragController() override {
@@ -531,6 +535,11 @@
     return std::move(drag_controller_);
   }
 
+  void SetDragControllerCallbackForTesting(
+      base::OnceCallback<void(TabDragController*)> callback) override {
+    drag_controller_set_callback_ = std::move(callback);
+  }
+
   bool IsDragSessionActive() const override {
     return drag_controller_ != nullptr;
   }
@@ -1103,6 +1112,9 @@
   // the drag session.
   std::unique_ptr<TabDragController> drag_controller_;
 
+  // Only used in tests.
+  base::OnceCallback<void(TabDragController*)> drag_controller_set_callback_;
+
   base::WeakPtrFactory<TabDragContext> weak_factory_{this};
 };
 
diff --git a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc
index a3d8c3b..b85b7fb 100644
--- a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/toolbar/read_later_toolbar_button.h"
 
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -35,6 +37,12 @@
     SetWebContents(contents_wrapper_->web_contents());
   }
 
+  void SetVisible(bool visible) override {
+    views::WebView::SetVisible(visible);
+    base::RecordAction(
+        base::UserMetricsAction(visible ? "SidePanel.Show" : "SidePanel.Hide"));
+  }
+
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override {
     WebView::ViewHierarchyChanged(details);
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
index 5ed54ba8..d594f46 100644
--- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -24,6 +25,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/web_applications/file_handling_permission_request_dialog_test_api.h"
+#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/ui/webui/settings/site_settings_helper.h"
 #include "chrome/browser/web_applications/components/file_handler_manager.h"
@@ -289,6 +291,16 @@
     }
   }
 
+  void UninstallWebApp(const AppId& app_id) {
+    base::RunLoop run_loop;
+    UninstallWebAppWithCallback(
+        profile(), app_id, base::BindLambdaForTesting([&](bool uninstalled) {
+          EXPECT_TRUE(uninstalled);
+          run_loop.Quit();
+        }));
+    run_loop.Run();
+  }
+
  protected:
   base::test::ScopedFeatureList scoped_feature_list_;
   content::WebContents* web_contents_ = nullptr;
@@ -603,6 +615,76 @@
                                    ContentSettingsType::FILE_HANDLING));
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest,
+                       ResetPermissionOnUninstall) {
+  // Install an app and simulate the user granting it the file handling
+  // permission.
+  InstallFileHandlingPWA();
+  auto* map = HostContentSettingsMapFactory::GetForProfile(profile());
+  const GURL origin = GetSecureAppURL().GetOrigin();
+  EXPECT_EQ(CONTENT_SETTING_ASK,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+  map->SetContentSettingDefaultScope(origin, origin,
+                                     ContentSettingsType::FILE_HANDLING,
+                                     CONTENT_SETTING_ALLOW);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+
+  // Install a second app, which is on the same origin and does not handle any
+  // files. This should not affect the permission.
+  GURL second_app_url = https_server()->GetURL("app.com", "/pwa/app2.html");
+  InstallPWA(second_app_url);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+
+  // Uninstall the first app. It should reset the permission since no other app
+  // is installed with file handlers.
+  UninstallWebApp(app_id());
+  EXPECT_EQ(CONTENT_SETTING_ASK,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+
+  // Install the first app again and grant the permission.
+  InstallFileHandlingPWA();
+  EXPECT_EQ(CONTENT_SETTING_ASK,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+  map->SetContentSettingDefaultScope(origin, origin,
+                                     ContentSettingsType::FILE_HANDLING,
+                                     CONTENT_SETTING_ALLOW);
+
+  // Install a third app, which is on a different origin; this should have no
+  // effect on the permission.
+  GURL third_app_url = https_server()->GetURL("otherapp.com", "/pwa/app2.html");
+  InstallAnotherFileHandlingPwa(third_app_url);
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+
+  // Uninstall the first app. It should reset the permission since no other app
+  // is installed *on the same origin* with file handlers.
+  UninstallWebApp(app_id());
+  EXPECT_EQ(CONTENT_SETTING_ASK,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+
+  // Install two PWAs with file handlers on the same origin, then grant the
+  // permission. Uninstalling one should not reset the permission.
+  InstallFileHandlingPWA();
+  InstallAnotherFileHandlingPwa(
+      https_server()->GetURL("app.com", "/pwa/app2.html"));
+  map->SetContentSettingDefaultScope(origin, origin,
+                                     ContentSettingsType::FILE_HANDLING,
+                                     CONTENT_SETTING_ALLOW);
+  UninstallWebApp(app_id());
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            map->GetContentSetting(origin, origin,
+                                   ContentSettingsType::FILE_HANDLING));
+}
+
 class WebAppFileHandlingPermissionDialogTest
     : public WebAppFileHandlingBrowserTest {
  public:
diff --git a/chrome/browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc b/chrome/browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc
index 5da06cc0..b076461 100644
--- a/chrome/browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc
@@ -101,7 +101,7 @@
 void FormatDictRecurse(base::Value* value,
                        const std::vector<std::string>& messages) {
   if (value->is_dict()) {
-    for (const auto& child : value->DictItems())
+    for (const auto child : value->DictItems())
       FormatDictRecurse(&child.second, messages);
     return;
   }
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
index df5722a..94a53d5 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
@@ -96,12 +96,19 @@
 }
 
 // Helper method to create zippy data.
-base::Value CreateZippyData(const SettingZippyList& zippy_list,
+base::Value CreateZippyData(const ActivityControlUi& activity_control_ui,
                             bool is_minor_mode) {
   base::Value zippy_data(base::Value::Type::LIST);
+  auto zippy_list = activity_control_ui.setting_zippy();
   for (auto& setting_zippy : zippy_list) {
     base::Value data(base::Value::Type::DICTIONARY);
-    data.SetKey("title", base::Value(setting_zippy.title()));
+    data.SetKey("title", base::Value(activity_control_ui.title()));
+    data.SetKey("identity", base::Value(activity_control_ui.identity()));
+    if (activity_control_ui.intro_text_paragraph_size()) {
+      data.SetKey("intro",
+                  base::Value(activity_control_ui.intro_text_paragraph(0)));
+    }
+    data.SetKey("name", base::Value(setting_zippy.title()));
     if (setting_zippy.description_paragraph_size()) {
       data.SetKey("description",
                   base::Value(setting_zippy.description_paragraph(0)));
@@ -113,6 +120,7 @@
     data.SetKey("iconUri", base::Value(setting_zippy.icon_uri()));
     data.SetKey("popupLink", base::Value(l10n_util::GetStringUTF16(
                                  IDS_ASSISTANT_ACTIVITY_CONTROL_POPUP_LINK)));
+    // TODO(https://crbug.com/1224850) Add data from learn_more_dialog field.
     data.SetKey("isMinorMode", base::Value(is_minor_mode));
     zippy_data.Append(std::move(data));
   }
@@ -203,11 +211,6 @@
                       base::Value(activity_control_ui.identity()));
     dictionary.SetKey("valuePropTitle",
                       base::Value(activity_control_ui.title()));
-    if (activity_control_ui.intro_text_paragraph_size()) {
-      dictionary.SetKey(
-          "valuePropIntro",
-          base::Value(activity_control_ui.intro_text_paragraph(0)));
-    }
     if (activity_control_ui.footer_paragraph_size()) {
       dictionary.SetKey("valuePropFooter",
                         base::Value(activity_control_ui.footer_paragraph(0)));
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h
index a80687b..79f188b 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h
@@ -58,8 +58,10 @@
 
 using SettingZippyList = google::protobuf::RepeatedPtrField<
     assistant::ClassicActivityControlUiTexts::SettingZippy>;
+using ActivityControlUi =
+    assistant::ConsentFlowUi::ConsentUi::ActivityControlUi;
 // Helper method to create zippy data.
-base::Value CreateZippyData(const SettingZippyList& zippy_list,
+base::Value CreateZippyData(const ActivityControlUi& activity_control_ui,
                             bool is_minor_mode);
 
 // Helper method to create disclosure data.
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
index 7fb23267..762d8ac 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -429,8 +429,8 @@
   DCHECK(settings_ui.has_consent_flow_ui());
 
   RecordAssistantOptInStatus(FLOW_STARTED);
-  auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
-  auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
+  auto third_party_disclosure_ui =
+      settings_ui.consent_flow_ui().consent_ui().third_party_disclosure_ui();
 
   base::Value zippy_data(base::Value::Type::LIST);
   bool skip_activity_control = true;
@@ -448,11 +448,12 @@
         data.consent_token = activity_control_ui.consent_token();
         data.ui_audit_key = activity_control_ui.ui_audit_key();
         pending_consent_data_.push_back(data);
-        zippy_data.Append(CreateZippyData(activity_control_ui.setting_zippy(),
-                                          /*is_minor_mode=*/true));
+        zippy_data.Append(
+            CreateZippyData(activity_control_ui, /*is_minor_mode=*/true));
       }
     }
   } else {
+    auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
     auto activity_control_ui = consent_ui.activity_control_ui();
     if (activity_control_ui.setting_zippy().size()) {
       skip_activity_control = false;
@@ -460,8 +461,8 @@
       data.consent_token = activity_control_ui.consent_token();
       data.ui_audit_key = activity_control_ui.ui_audit_key();
       pending_consent_data_.push_back(data);
-      zippy_data.Append(CreateZippyData(activity_control_ui.setting_zippy(),
-                                        /*is_minor_mode=*/false));
+      zippy_data.Append(
+          CreateZippyData(activity_control_ui, /*is_minor_mode=*/false));
     }
   }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.cc
index 3ccb9ad..2e39545 100644
--- a/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.cc
@@ -68,6 +68,10 @@
                IDS_OS_INSTALL_SCREEN_ERROR_NO_DEST_SUBTITLE);
   builder->Add("osInstallDialogErrorNoDestContent",
                IDS_OS_INSTALL_SCREEN_ERROR_NO_DEST_CONTENT);
+  builder->Add("osInstallDialogErrorServiceLogsLink",
+               IDS_OS_INSTALL_SCREEN_ERROR_SERVICE_LOGS_LINK_TEXT);
+  builder->Add("osInstallDialogServiceLogsTitle",
+               IDS_OS_INSTALL_SCREEN_SERVICE_LOGS_TITLE);
 
   builder->Add("osInstallDialogSuccessTitle",
                IDS_OS_INSTALL_SCREEN_SUCCESS_TITLE);
@@ -126,6 +130,7 @@
       ShowStep(kNoDestinationDeviceFoundStep);
       break;
   }
+  CallJS("login.OsInstallScreen.setServiceLogs", service_log);
 }
 
 void OsInstallScreenHandler::OsInstallStarted(
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index de516e5..894e1da 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -18,7 +18,6 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/chrome_extension_browser_constants.h"
-#include "chrome/browser/extensions/extension_checkup.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/managed_ui_handler.h"
 #include "chrome/browser/ui/webui/metrics_handler.h"
@@ -315,38 +314,6 @@
                      base::CommandLine::ForCurrentProcess()->HasSwitch(
                          ::switches::kEnableExtensionActivityLogging));
 
-  bool checkup_enabled =
-      base::FeatureList::IsEnabled(extensions_features::kExtensionsCheckup);
-  source->AddBoolean("showCheckup", checkup_enabled);
-  if (checkup_enabled) {
-    int title_id = 0;
-    int body1_id = 0;
-    int body2_id = 0;
-    switch (GetCheckupMessageFocus()) {
-      case CheckupMessage::PERFORMANCE:
-        title_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_TITLE;
-        body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY1;
-        body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY2;
-        break;
-      case CheckupMessage::PRIVACY:
-        title_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_TITLE;
-        body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY1;
-        body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY2;
-        break;
-      case CheckupMessage::NEUTRAL:
-        title_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_TITLE;
-        body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY1;
-        body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY2;
-        break;
-    }
-    source->AddLocalizedString("checkupTitle", title_id);
-    source->AddLocalizedString("checkupBody1", body1_id);
-    source->AddLocalizedString("checkupBody2", body2_id);
-  } else {
-    source->AddString("checkupTitle", "");
-    source->AddString("checkupBody1", "");
-    source->AddString("checkupBody2", "");
-  }
   source->AddString(kLoadTimeClassesKey, GetLoadTimeClasses(in_dev_mode));
 
   return source;
@@ -355,8 +322,7 @@
 }  // namespace
 
 ExtensionsUI::ExtensionsUI(content::WebUI* web_ui)
-    : WebContentsObserver(web_ui->GetWebContents()),
-      WebUIController(web_ui),
+    : WebUIController(web_ui),
       webui_load_timer_(web_ui->GetWebContents(),
                         "Extensions.WebUi.DocumentLoadedInMainFrameTime",
                         "Extensions.WebUi.LoadCompletedInMainFrame") {
@@ -382,27 +348,9 @@
       network::mojom::CSPDirectiveName::ObjectSrc, "object-src 'self';");
 
   content::WebUIDataSource::Add(profile, source);
-
-  // Stores a boolean in ExtensionPrefs so we can make sure that the user is
-  // redirected to the extensions page upon startup once. We're using
-  // GetVisibleURL() because the load hasn't committed and this check isn't used
-  // for a security decision, however a stronger check will be implemented if we
-  // decide to invest more in this experiment.
-  if (base::StartsWith(web_ui->GetWebContents()->GetVisibleURL().query_piece(),
-                       "checkup")) {
-    ExtensionPrefs::Get(profile)->SetUserHasSeenExtensionsCheckupOnStartup(
-        true);
-  }
 }
 
-ExtensionsUI::~ExtensionsUI() {
-  if (timer_.has_value())
-    UMA_HISTOGRAM_LONG_TIMES("Extensions.Checkup.TimeSpent", timer_->Elapsed());
-}
-
-void ExtensionsUI::DidStopLoading() {
-  timer_ = base::ElapsedTimer();
-}
+ExtensionsUI::~ExtensionsUI() = default;
 
 // static
 base::RefCountedMemory* ExtensionsUI::GetFaviconResourceBytes(
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.h b/chrome/browser/ui/webui/extensions/extensions_ui.h
index eba3298..ca2df43c 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.h
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.h
@@ -5,10 +5,8 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSIONS_UI_H_
 #define CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSIONS_UI_H_
 
-#include "base/timer/elapsed_timer.h"
 #include "chrome/browser/ui/webui/webui_load_timer.h"
 #include "components/prefs/pref_member.h"
-#include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "ui/base/layout.h"
 
@@ -22,8 +20,7 @@
 
 namespace extensions {
 
-class ExtensionsUI : public content::WebContentsObserver,
-                     public content::WebUIController {
+class ExtensionsUI : public content::WebUIController {
  public:
   explicit ExtensionsUI(content::WebUI* web_ui);
   ExtensionsUI(const ExtensionsUI&) = delete;
@@ -36,9 +33,6 @@
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
  private:
-  // content::WebContentsObserver:
-  void DidStopLoading() override;
-
   // Called when developer mode is toggled.
   void OnDevModeChanged();
 
@@ -46,9 +40,6 @@
   BooleanPrefMember in_dev_mode_;
 
   WebuiLoadTimer webui_load_timer_;
-
-  // Time the chrome://extensions page has been open.
-  absl::optional<base::ElapsedTimer> timer_;
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
index 6e073e7..b0e1300 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
@@ -74,7 +74,7 @@
     history_clusters::mojom::QueryParamsPtr query_params) {
   const std::string& query = query_params->query;
   const size_t max_count = query_params->max_count;
-  base::Time max_time = query_params->max_time.value_or(base::Time::Now());
+  base::Time end_time = query_params->max_time.value_or(base::Time());
   auto result_callback =
       base::BindOnce(&HistoryClustersHandler::OnClustersQueryResult,
                      weak_ptr_factory_.GetWeakPtr(), std::move(query_params));
@@ -85,9 +85,9 @@
     auto* history_clusters_service =
         HistoryClustersServiceFactory::GetForBrowserContext(profile_);
     // TODO(crbug.com/1220765): Supply `continuation_max_time` in
-    // `result_callback` once the service supports paging.
+    //  `result_callback` once the service supports paging.
     history_clusters_service->QueryClusters(
-        query, max_time, max_count,
+        query, end_time, max_count,
         base::BindOnce(std::move(result_callback), absl::nullopt),
         &query_task_tracker_);
   } else {
@@ -99,7 +99,7 @@
     OnMemoriesDebugMessage("HistoryClustersHandler: Loading UI Mock clusters.");
     // Cancel pending tasks, if any.
     query_task_tracker_.TryCancelAll();
-    QueryHistoryService(query, max_time, max_count, {},
+    QueryHistoryService(query, end_time, max_count, {},
                         std::move(result_callback));
 #endif
   }
diff --git a/chrome/browser/ui/webui/management/management_ui_browsertest.cc b/chrome/browser/ui/webui/management/management_ui_browsertest.cc
index b718c0f6..518bbc02 100644
--- a/chrome/browser/ui/webui/management/management_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/management/management_ui_browsertest.cc
@@ -28,10 +28,9 @@
   ~ManagementUITest() override = default;
 
   void SetUpInProcessBrowserTestFixture() override {
-    ON_CALL(provider_, IsInitializationComplete(testing::_))
-        .WillByDefault(testing::Return(true));
-    ON_CALL(provider_, IsFirstPolicyLoadComplete(testing::_))
-        .WillByDefault(testing::Return(true));
+    provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
   }
 
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc
index 38cd675..d4aad45 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler.cc
@@ -820,7 +820,7 @@
   if (enterprise_manager.empty())
     enterprise_manager = GetAccountManager(profile);
 #else
-  std::string enterprise_manager = GetAccountManager(profile);
+  std::string enterprise_manager = connectors_service->GetManagementDomain();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   base::Value result(base::Value::Type::DICTIONARY);
diff --git a/chrome/browser/ui/webui/read_later/read_later_page_handler.cc b/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
index 651c008..3d94b5c 100644
--- a/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
+++ b/chrome/browser/ui/webui/read_later/read_later_page_handler.cc
@@ -9,12 +9,15 @@
 #include <utility>
 #include <vector>
 
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/clock.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/bookmarks/bookmark_stats.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -23,6 +26,7 @@
 #include "chrome/browser/ui/webui/read_later/read_later_ui.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/profile_metrics/browser_profile_type.h"
 #include "components/reading_list/core/reading_list_entry.h"
 #include "components/url_formatter/url_formatter.h"
 #include "content/public/browser/web_contents.h"
@@ -153,6 +157,7 @@
     : receiver_(this, std::move(receiver)),
       page_(std::move(page)),
       read_later_ui_(read_later_ui),
+      web_ui_(web_ui),
       web_contents_(web_ui->GetWebContents()),
       clock_(base::DefaultClock::GetInstance()) {
   Profile* profile = Profile::FromWebUI(web_ui);
@@ -174,10 +179,12 @@
   if (!browser)
     return;
 
+  const bool side_panel_enabled =
+      base::FeatureList::IsEnabled(features::kSidePanel);
+
   // Open in active tab if the user is on the NTP.
   WindowOpenDisposition open_location =
-      IsActiveTabNTP(browser) ||
-              base::FeatureList::IsEnabled(features::kSidePanel)
+      IsActiveTabNTP(browser) || side_panel_enabled
           ? WindowOpenDisposition::CURRENT_TAB
           : WindowOpenDisposition::NEW_FOREGROUND_TAB;
 
@@ -187,6 +194,14 @@
 
   if (mark_as_read)
     reading_list_model_->SetReadStatus(url, true);
+
+  base::RecordAction(base::UserMetricsAction(
+      side_panel_enabled ? "SidePanel.ReadingList.Navigation"
+                         : "ReadingList.Dialog.Navigation"));
+  RecordBookmarkLaunch(
+      side_panel_enabled ? BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_READING_LIST
+                         : BOOKMARK_LAUNCH_LOCATION_READING_LIST_DIALOG,
+      profile_metrics::GetBrowserProfileType(Profile::FromWebUI(web_ui_)));
 }
 
 void ReadLaterPageHandler::UpdateReadStatus(const GURL& url, bool read) {
@@ -199,6 +214,11 @@
     return;
 
   chrome::MoveCurrentTabToReadLater(browser);
+
+  base::RecordAction(
+      base::UserMetricsAction(base::FeatureList::IsEnabled(features::kSidePanel)
+                                  ? "SidePanel.ReadingList.AddCurrentPage"
+                                  : "ReadingList.Dialog.AddCurrentPage"));
 }
 
 void ReadLaterPageHandler::RemoveEntry(const GURL& url) {
diff --git a/chrome/browser/ui/webui/read_later/read_later_page_handler.h b/chrome/browser/ui/webui/read_later/read_later_page_handler.h
index d73ffdf..51ae9d6 100644
--- a/chrome/browser/ui/webui/read_later/read_later_page_handler.h
+++ b/chrome/browser/ui/webui/read_later/read_later_page_handler.h
@@ -82,6 +82,7 @@
   // ReadLaterPageHandler is owned by |read_later_ui_| and so we expect
   // |read_later_ui_| to remain valid for the lifetime of |this|.
   ReadLaterUI* const read_later_ui_;
+  content::WebUI* const web_ui_;
   content::WebContents* web_contents_;
 
   base::Clock* clock_;
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom b/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom
index 9dcf7a7..f0a615d 100644
--- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom
+++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom
@@ -16,8 +16,9 @@
 
 // Browser-side handler for requests from WebUI page.
 interface BookmarksPageHandler {
-  // Opens a bookmark by URL.
-  OpenBookmark(url.mojom.Url url);
+  // Opens a bookmark by URL and passes the parent folder depth for metrics
+  // collection.
+  OpenBookmark(url.mojom.Url url, int32 parent_folder_depth);
 
   // Opens a context menu for a bookmark node. The id parameter is internally
   // an int64 but gets passed as a string from the chrome.bookmarks Extension
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc
index a8b60ab8..7b6de2a 100644
--- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc
+++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc
@@ -4,11 +4,14 @@
 
 #include "chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h"
 
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
+#include "chrome/browser/ui/bookmarks/bookmark_stats.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
@@ -20,6 +23,7 @@
 #include "components/bookmarks/browser/bookmark_node.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/profile_metrics/browser_profile_type.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/models/simple_menu_model.h"
 
@@ -139,7 +143,8 @@
 
 BookmarksPageHandler::~BookmarksPageHandler() = default;
 
-void BookmarksPageHandler::OpenBookmark(const GURL& url) {
+void BookmarksPageHandler::OpenBookmark(const GURL& url,
+                                        int32_t parent_folder_depth) {
   Browser* browser = chrome::FindLastActive();
   if (!browser)
     return;
@@ -148,6 +153,11 @@
                                 WindowOpenDisposition::CURRENT_TAB,
                                 ui::PAGE_TRANSITION_AUTO_BOOKMARK, false);
   browser->OpenURL(params);
+  base::RecordAction(base::UserMetricsAction("SidePanel.Bookmarks.Navigation"));
+  RecordBookmarkLaunch(
+      parent_folder_depth > 0 ? BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_SUBFOLDER
+                              : BOOKMARK_LAUNCH_LOCATION_SIDE_PANEL_FOLDER,
+      profile_metrics::GetBrowserProfileType(browser->profile()));
 }
 
 void BookmarksPageHandler::ShowContextMenu(const std::string& id_string,
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h
index b0b6731..4503b12 100644
--- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h
+++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h
@@ -22,7 +22,7 @@
   ~BookmarksPageHandler() override;
 
   // side_panel::mojom::BookmarksPageHandler:
-  void OpenBookmark(const GURL& url) override;
+  void OpenBookmark(const GURL& url, int32_t parent_folder_depth) override;
   void ShowContextMenu(const std::string& id, const gfx::Point& point) override;
 
  private:
diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.cc b/chrome/browser/ui/webui/realbox/realbox_handler.cc
index 8004fb43..d6fe3bb 100644
--- a/chrome/browser/ui/webui/realbox/realbox_handler.cc
+++ b/chrome/browser/ui/webui/realbox/realbox_handler.cc
@@ -36,6 +36,7 @@
 #include "components/omnibox/browser/omnibox_prefs.h"
 #include "components/omnibox/browser/search_suggestion_parser.h"
 #include "components/omnibox/browser/vector_icons.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/profile_metrics/browser_profile_type.h"
 #include "components/search/ntp_features.h"
@@ -159,7 +160,8 @@
         match.swap_contents_and_description;
     mojom_match->type = AutocompleteMatchType::ToString(match.type);
     mojom_match->supports_deletion = match.SupportsDeletion();
-    if (match.answer.has_value()) {
+    if (match.answer.has_value() &&
+        base::FeatureList::IsEnabled(omnibox::kNtpRealboxSuggestionAnswers)) {
       const auto& additional_text =
           GetAdditionalText(match.answer->first_line());
       mojom_match->answer = realbox::mojom::SuggestionAnswer::New(
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index 0b9418c..420f6d9 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -50,8 +50,6 @@
 AccessibilityHandler::~AccessibilityHandler() {
   if (a11y_nav_buttons_toggle_metrics_reporter_timer_.IsRunning())
     a11y_nav_buttons_toggle_metrics_reporter_timer_.FireNow();
-  if (features::IsExperimentalAccessibilityDictationOfflineEnabled())
-    speech::SodaInstaller::GetInstance()->RemoveObserver(this);
 }
 
 void AccessibilityHandler::RegisterMessages() {
@@ -118,15 +116,21 @@
 void AccessibilityHandler::HandleManageA11yPageReady(
     const base::ListValue* args) {
   AllowJavascript();
+}
 
+void AccessibilityHandler::OnJavascriptAllowed() {
   FireWebUIListener(
       "initial-data-ready",
       base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled()));
-
   MaybeAddSodaInstallerObserver();
   MaybeAddDictationLocales();
 }
 
+void AccessibilityHandler::OnJavascriptDisallowed() {
+  if (features::IsExperimentalAccessibilityDictationOfflineEnabled())
+    soda_observation_.Reset();
+}
+
 void AccessibilityHandler::HandleShowChromeVoxTutorial(
     const base::ListValue* args) {
   AccessibilityManager::Get()->ShowChromeVoxTutorial();
@@ -147,10 +151,13 @@
   // TODO(crbug.com/1195916): Don't display SODA status if the Dictation
   // language is not a downloaded or available SODA language.
   if (features::IsExperimentalAccessibilityDictationOfflineEnabled()) {
-    if (speech::SodaInstaller::GetInstance()->IsSodaInstalled())
+    if (speech::SodaInstaller::GetInstance()->IsSodaInstalled()) {
       OnSodaInstalled();
-    else
-      speech::SodaInstaller::GetInstance()->AddObserver(this);
+    } else {
+      // Add self as an observer. If this was a page refresh we don't want to
+      // get added twice.
+      soda_observation_.Observe(speech::SodaInstaller::GetInstance());
+    }
   }
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
index 39294c72..48ab03d 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_
 
 #include "base/macros.h"
+#include "base/scoped_observation.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/soda/soda_installer.h"
@@ -27,8 +28,8 @@
 
   // SettingsPageUIHandler implementation.
   void RegisterMessages() override;
-  void OnJavascriptAllowed() override {}
-  void OnJavascriptDisallowed() override {}
+  void OnJavascriptAllowed() override;
+  void OnJavascriptDisallowed() override;
 
   // Callback which updates if startup sound is enabled. Visible for testing.
   void HandleManageA11yPageReady(const base::ListValue* args);
@@ -70,6 +71,10 @@
   // setting value in the screen UI.
   base::OneShotTimer a11y_nav_buttons_toggle_metrics_reporter_timer_;
 
+  base::ScopedObservation<speech::SodaInstaller,
+                          speech::SodaInstaller::Observer>
+      soda_observation_{this};
+
   base::WeakPtrFactory<AccessibilityHandler> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityHandler);
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
index eb8043f..4d9bbf9 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
@@ -58,7 +58,12 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void TearDownOnMainThread() override { handler_.reset(); }
+  void TearDownOnMainThread() override {
+    handler_->DisallowJavascript();
+    handler_.reset();
+  }
+
+  size_t GetNumWebUICalls() { return web_ui_.call_data().size(); }
 
   void AssertWebUICalls(unsigned int num) {
     ASSERT_EQ(num, web_ui_.call_data().size());
@@ -70,14 +75,13 @@
     for (auto it = web_ui_.call_data().rbegin();
          it != web_ui_.call_data().rend(); ++it) {
       const content::TestWebUI::CallData* data = it->get();
-      std::string listener;
-      std::string listener_argument;
-      data->arg1()->GetAsString(&listener);
-      if (!data->arg2()->GetAsString(&listener_argument)) {
+      std::string listener = data->arg1()->GetString();
+      if (!data->arg2()->is_string()) {
         // Only look for listeners with a single string argument. Continue
         // silently if we find anything else.
         continue;
       }
+      std::string listener_argument = data->arg2()->GetString();
 
       if (data->function_name() == "cr.webUIListenerCallback" &&
           listener == expected_listener &&
@@ -107,8 +111,6 @@
     return false;
   }
 
-  void AddSodaInstallerObserver() { handler_->MaybeAddSodaInstallerObserver(); }
-
   void OnSodaInstalled() { handler_->OnSodaInstalled(); }
 
   void OnSodaProgress(int progress) { handler_->OnSodaProgress(progress); }
@@ -131,18 +133,18 @@
 // This also verifies that the correct string is sent to the JavaScript end
 // of the web UI.
 IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaInstalledTestApi) {
-  AssertWebUICalls(0);
+  size_t num_calls = GetNumWebUICalls();
   OnSodaInstalled();
-  AssertWebUICalls(1);
+  AssertWebUICalls(num_calls + 1);
   ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument(
       "dictation-setting-subtitle-changed", "Speech files downloaded"));
 }
 
 // Verifies that the correct string is sent to the JavaScript end of the web UI.
 IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaProgressTestApi) {
-  AssertWebUICalls(0);
+  size_t num_calls = GetNumWebUICalls();
   OnSodaProgress(50);
-  AssertWebUICalls(1);
+  AssertWebUICalls(num_calls + 1);
   ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument(
       "dictation-setting-subtitle-changed",
       "Downloading speech recognition files… 50%"));
@@ -150,9 +152,9 @@
 
 // Verifies that the correct string is sent to the JavaScript end of the web UI.
 IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaErrorTestApi) {
-  AssertWebUICalls(0);
+  size_t num_calls = GetNumWebUICalls();
   OnSodaError();
-  AssertWebUICalls(1);
+  AssertWebUICalls(num_calls + 1);
   ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument(
       "dictation-setting-subtitle-changed",
       "Can't download speech files. Dictation will continue to work by sending "
@@ -162,10 +164,9 @@
 // Ensures that AccessibilityHandler listens to SODA download state and fires
 // the correct listener when SODA is installed.
 IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaInstalledNotification) {
-  AssertWebUICalls(0);
-  AddSodaInstallerObserver();
+  size_t num_calls = GetNumWebUICalls();
   speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting();
-  AssertWebUICalls(1);
+  AssertWebUICalls(num_calls + 1);
   ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument(
       "dictation-setting-subtitle-changed", "Speech files downloaded"));
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
index fac7aee..fd51b02 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
@@ -56,10 +56,9 @@
     for (auto it = web_ui_.call_data().rbegin();
          it != web_ui_.call_data().rend(); ++it) {
       const content::TestWebUI::CallData* data = it->get();
-      std::string name;
-      if (data->function_name() != "cr.webUIListenerCallback" ||
-          !data->arg1()->GetAsString(&name) ||
-          name != KeyboardHandler::kShowKeysChangedName) {
+      const std::string* name = data->arg1()->GetIfString();
+      if (data->function_name() != "cr.webUIListenerCallback" || !name ||
+          *name != KeyboardHandler::kShowKeysChangedName) {
         continue;
       }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
index cd13651..fd94ad4 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
@@ -109,15 +109,14 @@
     for (auto it = web_ui_.call_data().rbegin();
          it != web_ui_.call_data().rend(); ++it) {
       const content::TestWebUI::CallData* data = it->get();
-      std::string name;
+      const std::string* name = data->arg1()->GetIfString();
       const base::DictionaryValue* dict = nullptr;
-      if (data->function_name() != "cr.webUIListenerCallback" ||
-          !data->arg1()->GetAsString(&name) ||
-          name != PowerHandler::kPowerManagementSettingsChangedName) {
+      if (data->function_name() != "cr.webUIListenerCallback" || !name ||
+          *name != PowerHandler::kPowerManagementSettingsChangedName) {
         continue;
       }
       if (!data->arg2()->GetAsDictionary(&dict)) {
-        ADD_FAILURE() << "Failed to get dict from " << name << " message";
+        ADD_FAILURE() << "Failed to get dict from " << *name << " message";
         continue;
       }
       std::string out;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
index 494b918..245a8a518 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
@@ -149,12 +149,11 @@
     for (auto it = web_ui_.call_data().rbegin();
          it != web_ui_.call_data().rend(); ++it) {
       const content::TestWebUI::CallData* data = it->get();
-      std::string name;
-      if (data->function_name() != "cr.webUIListenerCallback" ||
-          !data->arg1()->GetAsString(&name)) {
+      const std::string* name = data->arg1()->GetIfString();
+      if (data->function_name() != "cr.webUIListenerCallback" || !name) {
         continue;
       }
-      if (name == event_name)
+      if (*name == event_name)
         return data->arg2();
     }
     return nullptr;
diff --git a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
index a4c6805..e9ac388a 100644
--- a/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc
@@ -187,7 +187,7 @@
   for (const AssignmentInfo& info : *kAssignmentInfo) {
     auto* keycodes = prefs_->GetDictionary(info.pref_name);
     base::ListValue keys;
-    for (const auto& item : keycodes->DictItems()) {
+    for (const auto item : keycodes->DictItems()) {
       int key_code;
       if (!base::StringToInt(item.first, &key_code)) {
         NOTREACHED();
diff --git a/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc b/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
index 2fc26bd..3b56501 100644
--- a/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc
@@ -61,9 +61,8 @@
 
     auto& data = *(test_web_ui_.call_data().back());
     EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
-    std::string event;
-    ASSERT_TRUE(data.arg1()->GetAsString(&event));
-    EXPECT_EQ("auto-open-downloads-changed", event);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ("auto-open-downloads-changed", data.arg1()->GetString());
     ASSERT_TRUE(data.arg2()->is_bool());
     EXPECT_FALSE(data.arg2()->GetBool());
   }
diff --git a/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc b/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
index 199f25f..9cef2796 100644
--- a/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc
@@ -87,9 +87,8 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-  std::string callback_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-  EXPECT_EQ(kCallbackId, callback_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
   ASSERT_TRUE(data.arg2()->is_bool());
   EXPECT_TRUE(data.arg2()->GetBool());
@@ -106,9 +105,8 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-  std::string callback_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-  EXPECT_EQ(kCallbackId, callback_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
   ASSERT_TRUE(data.arg2()->is_bool());
   EXPECT_TRUE(data.arg2()->GetBool());
@@ -128,9 +126,8 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-  std::string callback_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-  EXPECT_EQ(kCallbackId, callback_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
   ASSERT_TRUE(data.arg2()->is_bool());
   EXPECT_TRUE(data.arg2()->GetBool());
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 610229e..a57d63b 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -283,14 +283,13 @@
   void ExpectPageStatusResponse(const std::string& expected_status) {
     auto& data = *web_ui_.call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ(kTestCallbackId, callback_id);
+
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ(kTestCallbackId, data.arg1()->GetString());
     ASSERT_TRUE(data.arg2()->is_bool());
     EXPECT_TRUE(data.arg2()->GetBool());
-    std::string status;
-    ASSERT_TRUE(data.arg3()->GetAsString(&status));
-    EXPECT_EQ(expected_status, status);
+    ASSERT_TRUE(data.arg3()->is_string());
+    EXPECT_EQ(expected_status, data.arg3()->GetString());
   }
 
   // Expects a call to ResolveJavascriptCallback() with |should_succeed| as its
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc b/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
index e7ff776b..fb35faaa 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc
@@ -123,9 +123,8 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-  std::string callback_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-  EXPECT_EQ("get-profile-info-callback-id", callback_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ("get-profile-info-callback-id", data.arg1()->GetString());
 
   ASSERT_TRUE(data.arg2()->is_bool());
   EXPECT_TRUE(data.arg2()->GetBool());
@@ -143,9 +142,9 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
 
-  std::string event_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&event_id));
-  EXPECT_EQ(ProfileInfoHandler::kProfileInfoChangedEventName, event_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ(ProfileInfoHandler::kProfileInfoChangedEventName,
+            data.arg1()->GetString());
 
   VerifyProfileInfo(data.arg2());
 }
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
index 4800e171..9270dbe 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc
@@ -100,9 +100,10 @@
   // Check that Javascript side is notified after resetting is done.
   EXPECT_EQ("cr.webUIResponse",
             web_ui()->call_data()[0]->function_name());
-  std::string callback_id;
-  EXPECT_TRUE(web_ui()->call_data()[0]->arg1()->GetAsString(&callback_id));
-  EXPECT_EQ(expected_callback_id, callback_id);
+  const std::string* callback_id =
+      web_ui()->call_data()[0]->arg1()->GetIfString();
+  EXPECT_NE(nullptr, callback_id);
+  EXPECT_EQ(expected_callback_id, *callback_id);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
index d87a38e..85e4813 100644
--- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -378,11 +378,9 @@
     if (data.function_name() != "cr.webUIListenerCallback") {
       continue;
     }
-    std::string event;
-    if ((!data.arg1()->GetAsString(&event)) ||
-        event != "safety-check-" + component + "-status-changed") {
+    const std::string* event = data.arg1()->GetIfString();
+    if (!event || *event != "safety-check-" + component + "-status-changed")
       continue;
-    }
     const base::DictionaryValue* dictionary = nullptr;
     if (!data.arg2()->GetAsDictionary(&dictionary)) {
       continue;
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
index 9ac248d..fb872ec 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -265,8 +265,7 @@
   CHECK(args_list[1].is_list());
   base::Value::ConstListView data_type_list = args_list[1].GetList();
   for (const base::Value& type : data_type_list) {
-    std::string pref_name;
-    CHECK(type.GetAsString(&pref_name));
+    const std::string pref_name = type.GetString();
     BrowsingDataType data_type =
         browsing_data::GetDataTypeFromDeletionPreference(pref_name);
     data_type_vector.push_back(data_type);
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc
index 69121d7..cc2afcdc 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc
@@ -102,10 +102,9 @@
     if (data.function_name() != "cr.webUIListenerCallback") {
       continue;
     }
-    std::string event;
-    if ((!data.arg1()->GetAsString(&event)) || event != "update-sync-state") {
+    const std::string* event = data.arg1()->GetIfString();
+    if (!event || *event != "update-sync-state")
       continue;
-    }
     const base::DictionaryValue* dictionary = nullptr;
     if (!data.arg2()->GetAsDictionary(&dictionary)) {
       continue;
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index 142dd48..d762086 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -223,9 +223,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
 
-    std::string event_name;
-    ASSERT_TRUE(data.arg1()->GetAsString(&event_name));
-    EXPECT_EQ("onBlockAutoplayStatusChanged", event_name);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ("onBlockAutoplayStatusChanged", data.arg1()->GetString());
 
     const base::DictionaryValue* event_data = nullptr;
     ASSERT_TRUE(data.arg2()->GetAsDictionary(&event_data));
@@ -257,9 +256,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ(kCallbackId, callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
     ASSERT_TRUE(data.arg2()->is_bool());
     ASSERT_TRUE(data.arg2()->GetBool());
@@ -287,9 +285,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ(kCallbackId, callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
     ASSERT_TRUE(data.arg2()->is_bool());
     ASSERT_TRUE(data.arg2()->GetBool());
 
@@ -321,9 +318,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ(kCallbackId, callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
     ASSERT_TRUE(data.arg2()->is_bool());
     ASSERT_TRUE(data.arg2()->GetBool());
@@ -341,9 +337,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIResponse", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ(kCallbackId, callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
 
     ASSERT_TRUE(data.arg2()->is_bool());
     ASSERT_TRUE(data.arg2()->GetBool());
@@ -367,9 +362,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ("onIncognitoStatusChanged", callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ("onIncognitoStatusChanged", data.arg1()->GetString());
 
     ASSERT_TRUE(data.arg2()->is_bool());
     EXPECT_EQ(expected_incognito, data.arg2()->GetBool());
@@ -383,9 +377,8 @@
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
     EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
 
-    std::string callback_id;
-    ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-    EXPECT_EQ("onZoomLevelsChanged", callback_id);
+    ASSERT_TRUE(data.arg1()->is_string());
+    EXPECT_EQ("onZoomLevelsChanged", data.arg1()->GetString());
 
     const base::ListValue* exceptions;
     ASSERT_TRUE(data.arg2()->GetAsList(&exceptions));
@@ -485,8 +478,6 @@
     handler()->ClearAllSitesMapForTesting();
     handler()->OnStorageFetched();
     const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
-    std::string callback_id;
-    data.arg1()->GetAsString(&callback_id);
     const base::ListValue* storage_and_cookie_list;
     data.arg2()->GetAsList(&storage_and_cookie_list);
     return storage_and_cookie_list;
@@ -843,9 +834,8 @@
   const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
   EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
 
-  std::string callback_id;
-  ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
-  EXPECT_EQ("onStorageListFetched", callback_id);
+  ASSERT_TRUE(data.arg1()->is_string());
+  EXPECT_EQ("onStorageListFetched", data.arg1()->GetString());
 
   const base::ListValue* storage_and_cookie_list;
   ASSERT_TRUE(data.arg2()->GetAsList(&storage_and_cookie_list));
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc
index 62aed02..56669d7 100644
--- a/chrome/browser/ui/webui/settings/site_settings_helper.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -840,12 +840,11 @@
   // Convert the URLs to |ContentSettingsPattern|s. Ignore any invalid ones.
   std::vector<ContentSettingsPattern> patterns;
   for (const auto& entry : policy_urls->GetList()) {
-    std::string url;
-    bool valid_string = entry.GetAsString(&url);
-    if (!valid_string)
+    const std::string* url = entry.GetIfString();
+    if (!url)
       continue;
 
-    ContentSettingsPattern pattern = ContentSettingsPattern::FromString(url);
+    ContentSettingsPattern pattern = ContentSettingsPattern::FromString(*url);
     if (!pattern.IsValid())
       continue;
 
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc
index 792c2a3..eb41576 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc
@@ -58,15 +58,22 @@
 // JS code below.
 
 IN_PROC_BROWSER_TEST_F(TabSearchUIBrowserTest, InitialTabItemsListed) {
-  const std::string tab_items_js =
-      "const tabItems = document.querySelector('tab-search-app').shadowRoot"
-      "    .getElementById('tabsList')"
-      "    .querySelectorAll('tab-search-item');";
-  int tab_item_count =
-      content::EvalJs(webui_contents_.get(), tab_items_js + "tabItems.length",
-                      content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
-                      ISOLATED_WORLD_ID_CHROME_INTERNAL)
-          .ExtractInt();
+  const std::string tab_item_count_js =
+      "new Promise((resolve) => {"
+      "  const interval = setInterval(() => {"
+      "    const tabItems = document.querySelector('tab-search-app').shadowRoot"
+      "        .getElementById('tabsList')"
+      "        .querySelectorAll('tab-search-item');"
+      "    if (tabItems) {"
+      "      resolve(tabItems.length);"
+      "      clearInterval(interval);"
+      "    }"
+      "  }, 100);"
+      "});";
+  int tab_item_count = content::EvalJs(webui_contents_.get(), tab_item_count_js,
+                                       content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+                                       ISOLATED_WORLD_ID_CHROME_INTERNAL)
+                           .ExtractInt();
   ASSERT_EQ(4, tab_item_count);
 }
 
diff --git a/chrome/browser/web_applications/components/web_app_shortcut.cc b/chrome/browser/web_applications/components/web_app_shortcut.cc
index 42b9445..bffc2530 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut.cc
+++ b/chrome/browser/web_applications/components/web_app_shortcut.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
diff --git a/chrome/browser/web_applications/components/web_app_shortcut.h b/chrome/browser/web_applications/components/web_app_shortcut.h
index d0f058f..93cd23e8 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut.h
+++ b/chrome/browser/web_applications/components/web_app_shortcut.h
@@ -12,7 +12,6 @@
 #include "base/callback_forward.h"
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
-#include "base/no_destructor.h"
 #include "base/sequence_checker.h"
 #include "build/build_config.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/web_applications/file_handlers_permission_helper.cc b/chrome/browser/web_applications/file_handlers_permission_helper.cc
index 3ee39ff1..4255de23 100644
--- a/chrome/browser/web_applications/file_handlers_permission_helper.cc
+++ b/chrome/browser/web_applications/file_handlers_permission_helper.cc
@@ -116,6 +116,31 @@
   app->SetFileHandlerPermissionBlocked(IsPermissionBlocked(app->scope()));
 }
 
+void FileHandlersPermissionHelper::OnWebAppWillBeUninstalled(
+    const AppId& app_id) {
+  // If the uninstalled app had no file handler registrations, do nothing.
+  const WebAppRegistrar& registrar = finalizer_->GetWebAppRegistrar();
+  if (registrar.GetAppFileHandlers(app_id)->empty())
+    return;
+
+  // See if there are any remaining apps in the same origin that have file
+  // handlers. If so, do nothing.
+  const WebApp* app = registrar.GetAppById(app_id);
+  const GURL origin = app->scope().GetOrigin();
+  std::vector<AppId> app_ids = registrar.FindAppsInScope(origin);
+  for (const AppId& app_id_iter : app_ids) {
+    const apps::FileHandlers* handlers =
+        registrar.GetAppFileHandlers(app_id_iter);
+    if (app_id != app_id_iter && !handlers->empty())
+      return;
+  }
+
+  // This was the last app in the given origin that had file handlers, so reset
+  // the permission.
+  PermissionManagerFactory::GetForProfile(finalizer_->profile())
+      ->ResetPermission(content::PermissionType::FILE_HANDLING, origin, origin);
+}
+
 bool FileHandlersPermissionHelper::IsPermissionBlocked(const GURL& scope) {
   permissions::PermissionManager* permission_manager =
       PermissionManagerFactory::GetForProfile(finalizer_->profile());
diff --git a/chrome/browser/web_applications/file_handlers_permission_helper.h b/chrome/browser/web_applications/file_handlers_permission_helper.h
index e8a17bf..e099b040 100644
--- a/chrome/browser/web_applications/file_handlers_permission_helper.h
+++ b/chrome/browser/web_applications/file_handlers_permission_helper.h
@@ -55,6 +55,7 @@
   // AppRegistrarObserver:
   void OnWebAppManifestUpdated(const AppId& app_id,
                                base::StringPiece old_name) override;
+  void OnWebAppWillBeUninstalled(const AppId& app_id) override;
 
  private:
   // Checks if file handling permission is blocked in settings.
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
index 4ec6c55..04a5af1 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
@@ -104,4 +104,14 @@
     default String getGoogleApiKey() {
         return null;
     }
+
+    /** Returns Chrome's version string. */
+    default String getChromeVersion() {
+        return "";
+    }
+
+    /** Returns Chrome's channel as enumerated in components/version_info/channel.h. */
+    default int getChromeChannel() {
+        return 0;
+    }
 }
diff --git a/chrome/common/search/search.mojom b/chrome/common/search/search.mojom
index d53c558..dc22772 100644
--- a/chrome/common/search/search.mojom
+++ b/chrome/common/search/search.mojom
@@ -109,14 +109,6 @@
 
   // Called when a user dismisses a promo.
   BlocklistPromo(string promo_id);
-
-  // Handles navigation to chrome://extensions by calling the browser to
-  // complete the navigation for the extensions checkup middle slot promo.
-  OpenExtensionsPage(double button,
-                     bool alt_key,
-                     bool ctrl_key,
-                     bool meta_key,
-                     bool shift_key);
 };
 
 [Native]
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc
index 5c6dd74..cda5649 100644
--- a/chrome/renderer/cart/commerce_hint_agent.cc
+++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -383,7 +383,7 @@
             .value());
     DCHECK(json.is_dict());
     std::map<std::string, std::string> map;
-    for (const auto& item : json.DictItems()) {
+    for (const auto item : json.DictItems()) {
       map.insert({std::move(item.first), std::move(item.second.GetString())});
     }
     return map;
@@ -402,7 +402,7 @@
             .value());
     DCHECK(json.is_dict());
     std::map<std::string, std::string> map;
-    for (const auto& item : json.DictItems()) {
+    for (const auto item : json.DictItems()) {
       map.insert({std::move(item.first), std::move(item.second.GetString())});
     }
     return map;
@@ -416,7 +416,7 @@
         base::JSONReader::Read(kPurchaseButtonPatternMapping.Get()).value());
     DCHECK(json.is_dict());
     std::map<std::string, std::string> map;
-    for (const auto& item : json.DictItems()) {
+    for (const auto item : json.DictItems()) {
       map.insert({std::move(item.first), std::move(item.second.GetString())});
     }
     return map;
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index 4f902208..7045c42 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -344,15 +344,6 @@
   embedded_search_service_->BlocklistPromo(promo_id);
 }
 
-void SearchBox::OpenExtensionsPage(double button,
-                                   bool alt_key,
-                                   bool ctrl_key,
-                                   bool meta_key,
-                                   bool shift_key) {
-  embedded_search_service_->OpenExtensionsPage(button, alt_key, ctrl_key,
-                                               meta_key, shift_key);
-}
-
 void SearchBox::SetPageSequenceNumber(int page_seq_no) {
   page_seq_no_ = page_seq_no;
 }
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 2898f00..ea1f56a7 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -152,14 +152,6 @@
   // Called when a user dismisses a promo.
   void BlocklistPromo(const std::string& promo_id);
 
-  // Handles navigation to the chrome://extensions page by calling the browser
-  // to do the navigation.
-  void OpenExtensionsPage(double button,
-                          bool alt_key,
-                          bool ctrl_key,
-                          bool meta_key,
-                          bool shift_key);
-
   bool is_focused() const { return is_focused_; }
   bool is_input_in_progress() const { return is_input_in_progress_; }
   bool is_key_capture_enabled() const { return is_key_capture_enabled_; }
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index dc94b7f..4a6d1de 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -630,11 +630,6 @@
   static void RevertThemeChanges();
   static void ConfirmThemeChanges();
   static void BlocklistPromo(const std::string& promo_id);
-  static void OpenExtensionsPage(double button,
-                                 bool alt_key,
-                                 bool ctrl_key,
-                                 bool meta_key,
-                                 bool shift_key);
   static v8::Local<v8::Value> GetColorsInfo(v8::Isolate* isolate);
 
   DISALLOW_COPY_AND_ASSIGN(NewTabPageBindings);
@@ -701,8 +696,7 @@
       .SetMethod("confirmThemeChanges",
                  &NewTabPageBindings::ConfirmThemeChanges)
       .SetMethod("getColorsInfo", &NewTabPageBindings::GetColorsInfo)
-      .SetMethod("blocklistPromo", &NewTabPageBindings::BlocklistPromo)
-      .SetMethod("openExtensionsPage", &NewTabPageBindings::OpenExtensionsPage);
+      .SetMethod("blocklistPromo", &NewTabPageBindings::BlocklistPromo);
 }
 
 // static
@@ -1052,18 +1046,6 @@
   search_box->BlocklistPromo(promo_id);
 }
 
-void NewTabPageBindings::OpenExtensionsPage(double button,
-                                            bool alt_key,
-                                            bool ctrl_key,
-                                            bool meta_key,
-                                            bool shift_key) {
-  SearchBox* search_box = GetSearchBoxForCurrentContext();
-  if (!search_box)
-    return;
-  search_box->OpenExtensionsPage(button, alt_key, ctrl_key, meta_key,
-                                 shift_key);
-}
-
 }  // namespace
 
 // static
diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc
index 63c48ee..9cfe308 100644
--- a/chrome/service/cloud_print/print_system_cups.cc
+++ b/chrome/service/cloud_print/print_system_cups.cc
@@ -547,7 +547,7 @@
     return false;
 
   options->clear();
-  for (const auto& it : ticket.value().DictItems()) {
+  for (const auto it : ticket.value().DictItems()) {
     if (it.second.is_string())
       (*options)[it.first] = it.second.GetString();
   }
diff --git a/chrome/services/util_win/util_read_icon.cc b/chrome/services/util_win/util_read_icon.cc
index 3f93358..956af840 100644
--- a/chrome/services/util_win/util_read_icon.cc
+++ b/chrome/services/util_win/util_read_icon.cc
@@ -9,33 +9,55 @@
 #include <string>
 
 #include "base/files/file_path.h"
+#include "base/scoped_native_library.h"
+#include "base/win/scoped_gdi_object.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/icon_util.h"
 #include "ui/gfx/image/image_skia.h"
 
-namespace {
-// Provides storage for icon handles.
-struct ScopedIconHandles {
- public:
-  explicit ScopedIconHandles(size_t n)
-      : handles(std::vector<HICON>(n, nullptr)),
-        resources(std::vector<UINT>(n, 0)) {}
-  ~ScopedIconHandles() {
-    for (HICON icon : handles) {
-      if (icon) {
-        DeleteObject(icon);
-      }
-    }
-  }
-
-  std::vector<HICON> handles;
-  std::vector<UINT> resources;
-};
-}  // namespace
-
 using chrome::mojom::IconSize;
 
+namespace {
+
+gfx::ImageSkia LoadIcon(const wchar_t* filename, int size, float scale) {
+  base::ScopedNativeLibrary library(::LoadLibraryEx(
+      filename, nullptr,
+      LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE));
+  if (!library.is_valid())
+    return gfx::ImageSkia();
+
+  // Find the first icon referenced in the file.  This matches Explorer.
+  LPWSTR id = nullptr;
+  // Because the lambda below returns FALSE, EnumResourceNames() itself will
+  // return FALSE even when it "succeeds", so ignore its return value.
+  ::EnumResourceNames(
+      library.get(), RT_GROUP_ICON,
+      [](HMODULE, LPCWSTR, LPWSTR name, LONG_PTR param) {
+        *reinterpret_cast<LPWSTR*>(param) =
+            IS_INTRESOURCE(name) ? name : _wcsdup(name);
+        return FALSE;
+      },
+      reinterpret_cast<LONG_PTR>(&id));
+
+  base::win::ScopedHICON icon(static_cast<HICON>(
+      ::LoadImage(library.get(), id, IMAGE_ICON, size, size, LR_DEFAULTCOLOR)));
+  if (!IS_INTRESOURCE(id))
+    free(id);
+  if (!icon.is_valid())
+    return gfx::ImageSkia();
+
+  const SkBitmap bitmap = IconUtil::CreateSkBitmapFromHICON(icon.get());
+  if (bitmap.isNull())
+    return gfx::ImageSkia();
+
+  gfx::ImageSkia image_skia(gfx::ImageSkiaRep(bitmap, scale));
+  image_skia.MakeThreadSafe();
+  return image_skia;
+}
+
+}  // namespace
+
 UtilReadIcon::UtilReadIcon(
     mojo::PendingReceiver<chrome::mojom::UtilReadIcon> receiver)
     : receiver_(this, std::move(receiver)) {}
@@ -63,46 +85,7 @@
     default:
       NOTREACHED();
   }
-
-  size *= scale;
-
-  gfx::ImageSkia image_ret;
-
-  // Returns number of icons, or 0 on failure.
-  UINT nIcons = PrivateExtractIconsW(filename.value().c_str(), 0, 0, 0, nullptr,
-                                     nullptr, 0, 0);
-
-  if (nIcons == 0) {
-    std::move(callback).Run(std::move(image_ret), filename.AsUTF16Unsafe());
-    return;
-  }
-
-  ScopedIconHandles icons(nIcons);
-  UINT ret = PrivateExtractIconsW(filename.value().c_str(), 0, size, size,
-                                  icons.handles.data(), icons.resources.data(),
-                                  nIcons, 0);
-
-  if (ret != nIcons) {
-    std::move(callback).Run(std::move(image_ret), filename.AsUTF16Unsafe());
-    return;
-  }
-
-  // Use icon with lowest resource value, or first if no hints available.
-  UINT best = 0xFFFFFFFF;
-  HICON selected = icons.handles.at(0);
-  for (size_t i = 0; i < icons.handles.size(); i++) {
-    if (icons.resources.at(i) < best) {
-      best = icons.resources.at(i);
-      selected = icons.handles.at(i);
-    }
-  }
-
-  const SkBitmap bitmap = IconUtil::CreateSkBitmapFromHICON(selected);
-  if (!bitmap.isNull()) {
-    gfx::ImageSkia image_skia(gfx::ImageSkiaRep(bitmap, scale));
-    image_skia.MakeThreadSafe();
-    image_ret = std::move(image_skia);
-  }
-
-  std::move(callback).Run(std::move(image_ret), filename.AsUTF16Unsafe());
+  std::move(callback).Run(
+      LoadIcon(filename.value().c_str(), size * scale, scale),
+      filename.AsUTF16Unsafe());
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 714761d1..6a92133 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -243,8 +243,6 @@
     "//base/test:test_support",
     "//chrome:resources",
     "//chrome:strings",
-
-    #"//chrome/app/theme:theme_resources",
     "//chrome/browser:browser_process",
     "//chrome/browser:test_support",
     "//chrome/browser/safe_browsing",
@@ -735,6 +733,7 @@
       "../browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc",
       "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h",
       "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.cc",
+      "../browser/policy/cloud/cloud_policy_manager_browsertest.cc",
       "../browser/policy/policy_prefs_browsertest.cc",
       "../browser/profiles/profile_browsertest_android.cc",
       "../browser/safe_browsing/test_safe_browsing_database_helper.cc",
@@ -978,6 +977,7 @@
     deps = [
       ":browser_tests_runner",
       ":policy_testserver_pyproto",
+      ":sync_integration_test_support",
       ":test_support",
       ":test_support_ui",
       "//base",
@@ -2401,10 +2401,6 @@
       }
     }
 
-    if (!is_fuchsia) {
-      deps += [ ":sync_integration_test_support" ]
-    }
-
     if (!is_mac) {
       data_deps += [ "//chrome:packed_resources" ]
       sources +=
@@ -5799,7 +5795,7 @@
       # Android uses a different way of showing browser windows.
       "../browser/optimization_guide/optimization_guide_tab_url_provider_unittest.cc",
     ]
-    if (is_posix || is_fuchsia) {
+    if (is_posix) {
       sources += [ "../browser/process_singleton_posix_unittest.cc" ]
     }
     if (is_chromeos_ash) {
@@ -6434,7 +6430,6 @@
       "../browser/extensions/extension_allowlist_unittest.cc",
       "../browser/extensions/extension_api_unittest.cc",
       "../browser/extensions/extension_api_unittest.h",
-      "../browser/extensions/extension_checkup_unittest.cc",
       "../browser/extensions/extension_context_menu_model_unittest.cc",
       "../browser/extensions/extension_error_controller_unittest.cc",
       "../browser/extensions/extension_error_ui_default_unittest.cc",
@@ -6799,13 +6794,10 @@
       "../browser/safe_browsing/user_population_unittest.cc",
     ]
 
-    # TODO(crbug/1056278): Enable this on Fuchsia
-    if (!is_fuchsia) {
-      deps += [
-        "//components/safe_browsing/content/common:file_type_policies",
-        "//components/safe_browsing/content/common:file_type_policies_test_support",
-      ]
-    }
+    deps += [
+      "//components/safe_browsing/content/common:file_type_policies",
+      "//components/safe_browsing/content/common:file_type_policies_test_support",
+    ]
   }
 
   if (safe_browsing_mode == 1) {
@@ -8296,7 +8288,6 @@
     "//pdf:pdf_ppapi",
   ]
   if (!is_fuchsia) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
     deps += [ "//third_party/breakpad:client" ]
   }
   if (enable_gwp_asan) {
@@ -8349,184 +8340,182 @@
   }
 }
 
-if (!is_fuchsia) {
-  # For Android, this target as to be built along the
-  # sync_integration_test_support_java target from the test target dependencies.
-  source_set("sync_integration_test_support") {
-    testonly = true
-    sources = [
-      "../browser/sync/test/integration/autofill_helper.cc",
-      "../browser/sync/test/integration/autofill_helper.h",
-      "../browser/sync/test/integration/bookmarks_helper.cc",
-      "../browser/sync/test/integration/bookmarks_helper.h",
-      "../browser/sync/test/integration/committed_all_nudged_changes_checker.cc",
-      "../browser/sync/test/integration/committed_all_nudged_changes_checker.h",
-      "../browser/sync/test/integration/configuration_refresher.cc",
-      "../browser/sync/test/integration/configuration_refresher.h",
-      "../browser/sync/test/integration/device_info_helper.cc",
-      "../browser/sync/test/integration/device_info_helper.h",
-      "../browser/sync/test/integration/encryption_helper.cc",
-      "../browser/sync/test/integration/encryption_helper.h",
-      "../browser/sync/test/integration/fake_server_invalidation_sender.cc",
-      "../browser/sync/test/integration/fake_server_invalidation_sender.h",
-      "../browser/sync/test/integration/fake_server_sync_invalidation_sender.cc",
-      "../browser/sync/test/integration/fake_server_sync_invalidation_sender.h",
-      "../browser/sync/test/integration/multi_client_status_change_checker.cc",
-      "../browser/sync/test/integration/multi_client_status_change_checker.h",
-      "../browser/sync/test/integration/offer_helper.cc",
-      "../browser/sync/test/integration/offer_helper.h",
-      "../browser/sync/test/integration/passwords_helper.cc",
-      "../browser/sync/test/integration/passwords_helper.h",
-      "../browser/sync/test/integration/quiesce_status_change_checker.cc",
-      "../browser/sync/test/integration/quiesce_status_change_checker.h",
-      "../browser/sync/test/integration/retry_verifier.cc",
-      "../browser/sync/test/integration/retry_verifier.h",
-      "../browser/sync/test/integration/secondary_account_helper.cc",
-      "../browser/sync/test/integration/secondary_account_helper.h",
-      "../browser/sync/test/integration/single_client_status_change_checker.cc",
-      "../browser/sync/test/integration/single_client_status_change_checker.h",
-      "../browser/sync/test/integration/status_change_checker.cc",
-      "../browser/sync/test/integration/status_change_checker.h",
-      "../browser/sync/test/integration/sync_datatype_helper.cc",
-      "../browser/sync/test/integration/sync_datatype_helper.h",
-      "../browser/sync/test/integration/sync_disabled_checker.cc",
-      "../browser/sync/test/integration/sync_disabled_checker.h",
-      "../browser/sync/test/integration/sync_service_impl_harness.cc",
-      "../browser/sync/test/integration/sync_service_impl_harness.h",
-      "../browser/sync/test/integration/sync_signin_delegate.cc",
-      "../browser/sync/test/integration/sync_signin_delegate.h",
-      "../browser/sync/test/integration/sync_test.cc",
-      "../browser/sync/test/integration/sync_test.h",
-      "../browser/sync/test/integration/typed_urls_helper.cc",
-      "../browser/sync/test/integration/typed_urls_helper.h",
-      "../browser/sync/test/integration/updated_progress_marker_checker.cc",
-      "../browser/sync/test/integration/updated_progress_marker_checker.h",
-      "../browser/sync/test/integration/wallet_helper.cc",
-      "../browser/sync/test/integration/wallet_helper.h",
+# For Android, this target has to be built along with the
+# sync_integration_test_support_java target from the test target dependencies.
+source_set("sync_integration_test_support") {
+  testonly = true
+  sources = [
+    "../browser/sync/test/integration/autofill_helper.cc",
+    "../browser/sync/test/integration/autofill_helper.h",
+    "../browser/sync/test/integration/bookmarks_helper.cc",
+    "../browser/sync/test/integration/bookmarks_helper.h",
+    "../browser/sync/test/integration/committed_all_nudged_changes_checker.cc",
+    "../browser/sync/test/integration/committed_all_nudged_changes_checker.h",
+    "../browser/sync/test/integration/configuration_refresher.cc",
+    "../browser/sync/test/integration/configuration_refresher.h",
+    "../browser/sync/test/integration/device_info_helper.cc",
+    "../browser/sync/test/integration/device_info_helper.h",
+    "../browser/sync/test/integration/encryption_helper.cc",
+    "../browser/sync/test/integration/encryption_helper.h",
+    "../browser/sync/test/integration/fake_server_invalidation_sender.cc",
+    "../browser/sync/test/integration/fake_server_invalidation_sender.h",
+    "../browser/sync/test/integration/fake_server_sync_invalidation_sender.cc",
+    "../browser/sync/test/integration/fake_server_sync_invalidation_sender.h",
+    "../browser/sync/test/integration/multi_client_status_change_checker.cc",
+    "../browser/sync/test/integration/multi_client_status_change_checker.h",
+    "../browser/sync/test/integration/offer_helper.cc",
+    "../browser/sync/test/integration/offer_helper.h",
+    "../browser/sync/test/integration/passwords_helper.cc",
+    "../browser/sync/test/integration/passwords_helper.h",
+    "../browser/sync/test/integration/quiesce_status_change_checker.cc",
+    "../browser/sync/test/integration/quiesce_status_change_checker.h",
+    "../browser/sync/test/integration/retry_verifier.cc",
+    "../browser/sync/test/integration/retry_verifier.h",
+    "../browser/sync/test/integration/secondary_account_helper.cc",
+    "../browser/sync/test/integration/secondary_account_helper.h",
+    "../browser/sync/test/integration/single_client_status_change_checker.cc",
+    "../browser/sync/test/integration/single_client_status_change_checker.h",
+    "../browser/sync/test/integration/status_change_checker.cc",
+    "../browser/sync/test/integration/status_change_checker.h",
+    "../browser/sync/test/integration/sync_datatype_helper.cc",
+    "../browser/sync/test/integration/sync_datatype_helper.h",
+    "../browser/sync/test/integration/sync_disabled_checker.cc",
+    "../browser/sync/test/integration/sync_disabled_checker.h",
+    "../browser/sync/test/integration/sync_service_impl_harness.cc",
+    "../browser/sync/test/integration/sync_service_impl_harness.h",
+    "../browser/sync/test/integration/sync_signin_delegate.cc",
+    "../browser/sync/test/integration/sync_signin_delegate.h",
+    "../browser/sync/test/integration/sync_test.cc",
+    "../browser/sync/test/integration/sync_test.h",
+    "../browser/sync/test/integration/typed_urls_helper.cc",
+    "../browser/sync/test/integration/typed_urls_helper.h",
+    "../browser/sync/test/integration/updated_progress_marker_checker.cc",
+    "../browser/sync/test/integration/updated_progress_marker_checker.h",
+    "../browser/sync/test/integration/wallet_helper.cc",
+    "../browser/sync/test/integration/wallet_helper.h",
+  ]
+  if (!is_android) {
+    sources += [
+      "../browser/sync/test/integration/apps_helper.cc",
+      "../browser/sync/test/integration/apps_helper.h",
+      "../browser/sync/test/integration/await_match_status_change_checker.cc",
+      "../browser/sync/test/integration/await_match_status_change_checker.h",
+      "../browser/sync/test/integration/cookie_helper.cc",
+      "../browser/sync/test/integration/cookie_helper.h",
+      "../browser/sync/test/integration/dictionary_helper.cc",
+      "../browser/sync/test/integration/dictionary_helper.h",
+      "../browser/sync/test/integration/dictionary_load_observer.cc",
+      "../browser/sync/test/integration/dictionary_load_observer.h",
+      "../browser/sync/test/integration/extension_settings_helper.cc",
+      "../browser/sync/test/integration/extension_settings_helper.h",
+      "../browser/sync/test/integration/extensions_helper.cc",
+      "../browser/sync/test/integration/extensions_helper.h",
+      "../browser/sync/test/integration/fake_server_match_status_checker.cc",
+      "../browser/sync/test/integration/fake_server_match_status_checker.h",
+      "../browser/sync/test/integration/feature_toggler.cc",
+      "../browser/sync/test/integration/feature_toggler.h",
+      "../browser/sync/test/integration/migration_waiter.cc",
+      "../browser/sync/test/integration/migration_waiter.h",
+      "../browser/sync/test/integration/migration_watcher.cc",
+      "../browser/sync/test/integration/migration_watcher.h",
+      "../browser/sync/test/integration/preferences_helper.cc",
+      "../browser/sync/test/integration/preferences_helper.h",
+      "../browser/sync/test/integration/search_engines_helper.cc",
+      "../browser/sync/test/integration/search_engines_helper.h",
+      "../browser/sync/test/integration/send_tab_to_self_helper.cc",
+      "../browser/sync/test/integration/send_tab_to_self_helper.h",
+      "../browser/sync/test/integration/session_hierarchy_match_checker.cc",
+      "../browser/sync/test/integration/session_hierarchy_match_checker.h",
+      "../browser/sync/test/integration/sessions_helper.cc",
+      "../browser/sync/test/integration/sessions_helper.h",
+      "../browser/sync/test/integration/sync_app_helper.cc",
+      "../browser/sync/test/integration/sync_app_helper.h",
+      "../browser/sync/test/integration/sync_extension_helper.cc",
+      "../browser/sync/test/integration/sync_extension_helper.h",
+      "../browser/sync/test/integration/sync_extension_installer.cc",
+      "../browser/sync/test/integration/sync_extension_installer.h",
+      "../browser/sync/test/integration/sync_integration_test_util.cc",
+      "../browser/sync/test/integration/sync_integration_test_util.h",
+      "../browser/sync/test/integration/sync_signin_delegate_desktop.cc",
+      "../browser/sync/test/integration/sync_signin_delegate_desktop.h",
+      "../browser/sync/test/integration/themes_helper.cc",
+      "../browser/sync/test/integration/themes_helper.h",
+      "../browser/sync/test/integration/user_events_helper.cc",
+      "../browser/sync/test/integration/user_events_helper.h",
     ]
-    if (!is_android) {
-      sources += [
-        "../browser/sync/test/integration/apps_helper.cc",
-        "../browser/sync/test/integration/apps_helper.h",
-        "../browser/sync/test/integration/await_match_status_change_checker.cc",
-        "../browser/sync/test/integration/await_match_status_change_checker.h",
-        "../browser/sync/test/integration/cookie_helper.cc",
-        "../browser/sync/test/integration/cookie_helper.h",
-        "../browser/sync/test/integration/dictionary_helper.cc",
-        "../browser/sync/test/integration/dictionary_helper.h",
-        "../browser/sync/test/integration/dictionary_load_observer.cc",
-        "../browser/sync/test/integration/dictionary_load_observer.h",
-        "../browser/sync/test/integration/extension_settings_helper.cc",
-        "../browser/sync/test/integration/extension_settings_helper.h",
-        "../browser/sync/test/integration/extensions_helper.cc",
-        "../browser/sync/test/integration/extensions_helper.h",
-        "../browser/sync/test/integration/fake_server_match_status_checker.cc",
-        "../browser/sync/test/integration/fake_server_match_status_checker.h",
-        "../browser/sync/test/integration/feature_toggler.cc",
-        "../browser/sync/test/integration/feature_toggler.h",
-        "../browser/sync/test/integration/migration_waiter.cc",
-        "../browser/sync/test/integration/migration_waiter.h",
-        "../browser/sync/test/integration/migration_watcher.cc",
-        "../browser/sync/test/integration/migration_watcher.h",
-        "../browser/sync/test/integration/preferences_helper.cc",
-        "../browser/sync/test/integration/preferences_helper.h",
-        "../browser/sync/test/integration/search_engines_helper.cc",
-        "../browser/sync/test/integration/search_engines_helper.h",
-        "../browser/sync/test/integration/send_tab_to_self_helper.cc",
-        "../browser/sync/test/integration/send_tab_to_self_helper.h",
-        "../browser/sync/test/integration/session_hierarchy_match_checker.cc",
-        "../browser/sync/test/integration/session_hierarchy_match_checker.h",
-        "../browser/sync/test/integration/sessions_helper.cc",
-        "../browser/sync/test/integration/sessions_helper.h",
-        "../browser/sync/test/integration/sync_app_helper.cc",
-        "../browser/sync/test/integration/sync_app_helper.h",
-        "../browser/sync/test/integration/sync_extension_helper.cc",
-        "../browser/sync/test/integration/sync_extension_helper.h",
-        "../browser/sync/test/integration/sync_extension_installer.cc",
-        "../browser/sync/test/integration/sync_extension_installer.h",
-        "../browser/sync/test/integration/sync_integration_test_util.cc",
-        "../browser/sync/test/integration/sync_integration_test_util.h",
-        "../browser/sync/test/integration/sync_signin_delegate_desktop.cc",
-        "../browser/sync/test/integration/sync_signin_delegate_desktop.h",
-        "../browser/sync/test/integration/themes_helper.cc",
-        "../browser/sync/test/integration/themes_helper.h",
-        "../browser/sync/test/integration/user_events_helper.cc",
-        "../browser/sync/test/integration/user_events_helper.h",
-      ]
-    } else {
-      sources += [
-        "../browser/sync/test/integration/sync_signin_delegate_android.cc",
-        "../browser/sync/test/integration/sync_signin_delegate_android.h",
-        "../browser/sync/test/integration/sync_test_utils_android.cc",
-        "../browser/sync/test/integration/sync_test_utils_android.h",
-      ]
-    }
-    public_deps = [ "//chrome/browser" ]
-    deps = [
-      ":test_support",
-      "//base",
-      "//build:chromeos_buildflags",
-      "//components/bookmarks/browser",
-      "//components/bookmarks/browser:test_support",
-      "//components/bookmarks/managed",
-      "//components/favicon/core",
-      "//components/invalidation/impl",
-      "//components/invalidation/impl:test_support",
-      "//components/os_crypt:test_support",
-      "//components/signin/public/identity_manager:test_support",
-      "//components/sync",
-      "//components/sync:test_support_model",
-      "//components/sync:test_support_nigori",
-      "//components/sync/test/fake_server",
-      "//components/sync/trusted_vault:test_support",
-      "//content/public/browser",
-      "//content/test:test_support",
-      "//net",
-      "//services/network/public/mojom",
-      "//skia",
+  } else {
+    sources += [
+      "../browser/sync/test/integration/sync_signin_delegate_android.cc",
+      "../browser/sync/test/integration/sync_signin_delegate_android.h",
+      "../browser/sync/test/integration/sync_test_utils_android.cc",
+      "../browser/sync/test/integration/sync_test_utils_android.h",
     ]
+  }
+  public_deps = [ "//chrome/browser" ]
+  deps = [
+    ":test_support",
+    "//base",
+    "//build:chromeos_buildflags",
+    "//components/bookmarks/browser",
+    "//components/bookmarks/browser:test_support",
+    "//components/bookmarks/managed",
+    "//components/favicon/core",
+    "//components/invalidation/impl",
+    "//components/invalidation/impl:test_support",
+    "//components/os_crypt:test_support",
+    "//components/signin/public/identity_manager:test_support",
+    "//components/sync",
+    "//components/sync:test_support_model",
+    "//components/sync:test_support_nigori",
+    "//components/sync/test/fake_server",
+    "//components/sync/trusted_vault:test_support",
+    "//content/public/browser",
+    "//content/test:test_support",
+    "//net",
+    "//services/network/public/mojom",
+    "//skia",
+  ]
 
-    if (is_mac) {
-      sources -= [
-        "../browser/sync/test/integration/dictionary_helper.cc",
-        "../browser/sync/test/integration/dictionary_helper.h",
-        "../browser/sync/test/integration/dictionary_load_observer.cc",
-        "../browser/sync/test/integration/dictionary_load_observer.h",
-      ]
-    }
-    if (is_chromeos_ash) {
-      sources += [
-        "../browser/sync/test/integration/os_sync_test.cc",
-        "../browser/sync/test/integration/os_sync_test.h",
-        "../browser/sync/test/integration/printers_helper.cc",
-        "../browser/sync/test/integration/printers_helper.h",
-        "../browser/sync/test/integration/sync_app_list_helper.cc",
-        "../browser/sync/test/integration/sync_app_list_helper.h",
-        "../browser/sync/test/integration/sync_arc_package_helper.cc",
-        "../browser/sync/test/integration/sync_arc_package_helper.h",
-        "../browser/ui/app_list/test/fake_app_list_model_updater.cc",
-        "../browser/ui/app_list/test/fake_app_list_model_updater.h",
-      ]
-      deps += [
-        "//ash/app_list:test_support",
-        "//chromeos",
-        "//components/arc:arc_test_support",
-        "//components/user_manager:test_support",
-      ]
-    }
-    if (is_android) {
-      deps += [ ":sync_integration_test_support_jni_headers" ]
-    } else {
-      deps += [
-        "//chrome/browser/web_applications:web_applications_test_support",
-        "//components/send_tab_to_self",
-        "//components/webapps/browser",
-      ]
-    }
+  if (is_mac) {
+    sources -= [
+      "../browser/sync/test/integration/dictionary_helper.cc",
+      "../browser/sync/test/integration/dictionary_helper.h",
+      "../browser/sync/test/integration/dictionary_load_observer.cc",
+      "../browser/sync/test/integration/dictionary_load_observer.h",
+    ]
+  }
+  if (is_chromeos_ash) {
+    sources += [
+      "../browser/sync/test/integration/os_sync_test.cc",
+      "../browser/sync/test/integration/os_sync_test.h",
+      "../browser/sync/test/integration/printers_helper.cc",
+      "../browser/sync/test/integration/printers_helper.h",
+      "../browser/sync/test/integration/sync_app_list_helper.cc",
+      "../browser/sync/test/integration/sync_app_list_helper.h",
+      "../browser/sync/test/integration/sync_arc_package_helper.cc",
+      "../browser/sync/test/integration/sync_arc_package_helper.h",
+      "../browser/ui/app_list/test/fake_app_list_model_updater.cc",
+      "../browser/ui/app_list/test/fake_app_list_model_updater.h",
+    ]
+    deps += [
+      "//ash/app_list:test_support",
+      "//chromeos",
+      "//components/arc:arc_test_support",
+      "//components/user_manager:test_support",
+    ]
+  }
+  if (is_android) {
+    deps += [ ":sync_integration_test_support_jni_headers" ]
+  } else {
+    deps += [
+      "//chrome/browser/web_applications:web_applications_test_support",
+      "//components/send_tab_to_self",
+      "//components/webapps/browser",
+    ]
   }
 }
 
-if (!is_fuchsia && !is_android) {
+if (!is_android) {
   test("sync_integration_tests") {
     use_xvfb = use_xvfb_in_this_config
 
@@ -8882,10 +8871,6 @@
     testonly = true
     deps = [ "//tools/perf/chrome_telemetry_build:telemetry_chrome_test_without_chrome" ]
     data = [
-      # TODO(kbr): refactor the telemetry dependencies more cleanly.
-      "//content/test/gpu/",
-      "//content/test/data/gpu/",
-
       # For GpuProcess.video
       "//content/test/data/media/bear.ogv",
 
@@ -8903,16 +8888,12 @@
 
       # For Skia Gold code, which has some GPU-specific unittests.
       "//build/skia_gold_common/",
-
-      # Not actually needed, but the way Telemetry looks for tests ends up
-      # looking in the unexpected_passes directory, which has a dependency on
-      # this.
-      # TODO(crbug.com/1227899): Remove this dependency once this target only
-      # includes the things it needs instead of all of //content/test/gpu/.
-      "//testing/unexpected_passes_common/",
     ]
 
-    data_deps = [ "//testing:test_scripts_shared" ]
+    data_deps = [
+      "//content/test:telemetry_gpu_unittest_data",
+      "//testing:test_scripts_shared",
+    ]
   }
 }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java b/chrome/test/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
index 055e33a..5669115 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/browser/history/StubbedHistoryProvider.java
@@ -29,6 +29,7 @@
     private int mLastQueryEndPosition;
     private String mLastQuery;
     private int mPaging = 5;
+    private boolean mHostOnly;
 
     @Override
     public void setObserver(BrowsingHistoryObserver observer) {
@@ -37,6 +38,17 @@
 
     @Override
     public void queryHistory(String query) {
+        mHostOnly = false;
+        query(query);
+    }
+
+    @Override
+    public void queryHistoryForHost(String hostName) {
+        mHostOnly = true;
+        query(hostName);
+    }
+
+    private void query(String query) {
         mLastQueryEndPosition = 0;
         mLastQuery = query;
         queryHistoryContinuation();
@@ -50,10 +62,21 @@
         if (!isSearch) {
             mSearchItems.clear();
         } else if (mLastQueryEndPosition == 0) {
+            mSearchItems.clear();
             // Start a new search; simulate basic search.
             mLastQuery = mLastQuery.toLowerCase(Locale.getDefault());
             for (HistoryItem item : mItems) {
-                if (item.getUrl().getSpec().toLowerCase(Locale.getDefault()).contains(mLastQuery)
+                if (mHostOnly) {
+                    if (item.getUrl()
+                                    .getHost()
+                                    .toLowerCase(Locale.getDefault())
+                                    .equals(mLastQuery)) {
+                        mSearchItems.add(item);
+                    }
+                } else if (item.getUrl()
+                                   .getSpec()
+                                   .toLowerCase(Locale.getDefault())
+                                   .contains(mLastQuery)
                         || item.getTitle().toLowerCase(Locale.getDefault()).contains(mLastQuery)) {
                     mSearchItems.add(item);
                 }
diff --git a/chrome/test/data/fullscreen_mouselock/fullscreen_mouselock.html b/chrome/test/data/fullscreen_mouselock/fullscreen_mouselock.html
index e6593b3..3fe2247b 100644
--- a/chrome/test/data/fullscreen_mouselock/fullscreen_mouselock.html
+++ b/chrome/test/data/fullscreen_mouselock/fullscreen_mouselock.html
@@ -20,15 +20,10 @@
     Element.ALLOW_KEYBOARD_INPUT);
 }
 
-function exitFullscreen() {
-  console.log("exitFullscreen()");
-  document.webkitCancelFullScreen();
-}
-
 // Wait for notification from JS, then notify test of success or failure
 // callback that the click has registered and the mouse lock state has changed.
-function lockMouse1(callback) {
-  console.log("lockMouse1()");
+function lockMouse(callback) {
+  console.log("lockMouse()");
   var target = document.getElementById("lockTarget1");
 
   function failure() {
@@ -55,7 +50,7 @@
 // wait state reading the value of lock_result. One of the two asynchronous
 // functions in the JS will be executed. The PyAuto code waits for lock_result
 // to return "success" or "failure". Sample PyAuto code:
-// lock_result = self._driver.execute_script('lockMouse1AndSetLockResult()')
+// lock_result = self._driver.execute_script('lockMouseAndSetLockResult()')
 function lockMouseAndSetLockResult(targetId) {
   var target = document.getElementById(targetId);
   lock_result = "";
@@ -77,29 +72,17 @@
   target.requestPointerLock();
 }
 
-function lockMouse1AndSetLockResult() {
-  console.log("lockMouse1AndSetLockResult()");
+function lockMouseAndSetLockResult() {
+  console.log("lockMouseAndSetLockResult()");
   lockMouseAndSetLockResult("lockTarget1");
 }
 
-// When mouse lock is initiated and accepted, PyAuto test will wait for the
-// lock_result to return "success" or "failure" to initiate the next action.
-function lockMouse2() {
-  console.log("lockMouse2()");
-  lockMouseAndSetLockResult("lockTarget2");
-}
-
-function delayedLockMouse1() {
-  console.log("delayedLockMouse1()");
-  window.setTimeout(lockMouse1, 1010);
-  // Delay must be over 1 second or the click that initiated the delayed action
-  // may still be considered active and treat this as a user gesture.
-  // We want to test a lock not associated with a user gesture.
-}
-
-function spamLockMouse2() {
-  console.log("spamLockMouse2()")
-  window.setInterval(lockMouse2, 111);
+function delayedLockMouse() {
+  console.log("delayedLockMouse()");
+  window.setTimeout(lockMouse, 5050);
+  // To test a lock not associated with user activation, the delay must
+  // be over 5 seconds so that the transient user activation expires
+  // before locking.
 }
 
 function unlockMouse() {
@@ -107,16 +90,10 @@
   document.exitPointerLock();
 }
 
-function enterFullscreenAndLockMouse1() {
-  console.log("enterFullscreenAndLockMouse1()");
+function enterFullscreenAndLockMouse() {
+  console.log("enterFullscreenAndLockMouse()");
   enterFullscreen();
-  lockMouse1();
-}
-
-function lockMouse1AndEnterFullscreen() {
-  console.log("lockMouse1AndEnterFullscreen()");
-  lockMouse1();
-  enterFullscreen();
+  lockMouse();
 }
 
 function moveHTMLCursorTo(x, y) {
@@ -175,14 +152,10 @@
 
   document.addEventListener("keypress", function (e) {
     switch (String.fromCharCode(e.charCode)) {
-    case "f": enterFullscreen(); break;
-    case "x": exitFullscreen(); break;
-    case "1": lockMouse1(); break;
-    case "2": lockMouse2(); break;
-    case "d": delayedLockMouse1(); break;
+    case "1": lockMouse(); break;
+    case "d": delayedLockMouse(); break;
     case "u": unlockMouse(); break;
-    case "b": enterFullscreenAndLockMouse1(); break;
-    case "B": lockMouse1AndEnterFullscreen(); break;
+    case "b": enterFullscreenAndLockMouse(); break;
     default: moveHTMLCursorToCenter(); break;
     }
   });
@@ -193,34 +166,18 @@
 <body onload="init()"
   title="This tooltip should not be shown if the mouse is locked.">
   <div id="container">
-    <button id="enterFullscreen" onclick="enterFullscreen();">
-      enterFullscreen() [f]
+    <button id="lockMouse" onclick="lockMouse();">
+      lockMouse() [1]
     </button><br>
-    <button id="exitFullscreen" onclick="exitFullscreen();">
-      exitFullscreen() [x]
-    </button><br>
-    <button id="lockMouse1" onclick="lockMouse1();">
-      lockMouse1() [1]
-    </button><br>
-    <button id="lockMouse2" onclick="lockMouse2();">
-      lockMouse2() [2]
-    </button><br>
-    <button id="delayedLockMouse1" onclick="delayedLockMouse1();">
-      delayedLockMouse1() [d]
-    </button><br>
-    <button id="spamLockMouse2" onclick="spamLockMouse2();">
-      spamLockMouse2()
+    <button id="delayedLockMouse" onclick="delayedLockMouse();">
+      delayedLockMouse() [d]
     </button><br>
     <button id="unlockMouse" onclick="unlockMouse();">
       unlockMouse() [u]
     </button><br>
-    <button id="enterFullscreenAndLockMouse1"
-      onclick="enterFullscreenAndLockMouse1()">
-      enterFullscreenAndLockMouse1() [b]
-    </button><br>
-    <button id="lockMouse1AndEnterFullscreen"
-      onclick="lockMouse1AndEnterFullscreen()">
-      lockMouse1AndEnterFullscreen() [B]
+    <button id="enterFullscreenAndLockMouse"
+      onclick="enterFullscreenAndLockMouse()">
+      enterFullscreenAndLockMouse() [b]
     </button><br>
     <div id="lockTarget1">lockTarget1</div>
     <div id="lockTarget2">lockTarget2</div>
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn
index 337565c..4609896 100644
--- a/chrome/test/data/pdf/BUILD.gn
+++ b/chrome/test/data/pdf/BUILD.gn
@@ -30,6 +30,7 @@
     ":nobeep_test",
     ":page_change_test",
     ":params_parser_test",
+    ":post_message_proxy_test",
     ":printing_icon_test",
 
     #":redirects_fail_test",
@@ -157,6 +158,14 @@
   externs_list = [ "$externs_path/test.js" ]
 }
 
+js_library("post_message_proxy_test") {
+  deps = [
+    "../webui:test_util.m",
+    "//chrome/browser/resources/pdf:pdf_viewer_wrapper",
+  ]
+  externs_list = [ "$externs_path/test.js" ]
+}
+
 js_library("printing_icon_test") {
   deps = [ "//chrome/browser/resources/pdf:pdf_viewer_wrapper" ]
   externs_list = [ "$externs_path/test.js" ]
diff --git a/chrome/test/data/pdf/post_message_proxy_test.js b/chrome/test/data/pdf/post_message_proxy_test.js
new file mode 100644
index 0000000..5e1b229
--- /dev/null
+++ b/chrome/test/data/pdf/post_message_proxy_test.js
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js';
+import {PDFViewerElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_wrapper.js';
+
+const viewer =
+    /** @type {!PDFViewerElement} */ (document.body.querySelector('#viewer'));
+
+const tests = [
+  async function testNoToken() {
+    const whenConnectionDenied =
+        eventToPromise('connection-denied-for-testing', viewer);
+    window.postMessage({type: 'connect'});
+    await whenConnectionDenied;
+    chrome.test.succeed();
+  },
+  async function testBadToken() {
+    const whenConnectionDenied =
+        eventToPromise('connection-denied-for-testing', viewer);
+    window.postMessage({type: 'connect', token: 'foo'});
+    await whenConnectionDenied;
+    chrome.test.succeed();
+  },
+];
+
+chrome.test.runTests(tests);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 7ed3da2d..345b265 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -546,7 +546,6 @@
     ":closure_compile_local",
     "cr_components:closure_compile",
     "cr_elements:closure_compile",
-    "download_shelf:closure_compile",
     "inline_login:closure_compile",
     "js/cr:closure_compile",
     "media_router:closure_compile",
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js
index 588dee9..18df63f 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js
@@ -53,4 +53,26 @@
 
     assertTrue(networkIcon.$$('#icon').classList.contains('cellular-locked'));
   });
+
+  test('Display roaming badge', async function() {
+    const networkState = OncMojo.getDefaultNetworkState(
+      mojom.NetworkType.kCellular, 'cellular');
+    networkState.typeState.cellular.roaming = true;
+    networkIcon.networkState = networkState;
+
+    await flushAsync();
+
+    assertFalse(networkIcon.$$('#roaming').hidden);
+  });
+
+  test('Should not display roaming badge', async function() {
+    const networkState = OncMojo.getDefaultNetworkState(
+      mojom.NetworkType.kCellular, 'cellular');
+    networkState.typeState.cellular.roaming = false;
+    networkIcon.networkState = networkState;
+
+    await flushAsync();
+
+    assertTrue(networkIcon.$$('#roaming').hidden);
+  });
 });
diff --git a/chrome/test/data/webui/download_shelf/BUILD.gn b/chrome/test/data/webui/download_shelf/BUILD.gn
deleted file mode 100644
index e9e3a97..0000000
--- a/chrome/test/data/webui/download_shelf/BUILD.gn
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2021 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
-  is_polymer3 = true
-  closure_flags = default_closure_args + mojom_js_args + [
-                    "browser_resolver_prefix_replacements=\"chrome://download-shelf.top-chrome/=./\"",
-                    "js_module_root=" +
-                        rebase_path("//chrome/browser/resources/download_shelf",
-                                    root_build_dir),
-                    "js_module_root=" +
-                        rebase_path("//chrome/test/data/webui", root_build_dir),
-                    "js_module_root=" +
-                        rebase_path("$root_gen_dir/chrome/test/data/webui",
-                                    root_build_dir),
-                    "js_module_root=" + rebase_path(
-                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/download_shelf",
-                            root_build_dir),
-                  ]
-  deps = [ ":download_list_test" ]
-}
-
-js_library("download_list_test") {
-  deps = [
-    ":test_download_shelf_api_proxy",
-    "..:chai_assert",
-    "//chrome/browser/resources/download_shelf:download_shelf",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("test_download_shelf_api_proxy") {
-  deps = [
-    "..:test_browser_proxy.m",
-    "//chrome/browser/resources/download_shelf:download_shelf",
-    "//chrome/browser/ui/webui/download_shelf:mojo_bindings_js_library_for_compile",
-  ]
-}
diff --git a/chrome/test/data/webui/download_shelf/download_list_test.js b/chrome/test/data/webui/download_shelf/download_list_test.js
index 4e4eb96..6554c33b 100644
--- a/chrome/test/data/webui/download_shelf/download_list_test.js
+++ b/chrome/test/data/webui/download_shelf/download_list_test.js
@@ -55,7 +55,7 @@
   setup(async () => {
     testProxy = new TestDownloadShelfApiProxy();
     testProxy.setDownloadItems([testItem(1)]);
-    DownloadShelfApiProxyImpl.instance_ = testProxy;
+    DownloadShelfApiProxyImpl.setInstance(testProxy);
     downloadListElement = /** @type {!DownloadListElement} */ (
         document.createElement('download-list'));
     document.body.appendChild(downloadListElement);
diff --git a/chrome/test/data/webui/download_shelf/test_download_shelf_api_proxy.js b/chrome/test/data/webui/download_shelf/test_download_shelf_api_proxy.js
index d2a72d2..286b108 100644
--- a/chrome/test/data/webui/download_shelf/test_download_shelf_api_proxy.js
+++ b/chrome/test/data/webui/download_shelf/test_download_shelf_api_proxy.js
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {DownloadItem, DownloadShelfApiProxy, DownloadShelfApiProxyImpl, PageCallbackRouter, PageRemote} from 'chrome://download-shelf.top-chrome/download_shelf.js';
+import {DownloadItem, PageCallbackRouter, PageRemote} from 'chrome://download-shelf.top-chrome/download_shelf.js';
 import {TestBrowserProxy} from '../test_browser_proxy.m.js';
 
-/** @implements {DownloadShelfApiProxy} */
 export class TestDownloadShelfApiProxy extends TestBrowserProxy {
   constructor() {
     super([
diff --git a/chrome/test/data/webui/read_later/side_panel/bookmark_folder_test.js b/chrome/test/data/webui/read_later/side_panel/bookmark_folder_test.js
index 237ccba4..fdfc1c3 100644
--- a/chrome/test/data/webui/read_later/side_panel/bookmark_folder_test.js
+++ b/chrome/test/data/webui/read_later/side_panel/bookmark_folder_test.js
@@ -121,8 +121,10 @@
 
   test('OpensBookmark', async () => {
     getChildElements()[1].click();
-    const url = await bookmarksApi.whenCalled('openBookmark');
+    const [url, parentFolderDepth] =
+        await bookmarksApi.whenCalled('openBookmark');
     assertEquals(folder.children[1].url, url);
+    assertEquals(0, parentFolderDepth);
   });
 
   test('MovesFocusDown', () => {
diff --git a/chrome/test/data/webui/read_later/side_panel/test_bookmarks_api_proxy.js b/chrome/test/data/webui/read_later/side_panel/test_bookmarks_api_proxy.js
index d8507fa7..a02b180 100644
--- a/chrome/test/data/webui/read_later/side_panel/test_bookmarks_api_proxy.js
+++ b/chrome/test/data/webui/read_later/side_panel/test_bookmarks_api_proxy.js
@@ -52,9 +52,12 @@
     return Promise.resolve(this.folders_);
   }
 
-  /** @param {string} url */
-  openBookmark(url) {
-    this.methodCalled('openBookmark', url);
+  /**
+   * @param {string} url
+   * @param {number} depth
+   */
+  openBookmark(url, depth) {
+    this.methodCalled('openBookmark', url, depth);
   }
 
   /** @param {!Array<!chrome.bookmarks.BookmarkTreeNode>} folders */
diff --git a/chrome/test/data/webui/settings/chromeos/google_assistant_page_test.js b/chrome/test/data/webui/settings/chromeos/google_assistant_page_test.js
index 3e77a65..67057f99 100644
--- a/chrome/test/data/webui/settings/chromeos/google_assistant_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/google_assistant_page_test.js
@@ -139,6 +139,23 @@
     assertTrue(!!button);
   });
 
+  test('hotwordToggleDisabledForChildUser', function() {
+    page.setPrefValue('settings.voice_interaction.enabled', true);
+    page.set('prefs.settings.voice_interaction.hotword.enabled', {
+      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
+      controlledBy: chrome.settingsPrivate.ControlledBy.CHILD_RESTRICTION,
+      value: false,
+    });
+
+    Polymer.dom.flush();
+    const button = page.$$('#google-assistant-hotword-enable');
+    const indicator = page.$$('#google-assistant-hotword-enable')
+                          .$$('cr-policy-pref-indicator');
+    assertTrue(!!button);
+    assertTrue(!!indicator);
+    assertTrue(button.disabled);
+  });
+
   test('tapOnRetrainVoiceModel', function() {
     let button = page.$$('#retrain-voice-model');
     assertFalse(!!button);
@@ -374,6 +391,25 @@
     assertTrue(dropdown.hasAttribute('disabled'));
   });
 
+  test('dspHotwordDropdownDisabledForChildUser', function() {
+    let indicator = page.$$('#hotword-policy-pref-indicator');
+    assertFalse(!!indicator);
+
+    page.setPrefValue('settings.voice_interaction.enabled', true);
+    page.set('prefs.settings.voice_interaction.hotword.enabled', {
+      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
+      controlledBy: chrome.settingsPrivate.ControlledBy.CHILD_RESTRICTION,
+      value: false,
+    });
+
+    Polymer.dom.flush();
+    const dropdown = page.$$('#dsp-hotword-state');
+    indicator = page.$$('#hotword-policy-pref-indicator');
+    assertTrue(!!dropdown);
+    assertTrue(!!indicator);
+    assertTrue(dropdown.disabled);
+  });
+
   test('dspHotwordDropdownSelection', function() {
     let dropdown = page.$$('#dsp-hotword-state');
     assertFalse(!!dropdown);
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index cb4c680..366c59e 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -272,7 +272,8 @@
  ['AmbientModePage', 'ambient_mode_page_test.m.js'],
  ['AmbientModePhotosPage', 'ambient_mode_photos_page_test.m.js'],
  ['AppsPage', 'apps_page_test.m.js'],
- ['AppNotificationsSubpage', 'app_notifications_subpage_tests.m.js'],
+ // TODO(crbug.com/1229194): Re-enable once flakiness is fixed.
+ //  ['AppNotificationsSubpage', 'app_notifications_subpage_tests.m.js'],
  ['AppManagementAppDetailView', 'app_detail_view_test.m.js'],
  ['AppManagementAppItem', 'app_item_test.m.js'],
  ['AppManagementArcDetailView', 'arc_detail_view_test.m.js'],
diff --git a/chrome/test/webapps/README.md b/chrome/test/webapps/README.md
index 470b4d0..6af388b7 100644
--- a/chrome/test/webapps/README.md
+++ b/chrome/test/webapps/README.md
@@ -129,6 +129,16 @@
 
 The action also needs to be implemented by the testing framework. See the [Testing Framework Implementation README.md](../../browser/ui/views/web_apps/README.md) for more info about how to do that.
 
+#### Adding 'support' for an action
+
+To tell the script that an action is supported by the testing framework (on a given platform), modify the [`framework_supported_actions.csv`](./data/framework_supported_actions.csv) file, and use the following emojis to specify coverage for an action on a given platform:
+
+* 🌕 - Full coverage
+* 🌓 - Partial coverage
+* 🌑 - No coverage
+
+The script reads this file to determine what tests to generate.
+
 ## Script Usage
 
 ### Downloading test data
@@ -140,7 +150,7 @@
 
 This will download the data from the sheet into csv files in the [data/](data/) directory:
 
-* `actions.csv` This lists all actions that can be used and which platforms they are supported on.
+* `actions.csv` This describes all actions that can be used in the required coverage tests (processed or unprocessed).
 * `coverage_required.csv` This is the full list of all tests needed to fully cover the Web App system. The first column specifies the platforms for testing, and the test starts on the fifth column.
 
 ### Generating test descriptions & coverage
diff --git a/chrome/test/webapps/data/framework_supported_actions.csv b/chrome/test/webapps/data/framework_supported_actions.csv
new file mode 100644
index 0000000..3d45bda
--- /dev/null
+++ b/chrome/test/webapps/data/framework_supported_actions.csv
@@ -0,0 +1,29 @@
+# Action base name,                                   Mac,Win,Lin,Cros
+check_app_in_list_not_locally_installed,               🌓, 🌓,  🌓,   🌓,
+check_app_not_in_list,                                 🌕, 🌕,  🌕,   🌕,
+check_app_not_locally_installed_internal,              🌕, 🌕,  🌕,   🌕,
+check_install_icon_not_shown,                          🌕, 🌕,  🌕,   🌕,
+check_install_icon_shown,                              🌕, 🌕,  🌕,   🌕,
+check_launch_icon_not_shown,                           🌕, 🌕,  🌕,   🌕,
+check_launch_icon_shown,                               🌕, 🌕,  🌕,   🌕,
+check_tab_created,                                     🌕, 🌕,  🌕,   🌕,
+check_window_closed,                                   🌕, 🌕,  🌕,   🌕,
+check_window_created,                                  🌕, 🌕,  🌕,   🌕,
+check_window_display_minimal,                          🌕, 🌕,  🌕,   🌕,
+check_window_display_standalone,                       🌕, 🌕,  🌕,   🌕,
+close_pwa,                                             🌕, 🌕,  🌕,   🌕,
+install_locally,                                       🌓, 🌓,  🌓,   🌓,
+install_menu_option,                                   🌓, 🌓,  🌓,   🌓,
+install_omnibox_icon,                                  🌕, 🌕,  🌕,   🌕,
+install_policy_app_tabbed_shortcut,                    🌓, 🌓,  🌓,   🌓,
+install_policy_app_windowed_shortcut,                  🌓, 🌓,  🌓,   🌓,
+launch_internal,                                       🌕, 🌕,  🌕,   🌕,
+manifest_update_display_minimal,                       🌕, 🌕,  🌕,   🌕,
+navigate_browser,                                      🌕, 🌕,  🌕,   🌕,
+set_open_in_tab,                                       🌓, 🌓,  🌓,   🌓,
+set_open_in_window,                                    🌓, 🌓,  🌓,   🌓,
+switch_profile_clients,                                🌕, 🌕,  🌕,   🌕,
+sync_turn_off,                                         🌕, 🌕,  🌕,   🌕,
+sync_turn_on,                                          🌕, 🌕,  🌕,   🌕,
+uninstall_policy_app,                                  🌕, 🌕,  🌕,   🌕,
+uninstall_from_menu,                                   🌕, 🌕,  🌕,   🌑,
diff --git a/chrome/test/webapps/file_reading.py b/chrome/test/webapps/file_reading.py
index 8b04be8..1e78e6c 100755
--- a/chrome/test/webapps/file_reading.py
+++ b/chrome/test/webapps/file_reading.py
@@ -12,15 +12,18 @@
 from typing import Dict, List, Set, Tuple
 
 from models import Action
+from models import ActionCoverage
+from models import ActionType
 from models import ActionsByName
+from models import CoverageTest
+from models import PartialAndFullCoverageByBaseName
 from models import TestIdsByPlatform
 from models import TestIdsByPlatformSet
 from models import TestPartitionDescription
-from models import ActionType
 from models import TestPlatform
-from models import CoverageTest
 
 MIN_COLUMNS_ACTIONS_FILE = 9
+MIN_COLUMNS_SUPPORTED_ACTIONS_FILE = 5
 MIN_COLUMNS_UNPROCESSED_COVERAGE_FILE = 6
 
 
@@ -54,8 +57,64 @@
     return human_friendly_action_name
 
 
-def read_actions_file(actions_csv_file
-                      ) -> Tuple[ActionsByName, Dict[str, str]]:
+def read_platform_supported_actions(csv_file
+                                    ) -> PartialAndFullCoverageByBaseName:
+    """Reads the action base names and coverage from the given csv file.
+
+    Args:
+        csv_file: The comma-separated-values file which lists action base names
+                  and whether it is fully or partially supported.
+
+    Returns:
+        A dictionary of action base name to a set of partially supported
+        and fully supported platforms.
+    """
+    actions_base_name_to_coverage: PartialAndFullCoverageByBaseName = {}
+    column_offset_to_platform = {
+        0: TestPlatform.MAC,
+        1: TestPlatform.WINDOWS,
+        2: TestPlatform.LINUX,
+        3: TestPlatform.CHROME_OS
+    }
+    for i, row in enumerate(csv_file):
+        if not row:
+            continue
+        if row[0].startswith("#"):
+            continue
+        if len(row) < MIN_COLUMNS_SUPPORTED_ACTIONS_FILE:
+            raise ValueError(f"Row {i} does not contain enough entries. "
+                             f"Got {row}.")
+        action_base_name: str = row[0].strip()
+        if action_base_name in actions_base_name_to_coverage:
+            raise ValueError(f"Action base name '{action_base_name}' on "
+                             f"row {i} is already specified.")
+        if not re.fullmatch(r'[a-z_]+', action_base_name):
+            raise ValueError(
+                f"Invald action base name '{action_base_name}' on "
+                f"row {i}. Please use snake_case.")
+        fully_supported_platforms: Set[TestPlatform] = set()
+        partially_supported_platforms: Set[TestPlatform] = set()
+        for j, value in enumerate(row[1:5]):
+            value = value.strip()
+            if not value:
+                continue
+            if value == "🌕":
+                fully_supported_platforms.add(column_offset_to_platform[j])
+            elif value == "🌓":
+                partially_supported_platforms.add(column_offset_to_platform[j])
+            elif value != "🌑":
+                raise ValueError(f"Invalid coverage '{value}' on row {i}. "
+                                 f"Please use '🌕', '🌓', or '🌑'.")
+
+        actions_base_name_to_coverage[action_base_name] = (
+            partially_supported_platforms, fully_supported_platforms)
+    return actions_base_name_to_coverage
+
+
+def read_actions_file(
+        actions_csv_file,
+        supported_platform_actions: PartialAndFullCoverageByBaseName
+) -> Tuple[ActionsByName, Dict[str, str]]:
     """Reads the actions comma-separated-values file.
 
     If modes are specified for an action in the file, then one action is
@@ -72,6 +131,9 @@
     Args:
         actions_csv_file: The comma-separated-values file read to parse all
                           actions.
+        supported_platform_actions: A dictionary of platform to the actions that
+                                    are fully or partially covered on that
+                                    platform.
 
     Returns (actions_by_name,
              action_base_name_to_default_mode):
@@ -84,17 +146,11 @@
     Raises:
         ValueError: The input file is invalid.
     """
-    actions_by_name = {}
-    action_base_name_to_default_mode = {}
-    action_base_names = set()
-    all_output_action_names = []
-    all_short_name = set()
-    column_offset_to_platform = {
-        0: TestPlatform.MAC,
-        1: TestPlatform.WINDOWS,
-        2: TestPlatform.LINUX,
-        3: TestPlatform.CHROME_OS
-    }
+    actions_by_name: Dict[str, Action] = {}
+    action_base_name_to_default_mode: Dict[str, str] = {}
+    action_base_names: Set[str] = set()
+    all_output_action_names: List[str] = []
+    all_short_name: Set[str] = set()
     for i, row in enumerate(actions_csv_file):
         if not row:
             continue
@@ -117,15 +173,6 @@
                 f"Short name '{short_name_base}' on line {i!r} is "
                 f"not populated or already used.")
 
-        fully_supported_platforms = set()
-        partially_supported_platforms = set()
-        for i, value in enumerate(row[4:8]):
-            value = value.strip()
-            if value == "🌕":
-                fully_supported_platforms.add(column_offset_to_platform[i])
-            if value == "🌓":
-                partially_supported_platforms.add(column_offset_to_platform[i])
-
         type = ActionType.STATE_CHANGE
         if action_base_name.startswith("check_"):
             type = ActionType.STATE_CHECK
@@ -142,6 +189,16 @@
             output_action_names = [
                 output.strip() for output in output_actions_str.split("&")
             ]
+            # Keep track of all specified output actions for error checking.
+            # Resolve any parameters if they are specified.
+            all_output_action_names.extend([
+                name.replace("(", "_").rstrip(")")
+                for name in output_action_names
+            ])
+
+        (partially_supported_platforms,
+         fully_supported_platforms) = supported_platform_actions.get(
+             action_base_name, (set(), set()))
 
         modes = [mode.strip() for mode in row[1].split("|")]
         if not modes:
@@ -185,6 +242,12 @@
                 action._output_action_names = output_action_names_with_mode
             actions_by_name[action.name] = action
 
+    unused_supported_actions = set(
+        supported_platform_actions.keys()).difference(action_base_names)
+    if unused_supported_actions:
+        raise ValueError(f"Actions specified as suppored that are not in "
+                         f"the actions list: {unused_supported_actions}.")
+
     # Filter out empty strings from the output_action_base_names.
     all_output_action_names = list(filter(len, all_output_action_names))
     # Make sure all output actions are either resolvable or are base names.
@@ -216,7 +279,6 @@
         assert (action.output_actions)
     return (actions_by_name, action_base_name_to_default_mode)
 
-
 def read_unprocessed_coverage_tests_file(
         coverage_csv_file, actions_by_name: ActionsByName,
         action_base_name_to_default_mode: Dict[str, str]
diff --git a/chrome/test/webapps/file_reading_unittest.py b/chrome/test/webapps/file_reading_unittest.py
index 37442c13c..014d1ead 100755
--- a/chrome/test/webapps/file_reading_unittest.py
+++ b/chrome/test/webapps/file_reading_unittest.py
@@ -8,7 +8,7 @@
 from typing import List
 import unittest
 
-from file_reading import get_tests_in_browsertest
+from file_reading import get_tests_in_browsertest, read_platform_supported_actions
 from file_reading import read_actions_file
 from file_reading import read_unprocessed_coverage_tests_file
 from models import ActionsByName
@@ -20,12 +20,42 @@
 
 
 class TestAnalysisTest(unittest.TestCase):
+    def test_supported_actions(self):
+        supported_actions_filename = os.path.join(
+            TEST_DATA_DIR, "framework_supported_actions.csv")
+
+        with open(supported_actions_filename, "r", encoding="utf-8") \
+                    as supported_actions:
+            supported = read_platform_supported_actions(
+                csv.reader(supported_actions))
+            self.assertEqual(len(supported), 4)
+            (check_a_partial, check_a_full) = supported["check_a"]
+            self.assertEqual(len(check_a_partial), 1)
+            self.assertEqual(len(check_a_full), 3)
+            (check_b_partial, check_b_full) = supported["check_b"]
+            self.assertEqual(len(check_b_partial), 1)
+            self.assertEqual(len(check_b_full), 3)
+            (state_change_a_partial,
+             state_change_a_full) = supported["state_change_a"]
+            self.assertEqual(len(state_change_a_partial), 0)
+            self.assertEqual(len(state_change_a_full), 4)
+            (state_change_b_partial,
+             state_change_b_full) = supported["state_change_b"]
+            self.assertEqual(len(state_change_b_partial), 0)
+            self.assertEqual(len(state_change_b_full), 3)
+
     def test_action_file_reading(self):
         actions_filename = os.path.join(TEST_DATA_DIR, "test_actions.csv")
-        with open(actions_filename) as f:
+        supported_actions_filename = os.path.join(
+            TEST_DATA_DIR, "framework_supported_actions.csv")
+        with open(actions_filename) as f, \
+                open(supported_actions_filename, "r", encoding="utf-8") \
+                    as supported_actions:
+            supported_actions = read_platform_supported_actions(
+                csv.reader(supported_actions))
             actions_csv = csv.reader(f, delimiter=',')
-            (actions, action_base_name_to_default_param
-             ) = read_actions_file(actions_csv)
+            (actions, action_base_name_to_default_param) = read_actions_file(
+                actions_csv, supported_actions)
             self.assertEqual(len(actions), 10)
             self.assertEqual(len(action_base_name_to_default_param), 4)
 
@@ -42,12 +72,18 @@
 
     def test_coverage_file_reading(self):
         actions_filename = os.path.join(TEST_DATA_DIR, "test_actions.csv")
+        supported_actions_filename = os.path.join(
+            TEST_DATA_DIR, "framework_supported_actions.csv")
         actions: ActionsByName = {}
         action_base_name_to_default_param = {}
-        with open(actions_filename) as f:
+        with open(actions_filename) as f, \
+                open(supported_actions_filename, "r", encoding="utf-8") \
+                    as supported_actions:
+            supported_actions = read_platform_supported_actions(
+                csv.reader(supported_actions))
             actions_csv = csv.reader(f, delimiter=',')
-            (actions, action_base_name_to_default_param
-             ) = read_actions_file(actions_csv)
+            (actions, action_base_name_to_default_param) = read_actions_file(
+                actions_csv, supported_actions)
 
         coverage_filename = os.path.join(TEST_DATA_DIR,
                                          "test_unprocessed_coverage.csv")
diff --git a/chrome/test/webapps/generate_framework_tests_and_coverage.py b/chrome/test/webapps/generate_framework_tests_and_coverage.py
index 38cff3f..0790757 100755
--- a/chrome/test/webapps/generate_framework_tests_and_coverage.py
+++ b/chrome/test/webapps/generate_framework_tests_and_coverage.py
@@ -12,9 +12,10 @@
 from io import TextIOWrapper
 import logging
 import os
-from typing import List, Optional
+from typing import List, Optional, Dict
 import csv
 
+from models import ActionCoverage
 from models import ActionNode
 from models import CoverageTestsByPlatform
 from models import CoverageTestsByPlatformSet
@@ -26,7 +27,7 @@
 from graph_analysis import trim_graph_to_platform_actions
 from graph_analysis import generate_framework_tests
 from graph_analysis import generage_graphviz_dot_file
-from file_reading import find_existing_and_disabled_tests
+from file_reading import find_existing_and_disabled_tests, read_platform_supported_actions
 from file_reading import read_actions_file
 from file_reading import read_unprocessed_coverage_tests_file
 from test_analysis import compare_and_print_tests_to_remove_and_add
@@ -45,6 +46,7 @@
 
 
 def generate_framework_tests_and_coverage(
+        supported_framework_action_file: TextIOWrapper,
         actions_file: TextIOWrapper, coverage_required_file: TextIOWrapper,
         custom_partitions: List[TestPartitionDescription],
         default_partition: TestPartitionDescription, coverage_output_dir: str,
@@ -57,8 +59,10 @@
                 continue
             check_partition_prefixes(partition_a, partition_b)
     actions_csv = csv.reader(actions_file, delimiter=',')
-    (actions,
-     action_base_name_to_default_param) = read_actions_file(actions_csv)
+    platform_supported_actions = read_platform_supported_actions(
+        csv.reader(supported_framework_action_file))
+    (actions, action_base_name_to_default_param) = read_actions_file(
+        actions_csv, platform_supported_actions)
 
     coverage_csv = csv.reader(coverage_required_file, delimiter=',')
     required_coverage_tests = read_unprocessed_coverage_tests_file(
@@ -98,7 +102,7 @@
                                                     platform)
             output_coverage_graph_file_name = os.path.join(
                 graph_output_dir,
-                "generated_tests_graph" + platform.suffix + ".dot")
+                "generated_tests_graph_" + platform.suffix + ".dot")
             with open(output_coverage_graph_file_name, "w",
                       encoding="'utf-8") as coverage_graph_file:
                 coverage_graph_file.write("# This is a generated file.\n")
@@ -149,7 +153,7 @@
             required_coverage_by_platform[platform], generated_tests_root_node,
             platform)
         coverage_filename = os.path.join(coverage_output_dir,
-                                         f"coverage{platform.suffix}.tsv")
+                                         f"coverage_{platform.suffix}.tsv")
         with open(coverage_filename, 'w+', encoding="'utf-8") as file:
             file.write("# This is a generated file.\n")
             file.write(f"# Full coverage: {full:.0%}, "
@@ -177,6 +181,8 @@
                         datefmt='%H:%M:%S')
     script_dir = os.path.dirname(os.path.realpath(__file__))
     actions_filename = os.path.join(script_dir, "data", "actions.csv")
+    supported_actions_filename = os.path.join(
+        script_dir, "data", "framework_supported_actions.csv")
     coverage_required_filename = os.path.join(script_dir, "data",
                                               "coverage_required.csv")
     coverage_output_dir = os.path.join(script_dir, "coverage")
@@ -205,11 +211,13 @@
     if options.graphs:
         graph_output_dir = script_dir
 
-    with open(actions_filename, 'r', encoding="'utf-8") as actions_file, open(
-            coverage_required_filename, 'r',
-            encoding="'utf-8") as coverage_file:
-        generate_framework_tests_and_coverage(actions_file, coverage_file,
-                                              custom_partitions,
+    with open(actions_filename, 'r', encoding="utf-8") as actions_file, \
+            open(supported_actions_filename, 'r', encoding="utf-8") \
+                as supported_actions, \
+            open(coverage_required_filename, 'r', encoding="utf-8") \
+                as coverage_file:
+        generate_framework_tests_and_coverage(supported_actions, actions_file,
+                                              coverage_file, custom_partitions,
                                               default_partition,
                                               coverage_output_dir,
                                               graph_output_dir)
diff --git a/chrome/test/webapps/generate_framework_tests_and_coverage_unittest.py b/chrome/test/webapps/generate_framework_tests_and_coverage_unittest.py
index da30ac2..4c370cd 100755
--- a/chrome/test/webapps/generate_framework_tests_and_coverage_unittest.py
+++ b/chrome/test/webapps/generate_framework_tests_and_coverage_unittest.py
@@ -6,6 +6,7 @@
 from io import StringIO
 import os
 import sys
+from typing import Dict
 import unittest
 import tempfile
 
@@ -20,6 +21,9 @@
 class GenerateFrameworkTestsAndCoverageTest(unittest.TestCase):
     def test_coverage(self):
         actions_filename = os.path.join(TEST_DATA_DIR, "test_actions.csv")
+        supported_actions_filename = os.path.join(
+            TEST_DATA_DIR, "framework_supported_actions.csv")
+
         coverage_filename = os.path.join(TEST_DATA_DIR,
                                          "test_unprocessed_coverage.csv")
 
@@ -37,12 +41,15 @@
             test_fixture="WebAppIntegrationBrowserTest")
 
         with open(actions_filename, "r", encoding="utf-8") as actions_file, \
+                open(supported_actions_filename, "r", encoding="utf-8") \
+                    as supported_actions_file, \
                 open(coverage_filename, "r", encoding="utf-8") \
-                as coverage_file, \
+                    as coverage_file, \
                 tempfile.TemporaryDirectory() as output_dir:
             capturedOutput = StringIO()
             sys.stdout = capturedOutput
-            generate_framework_tests_and_coverage(actions_file, coverage_file,
+            generate_framework_tests_and_coverage(supported_actions_file,
+                                                  actions_file, coverage_file,
                                                   custom_partitions,
                                                   default_partition,
                                                   output_dir, None)
@@ -53,7 +60,7 @@
             sys.stdout = sys.__stdout__
 
             for platform in TestPlatform:
-                file_title = "coverage" + platform.suffix + ".tsv"
+                file_title = "coverage_" + platform.suffix + ".tsv"
                 gen_coverage_filename = os.path.join(output_dir, file_title)
                 expected_coverage_filename = os.path.join(
                     TEST_DATA_DIR, "expected_" + file_title)
diff --git a/chrome/test/webapps/models.py b/chrome/test/webapps/models.py
index 45efd08..1e31df00 100755
--- a/chrome/test/webapps/models.py
+++ b/chrome/test/webapps/models.py
@@ -8,7 +8,7 @@
 from enum import Enum
 from enum import unique
 import os
-from typing import FrozenSet, Optional, Set, List, Dict
+from typing import FrozenSet, Optional, Set, List, Dict, Tuple
 
 TestId = str
 
@@ -43,10 +43,10 @@
         suffix: The suffix applied to browsertest files to specify that the
                 file runs on that platform.
     """
-    MAC = ("defined(OS_MAC)", "M", "_mac")
-    WINDOWS = ("defined(OS_WIN)", "W", "_win")
-    LINUX = ("defined(OS_LINUX)", "L", "_linux")
-    CHROME_OS = ("BUILDFLAG(IS_CHROMEOS_ASH)", "C", "_cros")
+    MAC = ("defined(OS_MAC)", "M", "mac")
+    WINDOWS = ("defined(OS_WIN)", "W", "win")
+    LINUX = ("defined(OS_LINUX)", "L", "linux")
+    CHROME_OS = ("BUILDFLAG(IS_CHROMEOS_ASH)", "C", "cros")
 
     def __init__(self, macro: str, char: str, suffix: str):
         self.macro: str = macro
@@ -275,7 +275,7 @@
             # Iterating TestPlatform to get stable ordering.
             for platform in TestPlatform:
                 if platform in platforms:
-                    suffix += platform.suffix
+                    suffix += "_" + platform.suffix
         return (os.path.join(self.browsertest_dir,
                              (self.test_file_prefix + suffix + ".cc")))
 
@@ -285,3 +285,5 @@
 CoverageTestsByPlatformSet = Dict[FrozenSet[TestPlatform], List[CoverageTest]]
 CoverageTestsByPlatform = Dict[TestPlatform, List[CoverageTest]]
 ActionsByName = Dict[str, Action]
+PartialAndFullCoverageByBaseName = Dict[
+    str, Tuple[Set[TestPlatform], Set[TestPlatform]]]
diff --git a/chrome/test/webapps/test_analysis.py b/chrome/test/webapps/test_analysis.py
index 763bccc5..84d5811 100755
--- a/chrome/test/webapps/test_analysis.py
+++ b/chrome/test/webapps/test_analysis.py
@@ -95,13 +95,15 @@
     for platforms, test_ids in existing_tests.items():
         tests_to_remove = []
         prompt_str = ""
+        nice_platform_str = ", ".join(
+            [f"{platform}" for platform in platforms])
         if platforms not in test_ids_to_keep:
             prompt_str = (f"\n\nRemove ALL tests from the file for the "
-                          f"platforms {platforms}:\n")
+                          f"platforms [{nice_platform_str}]:\n")
             tests_to_remove = test_ids
         else:
             prompt_str = (f"\n\nRemove these tests from the file for the "
-                          f" platforms {platforms}:\n")
+                          f" platforms [{nice_platform_str}]:\n")
             tests_to_remove = [
                 test_id for test_id in test_ids
                 if test_id not in test_ids_to_keep[platforms]
diff --git a/chrome/test/webapps/test_analysis_unittest.py b/chrome/test/webapps/test_analysis_unittest.py
index 66fbf85..5f8453e 100755
--- a/chrome/test/webapps/test_analysis_unittest.py
+++ b/chrome/test/webapps/test_analysis_unittest.py
@@ -9,6 +9,7 @@
 import unittest
 
 from file_reading import read_actions_file
+from file_reading import read_platform_supported_actions
 from file_reading import read_unprocessed_coverage_tests_file
 from models import Action
 from models import ActionsByName
@@ -73,12 +74,18 @@
 
     def test_processed_coverage(self):
         actions_filename = os.path.join(TEST_DATA_DIR, "test_actions.csv")
+        supported_actions_filename = os.path.join(
+            TEST_DATA_DIR, "framework_supported_actions.csv")
         actions: ActionsByName = {}
         action_base_name_to_default_param = {}
-        with open(actions_filename, "r", encoding="utf-8") as f:
+        with open(actions_filename, "r", encoding="utf-8") as f, \
+                open(supported_actions_filename, "r", encoding="utf-8") \
+                    as supported_actions_file:
+            supported_actions = read_platform_supported_actions(
+                csv.reader(supported_actions_file))
             actions_csv = csv.reader(f, delimiter=',')
-            (actions, action_base_name_to_default_param
-             ) = read_actions_file(actions_csv)
+            (actions, action_base_name_to_default_param) = read_actions_file(
+                actions_csv, supported_actions)
 
         coverage_filename = os.path.join(TEST_DATA_DIR,
                                          "test_unprocessed_coverage.csv")
diff --git a/chrome/test/webapps/test_data/framework_supported_actions.csv b/chrome/test/webapps/test_data/framework_supported_actions.csv
new file mode 100644
index 0000000..f10119d8
--- /dev/null
+++ b/chrome/test/webapps/test_data/framework_supported_actions.csv
@@ -0,0 +1,5 @@
+# Action base name, Mac,Win,Lin,Cros
+check_a,              🌓, 🌕,  🌕,   🌕,
+check_b,              🌓, 🌕,  🌕,   🌕,
+state_change_a,       🌕, 🌕,  🌕,   🌕,
+state_change_b,       🌕, 🌕,  🌕,   🌑,
diff --git a/chromecast/app/BUILD.gn b/chromecast/app/BUILD.gn
index f7cc24c..7d726b3 100644
--- a/chromecast/app/BUILD.gn
+++ b/chromecast/app/BUILD.gn
@@ -32,7 +32,7 @@
   ]
 
   if (!is_fuchsia) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+    # TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
     deps += [ "//components/crash/core/app" ]
   }
 }
diff --git a/chromecast/app/cast_main_delegate.cc b/chromecast/app/cast_main_delegate.cc
index 82d0b3c..8133643 100644
--- a/chromecast/app/cast_main_delegate.cc
+++ b/chromecast/app/cast_main_delegate.cc
@@ -151,7 +151,7 @@
   bool enable_crash_reporter = !command_line->HasSwitch(
       switches::kDisableCrashReporter);
   if (enable_crash_reporter) {
-  // TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+    // TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
 #if defined(OS_ANDROID)
     base::FilePath log_file;
     base::PathService::Get(FILE_CAST_ANDROID_LOG, &log_file);
diff --git a/chromecast/base/chromecast_config_android.h b/chromecast/base/chromecast_config_android.h
index 58fdeae..cd293023 100644
--- a/chromecast/base/chromecast_config_android.h
+++ b/chromecast/base/chromecast_config_android.h
@@ -7,7 +7,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/no_destructor.h"
 
 namespace chromecast {
 namespace android {
diff --git a/chromecast/base/chromecast_config_android_dummy.cc b/chromecast/base/chromecast_config_android_dummy.cc
index 8698260..33494c3 100644
--- a/chromecast/base/chromecast_config_android_dummy.cc
+++ b/chromecast/base/chromecast_config_android_dummy.cc
@@ -4,6 +4,8 @@
 
 #include "chromecast/base/chromecast_config_android.h"
 
+#include "base/no_destructor.h"
+
 namespace chromecast {
 namespace android {
 
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index f1ef6ae8..38b6011 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -346,7 +346,7 @@
   }
 
   if (!is_fuchsia) {
-    # TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+    # TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
     deps += [
       "//components/crash/content/browser",
       "//components/crash/core/app",
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 90c4ef3..f5ce041 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -753,7 +753,7 @@
       base::GlobalDescriptors::GetInstance()->GetRegion(kAndroidPakDescriptor));
 #endif  // defined(OS_ANDROID)
 #if !defined(OS_FUCHSIA)
-  // TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+  // TODO(crbug.com/753619): Complete crash reporting integration on Fuchsia.
   int crash_signal_fd = GetCrashSignalFD(command_line);
   if (crash_signal_fd >= 0) {
     mappings->Share(kCrashDumpSignal, crash_signal_fd);
diff --git a/chromeos/components/sync_wifi/OWNERS b/chromeos/components/sync_wifi/OWNERS
index 79a68cf..1143a80 100644
--- a/chromeos/components/sync_wifi/OWNERS
+++ b/chromeos/components/sync_wifi/OWNERS
@@ -1,3 +1,2 @@
 jonmann@chromium.org
 khorimoto@chromium.org
-vecore@google.com
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.cc b/chromeos/dbus/shill/fake_shill_manager_client.cc
index 3c383b36..365a4e08 100644
--- a/chromeos/dbus/shill/fake_shill_manager_client.cc
+++ b/chromeos/dbus/shill/fake_shill_manager_client.cc
@@ -69,9 +69,10 @@
   // Note: FindPath uses path expansion which is currently required for the
   // fake shill implementations.
   const base::Value* v = dict.FindPathOfType(key, base::Value::Type::STRING);
-  if (!v)
+  if (!v || !v->is_string())
     return false;
-  return v->GetAsString(result);
+  *result = v->GetString();
+  return true;
 }
 
 std::string GetStringValue(const base::Value& dict, const char* key) {
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc
index 4788ed5..09edefc 100644
--- a/chromeos/dbus/shill/fake_shill_service_client.cc
+++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -525,10 +525,10 @@
   ShillProfileClient::TestInterface* profile_test =
       ShillProfileClient::Get()->GetTestInterface();
   if (property == shill::kProfileProperty) {
-    std::string profile_path;
-    if (value.GetAsString(&profile_path)) {
-      if (!profile_path.empty())
-        profile_test->AddService(profile_path, service_path);
+    const std::string* profile_path = value.GetIfString();
+    if (profile_path) {
+      if (!profile_path->empty())
+        profile_test->AddService(*profile_path, service_path);
     } else {
       LOG(ERROR) << "Profile value is not a String!";
     }
@@ -541,10 +541,8 @@
 
   // Notify the Manager if the state changed (affects DefaultService).
   if (property == shill::kStateProperty) {
-    std::string state;
-    value.GetAsString(&state);
     ShillManagerClient::Get()->GetTestInterface()->ServiceStateChanged(
-        service_path, state);
+        service_path, value.is_string() ? value.GetString() : std::string());
   }
 
   // If the State or Visibility changes, the sort order of service lists may
diff --git a/chromeos/dbus/shill/shill_client_helper.cc b/chromeos/dbus/shill/shill_client_helper.cc
index 970d8d9..8c6d81c 100644
--- a/chromeos/dbus/shill/shill_client_helper.cc
+++ b/chromeos/dbus/shill/shill_client_helper.cc
@@ -385,8 +385,11 @@
     entry_writer.AppendString(it.first);
     const base::Value& value = it.second;
     std::string value_string;
-    if (!value.GetAsString(&value_string))
+    if (value.is_string()) {
+      value_string = value.GetString();
+    } else {
       NET_LOG(ERROR) << "Dictionary value not a string: " << it.first;
+    }
     entry_writer.AppendString(value_string);
     array_writer.CloseContainer(&entry_writer);
   }
@@ -421,8 +424,11 @@
       variant_writer.OpenArray("s", &array_writer);
       for (const auto& value : list->GetList()) {
         std::string value_string;
-        if (!value.GetAsString(&value_string))
+        if (value.is_string()) {
+          value_string = value.GetString();
+        } else {
           NET_LOG(ERROR) << "List value not a string: " << value;
+        }
         array_writer.AppendString(value_string);
       }
       variant_writer.CloseContainer(&array_writer);
diff --git a/chromeos/dbus/shill/shill_ipconfig_client.cc b/chromeos/dbus/shill/shill_ipconfig_client.cc
index fce2835..e72731e 100644
--- a/chromeos/dbus/shill/shill_ipconfig_client.cc
+++ b/chromeos/dbus/shill/shill_ipconfig_client.cc
@@ -113,9 +113,8 @@
       for (const auto& entry : list_value->GetList()) {
         DLOG_IF(ERROR, !entry.is_string())
             << "Unexpected type " << entry.type();
-        std::string str;
-        entry.GetAsString(&str);
-        array_writer.AppendString(str);
+        array_writer.AppendString(entry.is_string() ? entry.GetString()
+                                                    : std::string());
       }
       variant_writer.CloseContainer(&array_writer);
       writer.CloseContainer(&variant_writer);
diff --git a/chromeos/login/auth/authenticator.h b/chromeos/login/auth/authenticator.h
index f4c6e2087..4e5c884a 100644
--- a/chromeos/login/auth/authenticator.h
+++ b/chromeos/login/auth/authenticator.h
@@ -46,10 +46,8 @@
 
   // Initiates login into kiosk mode account identified by |app_account_id|.
   // The |app_account_id| is a generated account id for the account.
-  // |use_guest_mount| specifies whether to force the session to use a
-  // guest mount. If this is false, we use mount a public cryptohome.
-  virtual void LoginAsKioskAccount(const AccountId& app_account_id,
-                                   bool use_guest_mount) = 0;
+  // So called Public mount is used to mount cryptohome.
+  virtual void LoginAsKioskAccount(const AccountId& app_account_id) = 0;
 
   // Initiates login into ARC kiosk mode account identified by |app_account_id|.
   // The |app_account_id| is a generated account id for the account.
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index 6803e43d..9746a11 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -680,26 +680,16 @@
 }
 
 void CryptohomeAuthenticator::LoginAsKioskAccount(
-    const AccountId& app_account_id,
-    bool use_guest_mount) {
+    const AccountId& app_account_id) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
-
-  const AccountId& account_id =
-      use_guest_mount ? user_manager::GuestAccountId() : app_account_id;
   current_state_ = std::make_unique<AuthAttemptState>(
-      UserContext(user_manager::USER_TYPE_KIOSK_APP, account_id),
+      UserContext(user_manager::USER_TYPE_KIOSK_APP, app_account_id),
       false /* unlock */);
 
   remove_user_data_on_failure_ = true;
-  if (!use_guest_mount) {
-    MountPublic(current_state_->AsWeakPtr(),
-                scoped_refptr<CryptohomeAuthenticator>(this),
-                false);  // force_dircrypto_if_available
-  } else {
-    ephemeral_mount_attempted_ = true;
-    MountGuestAndGetHash(current_state_->AsWeakPtr(),
-                         scoped_refptr<CryptohomeAuthenticator>(this));
-  }
+  MountPublic(current_state_->AsWeakPtr(),
+              scoped_refptr<CryptohomeAuthenticator>(this),
+              false);  // force_dircrypto_if_available
 }
 
 void CryptohomeAuthenticator::LoginAsArcKioskAccount(
diff --git a/chromeos/login/auth/cryptohome_authenticator.h b/chromeos/login/auth/cryptohome_authenticator.h
index a9506e1..9f0b49d 100644
--- a/chromeos/login/auth/cryptohome_authenticator.h
+++ b/chromeos/login/auth/cryptohome_authenticator.h
@@ -124,13 +124,10 @@
   // success/failure.
   void LoginAsPublicSession(const UserContext& user_context) override;
 
-  // Initiates login into the kiosk mode account identified by |app_account_id|.
-  // Mounts an ephemeral guest cryptohome if |use_guest_mount| is |true|.
-  // Otherwise, mounts a public cryptohome, which will be ephemeral if the
-  // |DeviceEphemeralUsersEnabled| policy is enabled and non-ephemeral
-  // otherwise.
-  void LoginAsKioskAccount(const AccountId& app_account_id,
-                           bool use_guest_mount) override;
+  // Initiates login into kiosk mode account identified by |app_account_id|.
+  // The |app_account_id| is a generated account id for the account.
+  // So called Public mount is used to mount cryptohome.
+  void LoginAsKioskAccount(const AccountId& app_account_id) override;
 
   // Initiates login into the ARC kiosk mode account identified by
   // |app_account_id|.
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc
index 3ba66a3a..dfc59ecc 100644
--- a/chromeos/login/auth/login_performer.cc
+++ b/chromeos/login/auth/login_performer.cc
@@ -186,13 +186,11 @@
       base::BindOnce(&Authenticator::LoginOffTheRecord, authenticator_.get()));
 }
 
-void LoginPerformer::LoginAsKioskAccount(const AccountId& app_account_id,
-                                         bool use_guest_mount) {
+void LoginPerformer::LoginAsKioskAccount(const AccountId& app_account_id) {
   EnsureAuthenticator();
-  task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&Authenticator::LoginAsKioskAccount, authenticator_.get(),
-                     app_account_id, use_guest_mount));
+  task_runner_->PostTask(FROM_HERE,
+                         base::BindOnce(&Authenticator::LoginAsKioskAccount,
+                                        authenticator_.get(), app_account_id));
 }
 
 void LoginPerformer::LoginAsArcKioskAccount(
diff --git a/chromeos/login/auth/login_performer.h b/chromeos/login/auth/login_performer.h
index 9f4d0d3..b6d41ca 100644
--- a/chromeos/login/auth/login_performer.h
+++ b/chromeos/login/auth/login_performer.h
@@ -77,8 +77,7 @@
   void LoginAsPublicSession(const UserContext& user_context);
 
   // Performs a login into the kiosk mode account with |app_account_id|.
-  void LoginAsKioskAccount(const AccountId& app_account_id,
-                           bool use_guest_mount);
+  void LoginAsKioskAccount(const AccountId& app_account_id);
 
   // Performs a login into the ARC kiosk mode account with |arc_app_account_id|.
   void LoginAsArcKioskAccount(const AccountId& arc_app_account_id);
diff --git a/chromeos/login/auth/stub_authenticator.cc b/chromeos/login/auth/stub_authenticator.cc
index 6bdd9eb..08f616e 100644
--- a/chromeos/login/auth/stub_authenticator.cc
+++ b/chromeos/login/auth/stub_authenticator.cc
@@ -91,8 +91,7 @@
 }
 
 void StubAuthenticator::LoginAsKioskAccount(
-    const AccountId& /* app_account_id */,
-    bool use_guest_mount) {
+    const AccountId& /* app_account_id */) {
   UserContext user_context(user_manager::UserType::USER_TYPE_KIOSK_APP,
                            expected_user_context_.GetAccountId());
   user_context.SetIsUsingOAuth(false);
diff --git a/chromeos/login/auth/stub_authenticator.h b/chromeos/login/auth/stub_authenticator.h
index 693468f..6dd09b9 100644
--- a/chromeos/login/auth/stub_authenticator.h
+++ b/chromeos/login/auth/stub_authenticator.h
@@ -42,8 +42,7 @@
   void AuthenticateToLogin(const UserContext& user_context) override;
   void LoginOffTheRecord() override;
   void LoginAsPublicSession(const UserContext& user_context) override;
-  void LoginAsKioskAccount(const AccountId& app_account_id,
-                           bool use_guest_mount) override;
+  void LoginAsKioskAccount(const AccountId& app_account_id) override;
   void LoginAsArcKioskAccount(const AccountId& app_account_id) override;
   void LoginAsWebKioskAccount(const AccountId& app_account_id) override;
   void OnAuthSuccess() override;
diff --git a/chromeos/network/geolocation_handler.cc b/chromeos/network/geolocation_handler.cc
index 9e70faf..0e6c376 100644
--- a/chromeos/network/geolocation_handler.cc
+++ b/chromeos/network/geolocation_handler.cc
@@ -119,11 +119,10 @@
   cellular_enabled_ = false;
   wifi_enabled_ = false;
   for (const auto& entry : technologies->GetList()) {
-    std::string technology;
-    entry.GetAsString(&technology);
-    if (technology == shill::kTypeWifi) {
+    const std::string* technology = entry.GetIfString();
+    if (technology && *technology == shill::kTypeWifi) {
       wifi_enabled_ = true;
-    } else if (technology == shill::kTypeCellular) {
+    } else if (technology && *technology == shill::kTypeCellular) {
       cellular_enabled_ = true;
     }
     if (wifi_enabled_ && cellular_enabled_)
diff --git a/chromeos/network/managed_state.cc b/chromeos/network/managed_state.cc
index 625f7d8..406abfa 100644
--- a/chromeos/network/managed_state.cc
+++ b/chromeos/network/managed_state.cc
@@ -124,15 +124,14 @@
 bool ManagedState::GetStringValue(const std::string& key,
                                   const base::Value& value,
                                   std::string* out_value) {
-  std::string new_value;
-  if (!value.GetAsString(&new_value)) {
+  if (!value.is_string()) {
     NET_LOG(ERROR) << "Error parsing state value: " << NetworkPathId(path_)
                    << "." << key;
     return false;
   }
-  if (*out_value == new_value)
+  if (*out_value == value.GetString())
     return false;
-  *out_value = new_value;
+  *out_value = value.GetString();
   return true;
 }
 
diff --git a/chromeos/network/network_connect.cc b/chromeos/network/network_connect.cc
index bc3fcb8..e81bcfc 100644
--- a/chromeos/network/network_connect.cc
+++ b/chromeos/network/network_connect.cc
@@ -298,8 +298,8 @@
   // Move empty string properties to properties_to_clear.
   for (base::DictionaryValue::Iterator iter(*properties_to_set);
        !iter.IsAtEnd(); iter.Advance()) {
-    std::string value_str;
-    if (iter.value().GetAsString(&value_str) && value_str.empty())
+    const std::string* value_str = iter.value().GetIfString();
+    if (value_str && (*value_str).empty())
       properties_to_clear->push_back(iter.key());
   }
   // Remove cleared properties from properties_to_set.
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index 524b06f..eeb72c4 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -147,17 +147,17 @@
   } else if (key == shill::kEidProperty) {
     return GetStringValue(key, value, &eid_);
   } else if (key == shill::kProxyConfigProperty) {
-    std::string proxy_config_str;
-    if (!value.GetAsString(&proxy_config_str)) {
+    const std::string* proxy_config_str = value.GetIfString();
+    if (!proxy_config_str) {
       NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
       return false;
     }
 
-    if (proxy_config_str.empty()) {
+    if ((*proxy_config_str).empty()) {
       proxy_config_ = base::Value();
       return true;
     }
-    base::Value proxy_config = onc::ReadDictionaryFromJson(proxy_config_str);
+    base::Value proxy_config = onc::ReadDictionaryFromJson(*proxy_config_str);
     if (!proxy_config.is_dict()) {
       NET_LOG(ERROR) << "Failed to parse " << path() << "." << key;
       proxy_config_ = base::Value();
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index b7a37f9de..456fafb 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -1265,24 +1265,25 @@
   // Updates managed_list and request updates for new entries.
   std::set<std::string> list_entries;
   for (const auto& iter : entries.GetList()) {
-    std::string path;
-    iter.GetAsString(&path);
-    if (path.empty() || path == shill::kFlimflamServicePath) {
-      NET_LOG(ERROR) << "Bad path in type " << type << " Path: " << path;
+    const std::string* path = iter.GetIfString();
+    if (!path)
+      continue;
+    if (!path || (*path).empty() || *path == shill::kFlimflamServicePath) {
+      NET_LOG(ERROR) << "Bad path in type " << type << " Path: " << *path;
       continue;
     }
-    auto found = managed_map.find(path);
+    auto found = managed_map.find(*path);
     if (found == managed_map.end()) {
-      if (list_entries.count(path) != 0) {
-        NET_LOG(ERROR) << "Duplicate entry in list for " << path;
+      if (list_entries.count(*path) != 0) {
+        NET_LOG(ERROR) << "Duplicate entry in list for " << *path;
         continue;
       }
-      managed_list->push_back(ManagedState::Create(type, path));
+      managed_list->push_back(ManagedState::Create(type, *path));
     } else {
       managed_list->push_back(std::move(found->second));
       managed_map.erase(found);
     }
-    list_entries.insert(path);
+    list_entries.insert(*path);
   }
 
   if (type == ManagedState::ManagedType::MANAGED_TYPE_DEVICE) {
@@ -1484,13 +1485,12 @@
     notify_default = false;  // Notify will occur when properties are received.
   }
 
-  std::string value_str;
-  value.GetAsString(&value_str);
+  const std::string* value_str = value.GetIfString();
   if (key == shill::kSignalStrengthProperty || key == shill::kWifiBSsid ||
       key == shill::kWifiFrequency ||
       key == shill::kWifiFrequencyListProperty ||
       key == shill::kNetworkTechnologyProperty ||
-      (key == shill::kDeviceProperty && value_str == "/")) {
+      (key == shill::kDeviceProperty && value_str && *value_str == "/")) {
     // Uninteresting update. This includes 'Device' property changes to "/"
     // (occurs just before a service is removed).
     // For non active networks do not log or send any notifications.
diff --git a/chromeos/network/onc/onc_merger.cc b/chromeos/network/onc/onc_merger.cc
index 5e906ff3..8378f08 100644
--- a/chromeos/network/onc/onc_merger.cc
+++ b/chromeos/network/onc/onc_merger.cc
@@ -55,9 +55,8 @@
                                           &recommended_value))
     return;
   for (const auto& value : recommended_value->GetList()) {
-    std::string entry;
-    if (value.GetAsString(&entry))
-      result->SetKey(entry, base::Value(true));
+    if (value.is_string())
+      result->SetKey(value.GetString(), base::Value(true));
   }
 }
 
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc
index 5b4090a..42ce2a8f 100644
--- a/chromeos/network/onc/onc_translator_shill_to_onc.cc
+++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -291,12 +291,11 @@
       continue;
     }
 
-    std::string shill_str;
-    if (shill_value->GetAsString(&shill_str)) {
+    if (shill_value->is_string()) {
       // Shill wants all Provider/VPN fields to be strings. Translates these
       // strings back to the correct ONC type.
       base::Value translated = ConvertVpnStringToValue(
-          shill_str, field_signature->value_signature->onc_type);
+          shill_value->GetString(), field_signature->value_signature->onc_type);
 
       if (translated.is_none()) {
         NET_LOG(ERROR) << "Shill property '" << shill_property_name
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index e5893e2..d996c01 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -269,12 +269,8 @@
 
   base::Value pem_list(base::Value::Type::LIST);
   for (const auto& entry : guid_ref_list->GetList()) {
-    std::string guid_ref;
-    bool entry_is_string = entry.GetAsString(&guid_ref);
-    DCHECK(entry_is_string);
-
     std::string pem_encoded;
-    if (!GUIDRefToPEMEncoding(certs_by_guid, guid_ref, &pem_encoded))
+    if (!GUIDRefToPEMEncoding(certs_by_guid, entry.GetString(), &pem_encoded))
       return false;
 
     pem_list.Append(pem_encoded);
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc
index 6dd9c88..d831005 100644
--- a/chromeos/network/onc/onc_validator.cc
+++ b/chromeos/network/onc/onc_validator.cc
@@ -293,14 +293,14 @@
 
   base::ListValue repaired_recommended;
   for (const auto& entry : recommended_list->GetList()) {
-    std::string field_name;
-    if (!entry.GetAsString(&field_name)) {
+    const std::string* field_name = entry.GetIfString();
+    if (!field_name) {
       NOTREACHED();  // The types of field values are already verified.
       continue;
     }
 
     const OncFieldSignature* field_signature =
-        GetFieldSignature(object_signature, field_name);
+        GetFieldSignature(object_signature, *field_name);
 
     bool found_error = false;
     std::string error_cause;
@@ -316,7 +316,7 @@
     if (found_error) {
       path_.push_back(::onc::kRecommended);
       std::ostringstream msg;
-      msg << "The " << error_cause << " field '" << field_name
+      msg << "The " << error_cause << " field '" << *field_name
           << "' cannot be recommended.";
       AddValidationIssue(error_on_wrong_recommended_, msg.str());
       path_.pop_back();
@@ -325,7 +325,7 @@
       continue;
     }
 
-    repaired_recommended.AppendString(field_name);
+    repaired_recommended.AppendString(*field_name);
   }
 
   result->SetKey(::onc::kRecommended, std::move(repaired_recommended));
@@ -447,10 +447,10 @@
   if (!value)
     return false;
 
-  std::string str;
+  const std::string* str = value->GetIfString();
   const base::ListValue* list = NULL;
-  if (value->GetAsString(&str)) {
-    if (!str.empty())
+  if (str) {
+    if (!(*str).empty())
       return false;
   } else if (value->GetAsList(&list)) {
     if (!list->GetList().empty())
@@ -502,12 +502,12 @@
   if (object.GetListWithoutPathExpansion(field_name, &list)) {
     path_.push_back(field_name);
     for (const auto& entry : list->GetList()) {
-      std::string value;
-      if (!entry.GetAsString(&value)) {
+      const std::string* value = entry.GetIfString();
+      if (!value) {
         NOTREACHED();  // The types of field values are already verified.
         continue;
       }
-      if (!IsValidValue(value, valid_values)) {
+      if (!IsValidValue(*value, valid_values)) {
         path_.pop_back();
         return false;
       }
diff --git a/chromeos/network/policy_util.cc b/chromeos/network/policy_util.cc
index 1f298b386..794a979 100644
--- a/chromeos/network/policy_util.cc
+++ b/chromeos/network/policy_util.cc
@@ -61,10 +61,8 @@
     }
 
     // If |value| is a string, check if it is a fake credential.
-    std::string string_value;
-    if (value->GetAsString(&string_value) &&
-        onc::FieldIsCredential(signature, field_name)) {
-      if (string_value == kFakeCredential) {
+    if (value->is_string() && onc::FieldIsCredential(signature, field_name)) {
+      if (value->GetString() == kFakeCredential) {
         // The value wasn't modified by the UI, thus we remove the field to keep
         // the existing value that is stored in Shill.
         entries_to_remove.push_back(field_name);
diff --git a/chromeos/network/prohibited_technologies_handler.cc b/chromeos/network/prohibited_technologies_handler.cc
index c511307..cc1f4d99 100644
--- a/chromeos/network/prohibited_technologies_handler.cc
+++ b/chromeos/network/prohibited_technologies_handler.cc
@@ -66,11 +66,8 @@
   // enforced
   session_prohibited_technologies_.clear();
   for (const auto& item : prohibited_list->GetList()) {
-    std::string prohibited_technology;
-    bool item_is_string = item.GetAsString(&prohibited_technology);
-    DCHECK(item_is_string);
     std::string translated_tech =
-        network_util::TranslateONCTypeToShill(prohibited_technology);
+        network_util::TranslateONCTypeToShill(item.GetString());
     if (!translated_tech.empty())
       session_prohibited_technologies_.push_back(translated_tech);
   }
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index 843b456..a4dc7e3 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -370,7 +370,8 @@
                                                   const base::Value& value) {
   if (key == shill::kDefaultServiceProperty) {
     std::string service_path;
-    value.GetAsString(&service_path);
+    if (value.is_string())
+      service_path = value.GetString();
     NET_LOG(EVENT) << "Manager.DefaultService = "
                    << NetworkPathId(service_path);
     listener_->DefaultNetworkServiceChanged(service_path);
@@ -403,20 +404,15 @@
     const base::ListValue* vlist = GetListValue(key, value);
     if (vlist)
       UpdateUninitializedTechnologies(*vlist);
-  } else if (key == shill::kProhibitedTechnologiesProperty) {
-    std::string prohibited_technologies;
-    if (value.GetAsString(&prohibited_technologies))
-      UpdateProhibitedTechnologies(prohibited_technologies);
+  } else if (key == shill::kProhibitedTechnologiesProperty &&
+             value.is_string()) {
+    UpdateProhibitedTechnologies(value.GetString());
   } else if (key == shill::kProfilesProperty) {
     listener_->ProfileListChanged(value);
-  } else if (key == shill::kCheckPortalListProperty) {
-    std::string check_portal_list;
-    if (value.GetAsString(&check_portal_list))
-      listener_->CheckPortalListChanged(check_portal_list);
-  } else if (key == shill::kDhcpPropertyHostnameProperty) {
-    std::string hostname;
-    if (value.GetAsString(&hostname))
-      listener_->HostnameChanged(hostname);
+  } else if (key == shill::kCheckPortalListProperty && value.is_string()) {
+    listener_->CheckPortalListChanged(value.GetString());
+  } else if (key == shill::kDhcpPropertyHostnameProperty && value.is_string()) {
+    listener_->HostnameChanged(value.GetString());
   } else {
     VLOG(2) << "Ignored Manager Property: " << key;
   }
@@ -429,19 +425,18 @@
   NET_LOG(DEBUG) << "UpdateProperties: " << ManagedState::TypeToString(type)
                  << ": " << entries.GetSize();
   for (const auto& entry : entries.GetList()) {
-    std::string path;
-    entry.GetAsString(&path);
-    if (path.empty())
+    const std::string* path = entry.GetIfString();
+    if (!path || (*path).empty())
       continue;
 
     // We add a special case for devices here to work around an issue in shill
     // that prevents it from sending property changed signals for cellular
     // devices (see crbug.com/321854).
     if (type == ManagedState::MANAGED_TYPE_DEVICE ||
-        requested_updates.find(path) == requested_updates.end()) {
-      RequestProperties(type, path);
+        requested_updates.find(*path) == requested_updates.end()) {
+      RequestProperties(type, *path);
     }
-    new_requested_updates.insert(path);
+    new_requested_updates.insert(*path);
   }
   requested_updates.swap(new_requested_updates);
 }
@@ -453,27 +448,26 @@
                                                    : observed_devices_;
   ShillPropertyObserverMap new_observed;
   for (const auto& entry : entries.GetList()) {
-    std::string path;
-    entry.GetAsString(&path);
-    if (path.empty())
+    const std::string* path = entry.GetIfString();
+    if (!path || (*path).empty())
       continue;
-    auto iter = observer_map.find(path);
+    auto iter = observer_map.find(*path);
     std::unique_ptr<ShillPropertyObserver> observer;
     if (iter != observer_map.end()) {
       observer = std::move(iter->second);
     } else {
       // Create an observer for future updates.
       observer = std::make_unique<ShillPropertyObserver>(
-          type, path,
+          type, *path,
           base::BindRepeating(&ShillPropertyHandler::PropertyChangedCallback,
                               AsWeakPtr()));
     }
     auto result =
-        new_observed.insert(std::make_pair(path, std::move(observer)));
+        new_observed.insert(std::make_pair(*path, std::move(observer)));
     if (!result.second) {
-      NET_LOG(ERROR) << path << " is duplicated in the list.";
+      NET_LOG(ERROR) << *path << " is duplicated in the list.";
     }
-    observer_map.erase(path);
+    observer_map.erase(*path);
     // Limit the number of observed services.
     if (new_observed.size() >= kMaxObserved)
       break;
@@ -641,16 +635,15 @@
     ManagedState::ManagedType type,
     const std::string& path,
     const base::Value& ip_config_path_value) {
-  std::string ip_config_path;
-  if (!ip_config_path_value.GetAsString(&ip_config_path) ||
-      ip_config_path.empty()) {
+  const std::string* ip_config_path = ip_config_path_value.GetIfString();
+  if (!ip_config_path || (*ip_config_path).empty()) {
     NET_LOG(ERROR) << "Invalid IPConfig: " << path;
     return;
   }
   ShillIPConfigClient::Get()->GetProperties(
-      dbus::ObjectPath(ip_config_path),
+      dbus::ObjectPath(*ip_config_path),
       base::BindOnce(&ShillPropertyHandler::GetIPConfigCallback, AsWeakPtr(),
-                     type, path, ip_config_path));
+                     type, path, *ip_config_path));
 }
 
 void ShillPropertyHandler::RequestIPConfigsList(
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc
index 808652c..891ea94 100644
--- a/chromeos/network/shill_property_handler_unittest.cc
+++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -139,9 +139,8 @@
       return;
     entries_[type].clear();
     for (const auto& entry : entries.GetList()) {
-      std::string path;
-      if (entry.GetAsString(&path))
-        entries_[type].push_back(path);
+      if (entry.is_string())
+        entries_[type].push_back(entry.GetString());
     }
   }
 
diff --git a/chromeos/network/shill_property_util.cc b/chromeos/network/shill_property_util.cc
index 3ae03ed..41f07be 100644
--- a/chromeos/network/shill_property_util.cc
+++ b/chromeos/network/shill_property_util.cc
@@ -190,12 +190,13 @@
 
 std::unique_ptr<NetworkUIData> GetUIDataFromValue(
     const base::Value& ui_data_value) {
-  std::string ui_data_str;
-  if (!ui_data_value.GetAsString(&ui_data_str))
+  const std::string* ui_data_str = ui_data_value.GetIfString();
+  if (!ui_data_str)
     return nullptr;
-  if (ui_data_str.empty())
+  if ((*ui_data_str).empty())
     return std::make_unique<NetworkUIData>();
-  base::Value ui_data_dict = chromeos::onc::ReadDictionaryFromJson(ui_data_str);
+  base::Value ui_data_dict =
+      chromeos::onc::ReadDictionaryFromJson(*ui_data_str);
   if (!ui_data_dict.is_dict())
     return nullptr;
   return std::make_unique<NetworkUIData>(ui_data_dict);
diff --git a/chromeos/services/assistant/public/proto/consent_flow_ui.proto b/chromeos/services/assistant/public/proto/consent_flow_ui.proto
index 559b6340..ca9992a 100644
--- a/chromeos/services/assistant/public/proto/consent_flow_ui.proto
+++ b/chromeos/services/assistant/public/proto/consent_flow_ui.proto
@@ -93,6 +93,18 @@
       //
       // Required.
       repeated string footer_paragraph = 9;
+
+      message LearnMoreDialog {
+        // Title heading of the dialog.
+        optional string title = 1;
+        // May contain HTML tags for like bold and hyperlinks.
+        repeated string paragraph = 2;
+        // Bottom button that closes dialog.
+        optional string dismiss_button = 3;
+      }
+      // Learn more dialog that can be opened from the Learn More CTA within
+      // setting_zippy.
+      optional LearnMoreDialog learn_more_dialog = 13;
     }
     optional ActivityControlUi activity_control_ui = 1;
 
diff --git a/chromeos/services/chromebox_for_meetings/public/mojom/BUILD.gn b/chromeos/services/chromebox_for_meetings/public/mojom/BUILD.gn
index b1d01b1..231a7b85 100644
--- a/chromeos/services/chromebox_for_meetings/public/mojom/BUILD.gn
+++ b/chromeos/services/chromebox_for_meetings/public/mojom/BUILD.gn
@@ -7,6 +7,7 @@
 mojom("mojom") {
   sources = [
     "cfm_browser.mojom",
+    "cfm_network_settings.mojom",
     "cfm_service_manager.mojom",
     "meet_devices_diagnostics.mojom",
     "meet_devices_info.mojom",
diff --git a/chromeos/services/chromebox_for_meetings/public/mojom/cfm_network_settings.mojom b/chromeos/services/chromebox_for_meetings/public/mojom/cfm_network_settings.mojom
new file mode 100644
index 0000000..5ee11c3dc
--- /dev/null
+++ b/chromeos/services/chromebox_for_meetings/public/mojom/cfm_network_settings.mojom
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Next MinVersion: 1
+
+module chromeos.cfm.mojom;
+
+// Interface for opening a network settings dialog.
+interface CfmNetworkSettings {
+  // Displays the dialog if not already open.
+  ShowDialog@0();
+};
diff --git a/components/autofill/content/browser/BUILD.gn b/components/autofill/content/browser/BUILD.gn
index 49efeda..a1703e23 100644
--- a/components/autofill/content/browser/BUILD.gn
+++ b/components/autofill/content/browser/BUILD.gn
@@ -14,6 +14,8 @@
     "content_autofill_driver_factory.h",
     "content_autofill_router.cc",
     "content_autofill_router.h",
+    "form_forest.cc",
+    "form_forest.h",
     "risk/fingerprint.cc",
     "risk/fingerprint.h",
   ]
@@ -71,6 +73,8 @@
   sources = [
     "content_autofill_driver_test_api.h",
     "content_autofill_router_test_api.h",
+    "form_forest_test_api.cc",
+    "form_forest_test_api.h",
   ]
 
   public_deps = [ ":browser" ]
@@ -83,6 +87,7 @@
   sources = [
     "autofill_internals_log_router_unittest.cc",
     "content_autofill_driver_unittest.cc",
+    "form_forest_unittest.cc",
   ]
 
   deps = [
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS
index 05fe6995c..ca13e57 100644
--- a/components/autofill/content/browser/DEPS
+++ b/components/autofill/content/browser/DEPS
@@ -9,6 +9,7 @@
   "+services/device/public",
   "+services/service_manager/public/mojom",
   "+third_party/blink/public/common",
+  "+third_party/blink/public/mojom/permissions_policy",
 ]
 
 specific_include_rules = {
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc
index cc741b8..2f65d4184 100644
--- a/components/autofill/content/browser/content_autofill_driver.cc
+++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -99,7 +99,10 @@
   }
 }
 
-ContentAutofillDriver::~ContentAutofillDriver() = default;
+ContentAutofillDriver::~ContentAutofillDriver() {
+  if (autofill_router_)  // Can be nullptr only in tests.
+    autofill_router_->UnregisterDriver(this);
+}
 
 void ContentAutofillDriver::TriggerReparse() {
   GetAutofillAgent()->TriggerReparse();
@@ -247,11 +250,11 @@
 }
 
 void ContentAutofillDriver::RendererShouldAcceptDataListSuggestionImpl(
-    const FieldGlobalId& field,
+    const FieldRendererId& field,
     const std::u16string& value) {
   if (!RendererIsAvailable())
     return;
-  GetAutofillAgent()->AcceptDataListSuggestion(field.renderer_id, value);
+  GetAutofillAgent()->AcceptDataListSuggestion(field, value);
 }
 
 void ContentAutofillDriver::RendererShouldClearFilledSectionImpl() {
@@ -267,27 +270,27 @@
 }
 
 void ContentAutofillDriver::RendererShouldFillFieldWithValueImpl(
-    const FieldGlobalId& field,
+    const FieldRendererId& field,
     const std::u16string& value) {
   if (!RendererIsAvailable())
     return;
-  GetAutofillAgent()->FillFieldWithValue(field.renderer_id, value);
+  GetAutofillAgent()->FillFieldWithValue(field, value);
 }
 
 void ContentAutofillDriver::RendererShouldPreviewFieldWithValueImpl(
-    const FieldGlobalId& field,
+    const FieldRendererId& field,
     const std::u16string& value) {
   if (!RendererIsAvailable())
     return;
-  GetAutofillAgent()->PreviewFieldWithValue(field.renderer_id, value);
+  GetAutofillAgent()->PreviewFieldWithValue(field, value);
 }
 
 void ContentAutofillDriver::RendererShouldSetSuggestionAvailabilityImpl(
-    const FieldGlobalId& field,
+    const FieldRendererId& field,
     const mojom::AutofillState state) {
   if (!RendererIsAvailable())
     return;
-  GetAutofillAgent()->SetSuggestionAvailability(field.renderer_id, state);
+  GetAutofillAgent()->SetSuggestionAvailability(field, state);
 }
 
 void ContentAutofillDriver::SendAutofillTypePredictionsToRenderer(
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index c8afc90..49f1e81 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -185,16 +185,16 @@
                                   const FormData& data);
   void SendAutofillTypePredictionsToRendererImpl(
       const std::vector<FormDataPredictions>& forms);
-  void RendererShouldAcceptDataListSuggestionImpl(const FieldGlobalId& field,
+  void RendererShouldAcceptDataListSuggestionImpl(const FieldRendererId& field,
                                                   const std::u16string& value);
   void RendererShouldClearFilledSectionImpl();
   void RendererShouldClearPreviewedFormImpl();
-  void RendererShouldFillFieldWithValueImpl(const FieldGlobalId& field,
+  void RendererShouldFillFieldWithValueImpl(const FieldRendererId& field,
                                             const std::u16string& value);
-  void RendererShouldPreviewFieldWithValueImpl(const FieldGlobalId& field,
+  void RendererShouldPreviewFieldWithValueImpl(const FieldRendererId& field,
                                                const std::u16string& value);
   void RendererShouldSetSuggestionAvailabilityImpl(
-      const FieldGlobalId& field,
+      const FieldRendererId& field,
       const mojom::AutofillState state);
   void SendFieldsEligibleForManualFillingToRendererImpl(
       const std::vector<FieldRendererId>& fields);
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 611d5e0..82845a66 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -16,11 +16,14 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/autofill/content/browser/content_autofill_router.h"
 #include "components/autofill/core/browser/autofill_external_delegate.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/browser_autofill_manager.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data_predictions.h"
 #include "components/autofill/core/common/unique_ids.h"
@@ -343,7 +346,8 @@
   using ContentAutofillDriver::DidNavigateFrame;
 };
 
-class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
+class ContentAutofillDriverTest : public content::RenderViewHostTestHarness,
+                                  public ::testing::WithParamInterface<bool> {
  public:
   enum class NavigationType {
     kNormal,
@@ -351,6 +355,15 @@
     kServedFromBackForwardCache,
     kPrerenderedPageActivation,
   };
+
+  ContentAutofillDriverTest() : autofill_across_iframes_(GetParam()) {
+    std::vector<base::Feature> enabled;
+    std::vector<base::Feature> disabled;
+    (autofill_across_iframes_ ? enabled : disabled)
+        .push_back(features::kAutofillAcrossIframes);
+    scoped_feature_list_.InitWithFeatures(enabled, disabled);
+  }
+
   void SetUp() override {
     content::RenderViewHostTestHarness::SetUp();
     // This needed to keep the WebContentsObserverConsistencyChecker checks
@@ -398,6 +411,19 @@
   }
 
  protected:
+  FormData SeeAddressFormData() {
+    FormData form;
+    test::CreateTestAddressFormData(&form);
+    std::vector<FormData> augmented_forms;
+    EXPECT_CALL(*driver_->mock_browser_autofill_manager(), ShouldParseForms(_))
+        .WillOnce(DoAll(SaveArg<0>(&augmented_forms), Return(false)));
+    driver_->FormsSeen({form});
+    return augmented_forms.front();
+  }
+
+  bool autofill_across_iframes_ = false;
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   std::unique_ptr<MockAutofillClient> test_autofill_client_;
   std::unique_ptr<ContentAutofillRouter> router_;
   std::unique_ptr<TestContentAutofillDriver> driver_;
@@ -405,27 +431,27 @@
   FakeAutofillAgent fake_agent_;
 };
 
-TEST_F(ContentAutofillDriverTest, NavigatedMainFrameDifferentDocument) {
+TEST_P(ContentAutofillDriverTest, NavigatedMainFrameDifferentDocument) {
   EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset());
   Navigate(NavigationType::kNormal);
 }
 
-TEST_F(ContentAutofillDriverTest, NavigatedMainFrameSameDocument) {
+TEST_P(ContentAutofillDriverTest, NavigatedMainFrameSameDocument) {
   EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset()).Times(0);
   Navigate(NavigationType::kSameDocument);
 }
 
-TEST_F(ContentAutofillDriverTest, NavigatedMainFrameFromBackForwardCache) {
+TEST_P(ContentAutofillDriverTest, NavigatedMainFrameFromBackForwardCache) {
   EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset()).Times(0);
   Navigate(NavigationType::kServedFromBackForwardCache);
 }
 
-TEST_F(ContentAutofillDriverTest, NavigatedMainFramePrerenderedPageActivation) {
+TEST_P(ContentAutofillDriverTest, NavigatedMainFramePrerenderedPageActivation) {
   EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset()).Times(0);
   Navigate(NavigationType::kPrerenderedPageActivation);
 }
 
-TEST_F(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfForm) {
+TEST_P(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfForm) {
   NavigateAndCommit(GURL("https://username:password@hostname/path?query#hash"));
   FormData form;
   form.fields.push_back(FormFieldData());
@@ -455,7 +481,7 @@
   EXPECT_EQ(form2.fields.front().host_frame, form2.fields.front().host_frame);
 }
 
-TEST_F(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfField) {
+TEST_P(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfField) {
   NavigateAndCommit(GURL("https://username:password@hostname/path?query#hash"));
   FormData form;
   FormFieldData field;
@@ -471,10 +497,9 @@
   EXPECT_EQ(field2.host_frame, field.host_frame);
 }
 
-TEST_F(ContentAutofillDriverTest, FormDataSentToRenderer_FillForm) {
-  int input_page_id = 42;
-  FormData input_form_data;
-  test::CreateTestAddressFormData(&input_form_data);
+TEST_P(ContentAutofillDriverTest, FormDataSentToRenderer_FillForm) {
+  int input_page_id = autofill_across_iframes_ ? kCrossFrameFill : 42;
+  FormData input_form_data = SeeAddressFormData();
   base::RunLoop run_loop;
   fake_agent_.SetQuitLoopClosure(run_loop.QuitClosure());
   driver_->SendFormDataToRenderer(input_page_id,
@@ -494,10 +519,9 @@
                   .SameFormAs(output_form_data));
 }
 
-TEST_F(ContentAutofillDriverTest, FormDataSentToRenderer_PreviewForm) {
-  int input_page_id = 42;
-  FormData input_form_data;
-  test::CreateTestAddressFormData(&input_form_data);
+TEST_P(ContentAutofillDriverTest, FormDataSentToRenderer_PreviewForm) {
+  int input_page_id = autofill_across_iframes_ ? kCrossFrameFill : 42;
+  FormData input_form_data = SeeAddressFormData();
   base::RunLoop run_loop;
   fake_agent_.SetQuitLoopClosure(run_loop.QuitClosure());
   driver_->SendFormDataToRenderer(input_page_id,
@@ -516,7 +540,7 @@
   EXPECT_TRUE(input_form_data.SameFormAs(output_form_data));
 }
 
-TEST_F(ContentAutofillDriverTest, TypePredictionsSentToRendererWhenEnabled) {
+TEST_P(ContentAutofillDriverTest, TypePredictionsSentToRendererWhenEnabled) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kShowAutofillTypePredictions);
 
@@ -548,8 +572,8 @@
   EXPECT_EQ(expected_type_predictions, output_type_predictions);
 }
 
-TEST_F(ContentAutofillDriverTest, AcceptDataListSuggestion) {
-  FieldGlobalId field = test::MakeFieldGlobalId();
+TEST_P(ContentAutofillDriverTest, AcceptDataListSuggestion) {
+  FieldGlobalId field = SeeAddressFormData().fields.front().global_id();
   std::u16string input_value(u"barfoo");
   std::u16string output_value;
 
@@ -563,7 +587,8 @@
   EXPECT_EQ(input_value, output_value);
 }
 
-TEST_F(ContentAutofillDriverTest, ClearFilledSectionSentToRenderer) {
+TEST_P(ContentAutofillDriverTest, ClearFilledSectionSentToRenderer) {
+  SeeAddressFormData();
   base::RunLoop run_loop;
   fake_agent_.SetQuitLoopClosure(run_loop.QuitClosure());
   driver_->RendererShouldClearFilledSection();
@@ -572,7 +597,8 @@
   EXPECT_TRUE(fake_agent_.GetCalledClearSection());
 }
 
-TEST_F(ContentAutofillDriverTest, ClearPreviewedFormSentToRenderer) {
+TEST_P(ContentAutofillDriverTest, ClearPreviewedFormSentToRenderer) {
+  SeeAddressFormData();
   base::RunLoop run_loop;
   fake_agent_.SetQuitLoopClosure(run_loop.QuitClosure());
   driver_->RendererShouldClearPreviewedForm();
@@ -581,8 +607,8 @@
   EXPECT_TRUE(fake_agent_.GetCalledClearPreviewedForm());
 }
 
-TEST_F(ContentAutofillDriverTest, FillFieldWithValue) {
-  FieldGlobalId field = test::MakeFieldGlobalId();
+TEST_P(ContentAutofillDriverTest, FillFieldWithValue) {
+  FieldGlobalId field = SeeAddressFormData().fields.front().global_id();
   std::u16string input_value(u"barqux");
   std::u16string output_value;
 
@@ -595,8 +621,8 @@
   EXPECT_EQ(input_value, output_value);
 }
 
-TEST_F(ContentAutofillDriverTest, PreviewFieldWithValue) {
-  FieldGlobalId field = test::MakeFieldGlobalId();
+TEST_P(ContentAutofillDriverTest, PreviewFieldWithValue) {
+  FieldGlobalId field = SeeAddressFormData().fields.front().global_id();
   std::u16string input_value(u"barqux");
   std::u16string output_value;
 
@@ -610,7 +636,7 @@
   EXPECT_EQ(input_value, output_value);
 }
 
-TEST_F(ContentAutofillDriverTest, EnableHeavyFormDataScraping) {
+TEST_P(ContentAutofillDriverTest, EnableHeavyFormDataScraping) {
   struct TestCase {
     version_info::Channel channel;
     bool heavy_scraping_enabled;
@@ -637,4 +663,8 @@
   }
 }
 
+INSTANTIATE_TEST_SUITE_P(ContentAutofillDriverTest,
+                         ContentAutofillDriverTest,
+                         testing::Bool());
+
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_router.cc b/components/autofill/content/browser/content_autofill_router.cc
index 1dd0e31..d924d03 100644
--- a/components/autofill/content/browser/content_autofill_router.cc
+++ b/components/autofill/content/browser/content_autofill_router.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/debug/dump_without_crashing.h"
 #include "base/functional/invoke.h"
 #include "base/ranges/algorithm.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -19,15 +20,87 @@
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
 
+// AFCHECK(condition[, error_handler]) creates a crash dump and executes
+// |error_handler| if |condition| is false.
+// TODO(crbug/1187842): Replace AFCHECK() with DCHECK().
+#if DCHECK_IS_ON()
+#define AFCHECK(condition, ...) DCHECK(condition)
+#else
+#define AFCHECK(condition, ...)           \
+  {                                       \
+    if (!(condition)) {                   \
+      base::debug::DumpWithoutCrashing(); \
+      __VA_ARGS__;                        \
+    }                                     \
+  }
+#endif
+
 namespace autofill {
 
+namespace {
+
+// Calls |fun| for all drivers in |form_forest|.
+template <typename UnaryFunction>
+void ForEachFrame(internal::FormForest& form_forest, UnaryFunction fun) {
+  DCHECK(base::FeatureList::IsEnabled(features::kAutofillAcrossIframes));
+  for (const std::unique_ptr<internal::FormForest::FrameData>& some_frame :
+       form_forest.frame_datas()) {
+    AFCHECK(some_frame, continue);
+    if (some_frame->driver)
+      base::invoke(fun, *some_frame->driver);
+  }
+}
+
+}  // namespace
+
 ContentAutofillRouter::ContentAutofillRouter() = default;
 ContentAutofillRouter::~ContentAutofillRouter() = default;
 
+ContentAutofillDriver* ContentAutofillRouter::DriverOfFrame(
+    LocalFrameToken frame) {
+  DCHECK(base::FeatureList::IsEnabled(features::kAutofillAcrossIframes));
+  const auto& frames = form_forest_.frame_datas();
+  auto it = frames.find(frame);
+  return it != frames.end() ? (*it)->driver : nullptr;
+}
+
 void ContentAutofillRouter::UnregisterDriver(ContentAutofillDriver* driver) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes))
     return;
-  NOTREACHED();
+
+  AFCHECK(driver, return );
+
+  for (const std::unique_ptr<internal::FormForest::FrameData>& frame :
+       form_forest_.frame_datas()) {
+    AFCHECK(frame, continue);
+    if (frame->driver == driver) {
+      form_forest_.EraseFrame(frame->frame_token);
+      break;
+    }
+  }
+
+  if (last_queried_source_ == driver)
+    SetLastQueriedSource(nullptr);
+  if (last_queried_target_ == driver)
+    SetLastQueriedTarget(nullptr);
+}
+
+void ContentAutofillRouter::Reset() {
+  form_forest_.Reset();
+  SetLastQueriedSource(nullptr);
+  SetLastQueriedTarget(nullptr);
+}
+
+void ContentAutofillRouter::SetLastQueriedSource(
+    ContentAutofillDriver* source) {
+  if (last_queried_source_ && last_queried_target_ != source)
+    last_queried_source_->UnsetKeyPressHandlerImpl();
+  last_queried_source_ = source;
+}
+
+void ContentAutofillRouter::SetLastQueriedTarget(
+    ContentAutofillDriver* target) {
+  last_queried_target_ = target;
 }
 
 void ContentAutofillRouter::SetKeyPressHandler(
@@ -37,7 +110,9 @@
     source->SetKeyPressHandlerImpl(handler);
     return;
   }
-  NOTREACHED();
+
+  AFCHECK(last_queried_source_, return );
+  last_queried_source_->SetKeyPressHandlerImpl(handler);
 }
 
 void ContentAutofillRouter::UnsetKeyPressHandler(
@@ -46,18 +121,81 @@
     source->UnsetKeyPressHandlerImpl();
     return;
   }
-  NOTREACHED();
+
+  AFCHECK(last_queried_source_, return );
+  last_queried_source_->UnsetKeyPressHandlerImpl();
 }
 
 // Routing of events called by the renderer:
 
-void ContentAutofillRouter::FormsSeen(ContentAutofillDriver* source,
-                                      const std::vector<FormData>& forms) {
+// Calls TriggerReparse() on all ContentAutofillDrivers in |form_forest_| as
+// well as their ancestor ContentAutofillDrivers.
+//
+// An ancestor might not be contained in the form tree itself: if the ancestor
+// contained only invisible iframe(s) and no interesting fields, it would not be
+// sent to the browser. In the meantime, these frames may have become visible.
+//
+// The typical use case is that some frame triggers reparses on its own
+// initiative and triggers an event. Then ContentAutofillRouter's event handler
+// tells the other frames to reparse, too, using TriggerReparseExcept(source).
+void ContentAutofillRouter::TriggerReparseExcept(
+    ContentAutofillDriver* exception) {
+  DCHECK(base::FeatureList::IsEnabled(features::kAutofillAcrossIframes));
+
+  base::flat_set<ContentAutofillDriver*> already_triggered;
+  ForEachFrame(form_forest_, [&](ContentAutofillDriver& driver) mutable {
+    content::RenderFrameHost* rfh = driver.render_frame_host();
+    do {
+      // Trigger reparse for |rfh| and all its ancestors (as some
+      // ancestors may not be in the forest).
+      ContentAutofillDriver* driver =
+          ContentAutofillDriver::GetForRenderFrameHost(rfh);
+      AFCHECK(driver, continue);
+      if (driver != exception && !base::Contains(already_triggered, driver)) {
+        driver->TriggerReparse();
+        already_triggered.insert(driver);
+      }
+    } while ((rfh = rfh->GetParent()) != nullptr);
+  });
+}
+
+void ContentAutofillRouter::FormsSeen(
+    ContentAutofillDriver* source,
+    const std::vector<FormData>& renderer_forms) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->FormsSeenImpl(forms);
+    source->FormsSeenImpl(renderer_forms);
     return;
   }
-  NOTREACHED();
+
+  for (const FormData& form : renderer_forms)
+    form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  // Collects the browser forms of the |renderer_forms|. If all forms in
+  // |renderer_forms| are root forms, each of them has a different browser form.
+  // Otherwise, all forms in |renderer_forms| are non-root forms in the same
+  // tree, and |browser_forms| will contain the flattened root of this tree.
+  std::vector<FormData> browser_forms;
+  browser_forms.reserve(renderer_forms.size());
+  for (const FormData& form : renderer_forms) {
+    FormData browser_form = form_forest_.GetBrowserFormOfRendererForm(form);
+    if (!base::Contains(browser_forms, browser_form.global_id(),
+                        &FormData::global_id)) {
+      browser_forms.push_back(std::move(browser_form));
+    }
+  }
+  DCHECK(browser_forms.size() == renderer_forms.size() ||
+         browser_forms.size() == 1);
+
+  // Send the browser forms to the individual frames.
+  if (!browser_forms.empty()) {
+    LocalFrameToken frame = browser_forms.front().host_frame;
+    DCHECK(base::ranges::all_of(browser_forms, [frame](const FormData& f) {
+      return f.host_frame == frame;
+    }));
+    ContentAutofillDriver* target = DriverOfFrame(frame);
+    AFCHECK(target, return );
+    target->FormsSeenImpl(std::move(browser_forms));
+  }
 }
 
 void ContentAutofillRouter::SetFormToBeProbablySubmitted(
@@ -67,7 +205,19 @@
     source->SetFormToBeProbablySubmittedImpl(form);
     return;
   }
-  NOTREACHED();
+
+  if (!form) {
+    source->SetFormToBeProbablySubmittedImpl(form);
+    return;
+  }
+
+  form_forest_.UpdateTreeOfRendererForm(*form, source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(*form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->SetFormToBeProbablySubmittedImpl(absl::make_optional(browser_form));
 }
 
 void ContentAutofillRouter::FormSubmitted(
@@ -79,7 +229,14 @@
     source->FormSubmittedImpl(form, known_success, submission_source);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->FormSubmittedImpl(browser_form, known_success, submission_source);
 }
 
 void ContentAutofillRouter::TextFieldDidChange(ContentAutofillDriver* source,
@@ -91,7 +248,16 @@
     source->TextFieldDidChangeImpl(form, field, bounding_box, timestamp);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->TextFieldDidChangeImpl(browser_form, field, bounding_box, timestamp);
 }
 
 void ContentAutofillRouter::TextFieldDidScroll(ContentAutofillDriver* source,
@@ -102,7 +268,16 @@
     source->TextFieldDidScrollImpl(form, field, bounding_box);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->TextFieldDidScrollImpl(browser_form, field, bounding_box);
 }
 
 void ContentAutofillRouter::SelectControlDidChange(
@@ -114,7 +289,16 @@
     source->SelectControlDidChangeImpl(form, field, bounding_box);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->SelectControlDidChangeImpl(browser_form, field, bounding_box);
 }
 
 void ContentAutofillRouter::QueryFormFieldAutofill(
@@ -129,7 +313,19 @@
                                        autoselect_first_suggestion);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  SetLastQueriedSource(source);
+  SetLastQueriedTarget(target);
+  target->QueryFormFieldAutofillImpl(id, browser_form, field, bounding_box,
+                                     autoselect_first_suggestion);
 }
 
 void ContentAutofillRouter::HidePopup(ContentAutofillDriver* source) {
@@ -137,7 +333,13 @@
     source->HidePopupImpl();
     return;
   }
-  NOTREACHED();
+
+  // For Password Manager forms, |last_queried_target_| is not set. Since these
+  // forms are not form-transcending, the we can unicast to the |source|.
+  if (!last_queried_target_)
+    source->HidePopupImpl();
+  else
+    last_queried_target_->HidePopupImpl();
 }
 
 void ContentAutofillRouter::FocusNoLongerOnForm(ContentAutofillDriver* source,
@@ -146,7 +348,24 @@
     source->FocusNoLongerOnFormImpl(had_interacted_form);
     return;
   }
-  NOTREACHED();
+
+  // Suppresses FocusNoLongerOnForm() if the focus has already moved to a
+  // different frame.
+  LocalFrameToken frame_token(
+      source->render_frame_host()->GetFrameToken().value());
+  if (focused_frame_ != frame_token)
+    return;
+
+  // Prevents FocusOnFormField() from calling FocusNoLongerOnForm().
+  focus_no_longer_on_form_has_fired_ = true;
+
+  TriggerReparseExcept(source);
+
+  // TODO(crbug/1228706): Retrofit event with the FormGlobalId and unicast
+  // event.
+  ForEachFrame(form_forest_, [&](ContentAutofillDriver& some_driver) {
+    some_driver.FocusNoLongerOnFormImpl(had_interacted_form);
+  });
 }
 
 void ContentAutofillRouter::FocusOnFormField(ContentAutofillDriver* source,
@@ -157,7 +376,30 @@
     source->FocusOnFormFieldImpl(form, field, bounding_box);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  // Calls FocusNoLongerOnForm() if the focus has already moved from a
+  // different frame and FocusNoLongerOnForm() hasn't been called yet.
+  LocalFrameToken frame_token(
+      source->render_frame_host()->GetFrameToken().value());
+  if (focused_frame_ != frame_token && !focus_no_longer_on_form_has_fired_) {
+    ForEachFrame(form_forest_, [&](ContentAutofillDriver& some_driver) {
+      some_driver.FocusNoLongerOnFormImpl(true);
+    });
+  }
+
+  // Suppresses late FocusNoLongerOnForm().
+  focused_frame_ = frame_token;
+  focus_no_longer_on_form_has_fired_ = false;
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->FocusOnFormFieldImpl(browser_form, field, bounding_box);
 }
 
 void ContentAutofillRouter::DidFillAutofillFormData(
@@ -168,7 +410,16 @@
     source->DidFillAutofillFormDataImpl(form, timestamp);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  DCHECK(!last_queried_target_ ||
+         last_queried_target_ == DriverOfFrame(browser_form.host_frame));
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->DidFillAutofillFormDataImpl(browser_form, timestamp);
 }
 
 void ContentAutofillRouter::DidPreviewAutofillFormData(
@@ -177,7 +428,9 @@
     source->DidPreviewAutofillFormDataImpl();
     return;
   }
-  NOTREACHED();
+
+  if (last_queried_target_)
+    last_queried_target_->DidPreviewAutofillFormDataImpl();
 }
 
 void ContentAutofillRouter::DidEndTextFieldEditing(
@@ -186,7 +439,13 @@
     source->DidEndTextFieldEditingImpl();
     return;
   }
-  NOTREACHED();
+
+  TriggerReparseExcept(source);
+
+  // TODO(crbug/1228706): Retrofit event with the FormGlobalId and FieldGlobalId
+  // and unicast event.
+  ForEachFrame(form_forest_,
+               &ContentAutofillDriver::DidEndTextFieldEditingImpl);
 }
 
 void ContentAutofillRouter::SelectFieldOptionsDidChange(
@@ -196,7 +455,16 @@
     source->SelectFieldOptionsDidChangeImpl(form);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  target->SelectFieldOptionsDidChangeImpl(browser_form);
 }
 
 void ContentAutofillRouter::FillFormForAssistant(
@@ -208,10 +476,26 @@
     source->FillFormForAssistantImpl(fill_data, form, field);
     return;
   }
-  NOTREACHED();
+
+  form_forest_.UpdateTreeOfRendererForm(form, source);
+
+  TriggerReparseExcept(source);
+
+  const FormData& browser_form =
+      form_forest_.GetBrowserFormOfRendererForm(form);
+  auto* target = DriverOfFrame(browser_form.host_frame);
+  AFCHECK(target, return );
+  SetLastQueriedSource(source);
+  SetLastQueriedTarget(target);
+  target->FillFormForAssistantImpl(fill_data, form, field);
 }
 
-// Routing of events called by the browser.
+// Routing of events triggered by the browser.
+//
+// Below, `DriverOfFrame() == nullptr` does not necessarily indicate a bug and
+// is therefore not NOTREACHED().
+// The reason is that browser forms may be outdated and hence refer to frames
+// that do not exist anymore.
 
 void ContentAutofillRouter::SendFormDataToRenderer(
     ContentAutofillDriver* source,
@@ -224,17 +508,64 @@
     source->SendFormDataToRendererImpl(query_id, action, data);
     return;
   }
-  NOTREACHED();
+
+  std::vector<FormData> renderer_forms =
+      form_forest_.GetRendererFormsOfBrowserForm(data, triggered_origin,
+                                                 field_type_map);
+  for (const FormData& renderer_form : renderer_forms) {
+    if (auto* target = DriverOfFrame(renderer_form.host_frame)) {
+      target->SendFormDataToRendererImpl(kCrossFrameFill, action,
+                                         renderer_form);
+    }
+  }
 }
 
 void ContentAutofillRouter::SendAutofillTypePredictionsToRenderer(
     ContentAutofillDriver* source,
-    std::vector<FormDataPredictions> type_predictions) {
+    const std::vector<FormDataPredictions>& browser_fdps) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->SendAutofillTypePredictionsToRendererImpl(type_predictions);
+    source->SendAutofillTypePredictionsToRendererImpl(browser_fdps);
     return;
   }
-  NOTREACHED();
+
+  // Splits each FrameDataPredictions according to the respective FormData's
+  // renderer forms, and groups these FormDataPredictions by the renderer form's
+  // frame. We uso "fdp" as abbreviation of FormDataPredictions.
+  std::map<LocalFrameToken, std::vector<FormDataPredictions>> renderer_fdps;
+  for (const FormDataPredictions& browser_fdp : browser_fdps) {
+    // Builds an index of the field predictions by the field's global ID.
+    std::map<FieldGlobalId, FormFieldDataPredictions> field_predictions;
+    DCHECK_EQ(browser_fdp.data.fields.size(), browser_fdp.fields.size());
+    for (size_t i = 0; i < std::min(browser_fdp.data.fields.size(),
+                                    browser_fdp.fields.size());
+         ++i) {
+      field_predictions.emplace(browser_fdp.data.fields[i].global_id(),
+                                browser_fdp.fields[i]);
+    }
+
+    // Builds the FormDataPredictions of each renderer form and groups them by
+    // the renderer form's frame in |renderer_fdps|.
+    for (FormData& renderer_form : form_forest_.GetRendererFormsOfBrowserForm(
+             browser_fdp.data, browser_fdp.data.main_frame_origin, {})) {
+      LocalFrameToken frame = renderer_form.host_frame;
+      FormDataPredictions renderer_fdp;
+      renderer_fdp.data = std::move(renderer_form);
+      renderer_fdp.signature = browser_fdp.signature;
+      for (const FormFieldData& field : renderer_fdp.data.fields) {
+        renderer_fdp.fields.push_back(
+            std::move(field_predictions[field.global_id()]));
+      }
+      renderer_fdps[frame].push_back(std::move(renderer_fdp));
+    }
+  }
+
+  // Sends the predictions of the renderer forms to the individual frames.
+  for (const auto& p : renderer_fdps) {
+    LocalFrameToken frame = p.first;
+    const std::vector<FormDataPredictions>& renderer_fdp = p.second;
+    if (auto* target = DriverOfFrame(frame))
+      target->SendAutofillTypePredictionsToRendererImpl(renderer_fdp);
+  }
 }
 
 void ContentAutofillRouter::SendFieldsEligibleForManualFillingToRenderer(
@@ -248,7 +579,20 @@
     source->SendFieldsEligibleForManualFillingToRendererImpl(renderer_ids);
     return;
   }
-  NOTREACHED();
+
+  // Splits FieldGlobalIds by their frames and reduce them to the
+  // FieldRendererIds.
+  std::map<LocalFrameToken, std::vector<FieldRendererId>> fields_by_frame;
+  for (FieldGlobalId field : fields)
+    fields_by_frame[field.frame_token].push_back(field.renderer_id);
+
+  // Send the FieldRendererIds to the individual frames.
+  for (const auto& p : fields_by_frame) {
+    LocalFrameToken frame = p.first;
+    const std::vector<FieldRendererId>& fields = p.second;
+    if (auto* target = DriverOfFrame(frame))
+      target->SendFieldsEligibleForManualFillingToRendererImpl(fields);
+  }
 }
 
 void ContentAutofillRouter::RendererShouldAcceptDataListSuggestion(
@@ -256,10 +600,14 @@
     const FieldGlobalId& field,
     const std::u16string& value) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->RendererShouldAcceptDataListSuggestionImpl(field, value);
+    source->RendererShouldAcceptDataListSuggestionImpl(field.renderer_id,
+                                                       value);
     return;
   }
-  NOTREACHED();
+  if (auto* target = DriverOfFrame(field.frame_token)) {
+    target->RendererShouldAcceptDataListSuggestionImpl(field.renderer_id,
+                                                       value);
+  }
 }
 
 void ContentAutofillRouter::RendererShouldClearFilledSection(
@@ -268,7 +616,9 @@
     source->RendererShouldClearFilledSectionImpl();
     return;
   }
-  NOTREACHED();
+
+  ForEachFrame(form_forest_,
+               &ContentAutofillDriver::RendererShouldClearFilledSectionImpl);
 }
 
 void ContentAutofillRouter::RendererShouldClearPreviewedForm(
@@ -277,7 +627,9 @@
     source->RendererShouldClearPreviewedFormImpl();
     return;
   }
-  NOTREACHED();
+
+  ForEachFrame(form_forest_,
+               &ContentAutofillDriver::RendererShouldClearPreviewedFormImpl);
 }
 
 void ContentAutofillRouter::RendererShouldFillFieldWithValue(
@@ -285,10 +637,12 @@
     const FieldGlobalId& field,
     const std::u16string& value) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->RendererShouldFillFieldWithValueImpl(field, value);
+    source->RendererShouldFillFieldWithValueImpl(field.renderer_id, value);
     return;
   }
-  NOTREACHED();
+
+  if (auto* target = DriverOfFrame(field.frame_token))
+    target->RendererShouldFillFieldWithValueImpl(field.renderer_id, value);
 }
 
 void ContentAutofillRouter::RendererShouldPreviewFieldWithValue(
@@ -296,10 +650,12 @@
     const FieldGlobalId& field,
     const std::u16string& value) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->RendererShouldPreviewFieldWithValueImpl(field, value);
+    source->RendererShouldPreviewFieldWithValueImpl(field.renderer_id, value);
     return;
   }
-  NOTREACHED();
+
+  if (auto* target = DriverOfFrame(field.frame_token))
+    target->RendererShouldPreviewFieldWithValueImpl(field.renderer_id, value);
 }
 
 void ContentAutofillRouter::RendererShouldSetSuggestionAvailability(
@@ -307,10 +663,15 @@
     const FieldGlobalId& field,
     const mojom::AutofillState state) {
   if (!base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) {
-    source->RendererShouldSetSuggestionAvailabilityImpl(field, state);
+    source->RendererShouldSetSuggestionAvailabilityImpl(field.renderer_id,
+                                                        state);
     return;
   }
-  NOTREACHED();
+
+  if (auto* target = DriverOfFrame(field.frame_token)) {
+    target->RendererShouldSetSuggestionAvailabilityImpl(field.renderer_id,
+                                                        state);
+  }
 }
 
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_router.h b/components/autofill/content/browser/content_autofill_router.h
index d03ed7ae..dd6850e 100644
--- a/components/autofill/content/browser/content_autofill_router.h
+++ b/components/autofill/content/browser/content_autofill_router.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/containers/flat_map.h"
+#include "components/autofill/content/browser/form_forest.h"
 #include "components/autofill/core/browser/autofill_driver.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/form_data.h"
@@ -25,119 +26,114 @@
 class ContentAutofillDriver;
 
 // ContentAutofillRouter routes events between ContentAutofillDriver objects in
-// order to handle frame-transcending forms. The precise definition follows, but
-// essentially a frame-transcending form is a <form> which contain <iframe>s
-// with form controls that logically belong to the <form>. For example in credit
-// card forms, it is common that the credit card number is entered into an
-// <iframe> that is hosted on a different server than the one that hosts the
-// main page.
+// order to handle frame-transcending forms.
 //
+// A *frame-transcending* form is a form whose logical fields live in different
+// frames. For example, credit card forms often have the credit card number
+// field in an iframe hosted by a payment service provider.
 //
-// Each form control element belongs to one (synthetic or real) form. The *host
-// frame* of a form is the frame whose DOM contains the form.
-// A form is a *child form* of its host frame.
+// A frame-transcending form therefore consists of multiple *renderer forms*.
+// ContentAutofillRouter *flattens* these forms into a single *browser form*,
+// and maps all events concerning the renderer forms to that browser form, and
+// vice versa.
 //
-// A form can contain nested <iframe>s. The *host form* of a frame is the
-// (synthetic or real) form that contains the <iframe> that embeds the frame: if
-// the <iframe> is a descendant of a <form>, that form is the host form;
-// otherwise, the synthetic form is the host form.
-// A frame is a *child frame* of its host form.
+// That way, the collection of renderer forms appears as one ordinary form to
+// the browser.
 //
-// The described host-to-child relationship induces a forest of trees whose
-// nodes are forms and frames. Every tree with forms from different frames (<=>
-// with at least two forms) is called a *frame-transcending form*.
-//
-// *Flattening* refers to the process of collapsing the non-root forms of such a
-// tree into the root form. That is, flattening maps a hierarchy of forms to a
-// single form. This is done by inserting the non-root forms' fields into the
-// root form according to the cross-frame DOM order.
-//
-// The intention is that the browser shall only work with flattened forms. We
-// refer to the forms of the form tree as the *renderer forms*, and to the
-// flattened forms as *browser forms*. The inverse of flattening,
-// *unflattening*, is the process of determining from a browser form the
-// renderer forms that constitute that flattened form.
-//
-// For example, for the following pseudo HTML code,
+// For example, consider the following pseudo HTML code:
 //   <html>
-//   <form id="form1">
-//     <input id="field1">
-//     <iframe id="frame1">
-//       <input id="field2">
+//   <form id="Form-1">
+//     <input id="Field-1">
+//     <iframe id="Frame-1">
+//       <input id="Field-2">
 //     </iframe>
-//     <iframe id="frame2">
-//       <iframe id="frame3">
-//         <form id="form2">
-//           <input id="field3">
+//     <iframe id="Frame-2">
+//       <iframe id="Frame-3">
+//         <form id="Form-2">
+//           <input id="Field-3">
 //         </form>
-//         <form id="form3">
-//           <input id="field4">
+//         <form id="Form-3">
+//           <input id="Field-4">
 //         </form>
 //       </iframe>
 //     </iframe>
-//     <input id="field5">
+//     <input id="Field-5">
 //   </form>
-// the renderer forms will be in pseudo C++ code
-//   FormData{  // form1 in main frame.
-//     .name = "form1",
-//     .fields = { "field1", "field5" },
-//     .child_frames = { "frame1", "frame2" }
-//   }
-//   FormData{  // Synthetic form in frame1.
-//     .fields = { "field2" },
-//     .child_frames = { }
-//   }
-//   FormData{  // Synthetic form in frame2.
-//     .fields = { },
-//     .child_frames = { "frame3" }
-//   }
-//   FormData{  // form2 in frame3.
-//     .fields = { "field3" },
-//     .child_frames = { }
-//   }
-//   FormData{  // form3 in frame3.
-//     .fields = { "field4" },
-//     .child_frames = { }
-//   }
-// which by flattening are turned into one form
+//
+// Forms can be actual <form> elements or synthetic forms: <input>, <select>,
+// and <iframe> elements that are not in the scope of any <form> belong to the
+// enclosing frame's synthetic form.
+//
+// The five renderer forms are therefore, in pseudo C++ code:
 //   FormData{
-//     .name = "form1",
-//     .fields = { "field1", "field2", "field3", "field4", "field5" }
+//     .host_frame = "Frame-0",  // The main frame.
+//     .name = "Form-1",
+//     .fields = { "Field-1", "Field-5" },
+//     .child_frames = { "Frame-1", "Frame-2" }
 //   }
-// Unflattening the flattened form produces the above renderer forms.
+//   FormData{
+//     .host_frame = "Frame-1",
+//     .name = "synthetic",
+//     .fields = { "Field-2" },
+//     .child_frames = { }
+//   }
+//   FormData{
+//     .host_frame = "Frame-2",
+//     .name = "synthetic",
+//     .fields = { },
+//     .child_frames = { "Frame-3" }
+//   }
+//   FormData{
+//     .host_frame = "Frame-3",
+//     .name = "Form-2",
+//     .fields = { "Field-3" },
+//     .child_frames = { }
+//   }
+//   FormData{
+//     .host_frame = "Frame-3",
+//     .name = "Form-3",
+//     .fields = { "Field-4" },
+//     .child_frames = { }
+//   }
 //
+// The browser form of these renderer forms is obtained by flattening the fields
+// into the root form:
+//   FormData{
+//     .name = "Form-1",
+//     .fields = { "Field-1", "Field-2", "Field-3", "Field-4", "Field-5" }
+//   }
 //
-// ContentAutofillRouter's job is to
-// 1. flatten renderer forms and/or unflatten flattened forms, and
-// 2. route the communication between the renderer forms on the one hand and the
-//    flattened form on the other hand.
-//
-// The routing is necessary because after flattening,
-// 1. events coming from an AutofillAgent concerning a renderer form need to be
-//    routed to the flattened form's AutofillManager, and
-// 2. events coming from an AutofillManager concerning a flattened form need to
-//    be routed to the AutofillAgents whose forms constitute the flattened form.
-//
-// ContentAutofillRouter carries out this routing at a ContentAutofillDriver
-// level: each event in ContentAutofillDriver calls the identically-named
-// function of ContentAutofillRouter, which then routes the call back to one or
-// multiple ContentAutofillDrivers.
-//
-// For example, an event coming from AutofillAgent 1 might be routed from
-// ContentAutofillDriver 1 to ContentAutofillDriver 2 and then be handled by
-// AutofillManager 2:
+// Let AutofillAgent-N, ContentAutofillRouter-N, and AutofillManager-N
+// correspond to the Frame-N. ContentAutofillRouter would route an event
+// concerning any of the forms in Frame-3 from ContentAutofillDriver-3 to
+// ContentAutofillDriver-0:
 //
 //   +---Tab---+            +---Tab----+            +----Tab----+
-//   | Agent 1 | ---------> | Driver 1 | -----+     | Manager 1 |
-//   |         |            |          |      |     |           |
-//   | Agent 2 |      +---> | Driver 2 | -----|---> | Manager 2 |
+//   | Agent-0 |      +---> | Driver-0 | ---------> | Manager-0 |
+//   |         |      |     |          |            |           |
+//   | Agent-1 |      |     | Driver-1 |            | Manager-1 |
+//   |         |      |     |          |            |           |
+//   | Agent-2 |      |     | Driver-2 |            | Manager-2 |
+//   |         |      |     |          |            |           |
+//   | Agent-3 | -----|---> | Driver-3 | -----+     | Manager-3 |
 //   +---------+      |     +----------+      |     +-----------+
 //                    |                       |
 //                    |      +--Tab---+       |
 //                    +----- | Router | <-----+
 //                           +--------+
 //
+// If the event name is `f`, the control flow is as follows:
+//   Driver-3's ContentAutofillDriver::f(args...) calls
+//   Router's   ContentAutofillRouter::f(this, args...) calls
+//   Driver-0's ContentAutofillDriver::fImpl(args...).
+//
+// Every function in ContentAutofillRouter takes a |source_driver| parameter,
+// which points to the ContentAutofillDriver that triggered the event. In events
+// triggered by the renderer, the source driver is the driver the associated
+// renderer form originates from.
+//
 // See ContentAutofillDriver for details on the naming pattern and an example.
+//
 // See FormForest for details on (un)flattening.
 class ContentAutofillRouter {
  public:
@@ -147,15 +143,20 @@
   ~ContentAutofillRouter();
 
   // Deletes all forms and fields related to |driver| (and this driver only).
-  // Should be called whenever |driver| is destroyed.
+  // Must be called whenever |driver| is destroyed.
   void UnregisterDriver(ContentAutofillDriver* driver);
 
-  void Reset() {}
+  // Resets the object to the initial state.
+  void Reset();
 
   // Returns the ContentAutofillDriver* for which QueryFormFieldAutofill() was
   // called last.
-  ContentAutofillDriver* last_queried_source() const { return nullptr; }
+  ContentAutofillDriver* last_queried_source() const {
+    return last_queried_source_;
+  }
 
+  // Registers the key-press handler with the driver that last called
+  // QueryFormFieldAutofill(), that is, |last_queried_source_|.
   void SetKeyPressHandler(
       ContentAutofillDriver* source_driver,
       const content::RenderWidgetHost::KeyPressEventCallback& handler);
@@ -220,7 +221,7 @@
       const base::flat_map<FieldGlobalId, ServerFieldType>& field_type_map);
   void SendAutofillTypePredictionsToRenderer(
       ContentAutofillDriver* source_driver,
-      const std::vector<FormDataPredictions> type_predictions);
+      const std::vector<FormDataPredictions>& type_predictions);
   void SendFieldsEligibleForManualFillingToRenderer(
       ContentAutofillDriver* source_driver,
       const std::vector<FieldGlobalId>& fields);
@@ -240,6 +241,36 @@
       ContentAutofillDriver* source_driver,
       const FieldGlobalId& field,
       const mojom::AutofillState state);
+
+ private:
+  friend class ContentAutofillRouterTestApi;
+
+  // Returns the driver of |frame| stored in |form_forest_|.
+  ContentAutofillDriver* DriverOfFrame(LocalFrameToken frame);
+
+  // Calls ContentAutofillDriver::TriggerReparse() for all drivers in
+  // |form_forest_| except for |exception|.
+  void TriggerReparseExcept(ContentAutofillDriver* exception);
+
+  // Update the last queried and source and do cleanup work.
+  void SetLastQueriedSource(ContentAutofillDriver* source);
+  void SetLastQueriedTarget(ContentAutofillDriver* target);
+
+  // The forest of forms. See its documentation for the usage protocol.
+  internal::FormForest form_forest_;
+
+  // The driver that triggered the last QueryFormFieldAutofill() call.
+  // Update with SetLastQueriedSource().
+  ContentAutofillDriver* last_queried_source_ = nullptr;
+  // The driver to which the last QueryFormFieldAutofill() call was routed.
+  // Update with SetLastQueriedTarget().
+  ContentAutofillDriver* last_queried_target_ = nullptr;
+
+  // When the focus moves to a different frame, the order of the events
+  // FocusNoLongerOnForm() and FocusOnFormField() may be reversed due to race
+  // conditions. We use these members to correct the order of the events.
+  LocalFrameToken focused_frame_;
+  bool focus_no_longer_on_form_has_fired_ = true;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_router_test_api.h b/components/autofill/content/browser/content_autofill_router_test_api.h
index 6bd7ad9..d2899ca 100644
--- a/components/autofill/content/browser/content_autofill_router_test_api.h
+++ b/components/autofill/content/browser/content_autofill_router_test_api.h
@@ -18,11 +18,11 @@
   }
 
   void set_last_queried_source(ContentAutofillDriver* driver) {
-    // No-op before http://crrev.com/c/2531999.
+    router_->last_queried_source_ = driver;
   }
 
   void set_last_queried_target(ContentAutofillDriver* driver) {
-    // No-op before http://crrev.com/c/2531999.
+    router_->last_queried_target_ = driver;
   }
 
  private:
diff --git a/components/autofill/content/browser/form_forest.cc b/components/autofill/content/browser/form_forest.cc
new file mode 100644
index 0000000..9903a0c5
--- /dev/null
+++ b/components/autofill/content/browser/form_forest.cc
@@ -0,0 +1,527 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/content/browser/form_forest.h"
+
+#include "base/containers/stack.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/ranges/algorithm.h"
+#include "base/stl_util.h"
+#include "content/public/browser/render_process_host.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
+
+// AFCHECK(condition[, error_handler]) creates a crash dump and executes
+// |error_handler| if |condition| is false.
+// TODO(crbug/1187842): Replace AFCHECK() with DCHECK().
+#if DCHECK_IS_ON()
+#define AFCHECK(condition, ...) DCHECK(condition)
+#else
+#define AFCHECK(condition, ...)           \
+  {                                       \
+    if (!(condition)) {                   \
+      DCHECK(false);                      \
+      base::debug::DumpWithoutCrashing(); \
+      __VA_ARGS__;                        \
+    }                                     \
+  }
+#endif
+
+namespace autofill {
+namespace internal {
+
+namespace {
+
+// Shall indicate if |rfh| is a fenced frame (crbug/1111084), to be implemented
+// if and when fencedframes ship.
+//
+// We do not want to fill across the boundary of a fenced frame. Hence, a fenced
+// frame's FrameData must be disconnected (in terms of FormData::child_frames
+// and FrameData::parent_form) from its parent form. This is already guaranteed
+// because FormData::child_frames does not contain fenced frames. However,
+// UpdateTreeOfRendererForm() would still invoke TriggerReparse() to detect the
+// parent form. IsFencedFrame() should be implemented to suppress this.
+//
+// We also do not want to fill across iframes with the disallowdocumentaccess
+// attribute (crbug/961448). Since disallowdocumentaccess is currently not going
+// to ship and supporting it requires significant additional work in
+// UpdateTreeOfRendererForm() to remove FormData::child_frame and unset
+// FrameData::parent_form for frames that disallow document access, there is no
+// immediate need to support it.
+//
+// TODO(crbug/1201854): Implement if and when fencedframes ship, and/or extend
+// it to disallowdocumentaccess if and when disallowdocumentaccess ships.
+constexpr bool IsFencedFrame(content::RenderFrameHost* rfh) {
+  return false;
+}
+
+}  // namespace
+
+FormForest::FrameData::FrameData(LocalFrameToken frame_token)
+    : frame_token(frame_token) {}
+FormForest::FrameData::~FrameData() = default;
+
+FormForest::FormForest() = default;
+FormForest::~FormForest() = default;
+
+absl::optional<LocalFrameToken> FormForest::Resolve(const FrameData& reference,
+                                                    FrameToken query) {
+  if (absl::holds_alternative<LocalFrameToken>(query))
+    return absl::get<LocalFrameToken>(query);
+  DCHECK(absl::holds_alternative<RemoteFrameToken>(query));
+  AFCHECK(reference.driver, return absl::nullopt);
+  content::RenderFrameHost* rfh = reference.driver->render_frame_host();
+  AFCHECK(rfh, return absl::nullopt);
+  content::RenderProcessHost* rph = rfh->GetProcess();
+  AFCHECK(rph, return absl::nullopt);
+  blink::RemoteFrameToken blink_remote_token(
+      absl::get<RemoteFrameToken>(query).value());
+  content::RenderFrameHost* remote_rfh =
+      content::RenderFrameHost::FromPlaceholderToken(rph->GetID(),
+                                                     blink_remote_token);
+  if (!remote_rfh)
+    return absl::nullopt;
+  return LocalFrameToken(remote_rfh->GetFrameToken().value());
+}
+
+FormForest::FrameData* FormForest::GetOrCreateFrame(LocalFrameToken frame) {
+  auto it = frame_datas_.find(frame);
+  if (it == frame_datas_.end())
+    it = frame_datas_.insert(it, std::make_unique<FrameData>(frame));
+  AFCHECK(it != frame_datas_.end());
+  AFCHECK(it->get());
+  return it->get();
+}
+
+FormForest::FrameData* FormForest::GetFrameData(LocalFrameToken frame) {
+  auto it = frame_datas_.find(frame);
+  return it != frame_datas_.end() ? it->get() : nullptr;
+}
+
+FormData* FormForest::GetFormData(const FormGlobalId& form,
+                                  FrameData* frame_data) {
+  DCHECK(!frame_data || frame_data == GetFrameData(form.frame_token));
+  if (!frame_data)
+    frame_data = GetFrameData(form.frame_token);
+  auto it = base::ranges::find(frame_data->child_forms, form.renderer_id,
+                               &FormData::unique_renderer_id);
+  return it != frame_data->child_forms.end() ? &*it : nullptr;
+}
+
+FormForest::FrameAndForm FormForest::GetRoot(FormGlobalId form) {
+  FrameData* frame = nullptr;
+  for (;;) {
+    frame = GetFrameData(form.frame_token);
+    AFCHECK(frame, return {nullptr, nullptr});
+    if (!frame->parent_form) {
+      auto it = base::ranges::find(frame->child_forms, form.renderer_id,
+                                   &FormData::unique_renderer_id);
+      AFCHECK(it != frame->child_forms.end(), return {nullptr, nullptr});
+      return {frame, &*it};
+    }
+    form = *frame->parent_form;
+  }
+}
+
+void FormForest::EraseFrame(LocalFrameToken frame) {
+  if (!frame_datas_.erase(frame))
+    return;
+  // Removes all fields and unsets |frame|'s children's FrameData::parent_form
+  // pointer. We intentionally iterate over all frames and forms to search for
+  // fields from |frame|. Alternatively, we could limit this to the root form of
+  // |frame|. However, this would rely on |frame| being erased before its
+  // ancestors, for otherwise |frame| is disconnected from its root already.
+  for (std::unique_ptr<FrameData>& some_frame : frame_datas_) {
+    AFCHECK(some_frame, continue);
+    for (FormData& form : some_frame->child_forms) {
+      base::EraseIf(form.fields, [&frame](const FormFieldData& field) {
+        return field.host_frame == frame;
+      });
+    }
+    if (some_frame->parent_form &&
+        some_frame->parent_form->frame_token == frame) {
+      some_frame->parent_form = absl::nullopt;
+    }
+  }
+}
+
+// Maintains the following invariants:
+// 1. The graph is a disjoint union of trees, and the trees faithfully represent
+//    the frame-transcending forms in the DOMs.
+// 2. The root forms of each tree contain (only) the nodes of all forms in
+//    the subtree in DOM order, and all non-root forms have no fields.
+//
+// We keep the FormData::child_frame and FrameData::parent_form relations in
+// symmetry to ease reasoning about the tree. Since children are predetermined
+// by FormData:child_frame, we do so by always updating the childrens'
+// FrameData::parent_form.
+//
+// If |form| is not part of a frame-transcending form, the function has minimal
+// overhead. That is, if |form|'s FormData::child_frames is empty and |form|'s
+// frame has no parent frame, the function reduces to a few moves and index
+// lookups.
+//
+// If the FrameData::parent_form of |form|'s frame is not set although a parent
+// frame exists, the function triggers a reparse in the parent frame. This will
+// trigger an UpdateTreeOfRendererForm() for the true parent form (amongst
+// others), which will then also set the child frame's FrameData::parent_form.
+void FormForest::UpdateTreeOfRendererForm(FormData* form,
+                                          ContentAutofillDriver* driver) {
+  AFCHECK(form, return );
+  AFCHECK(driver, return );
+  AFCHECK(form->host_frame, return );
+
+  FrameData* frame = GetOrCreateFrame(form->host_frame);
+  AFCHECK(frame, return );
+  AFCHECK(!frame->driver || frame->driver == driver, return );
+  frame->driver = driver;
+
+  content::RenderFrameHost* rfh = driver->render_frame_host();
+  AFCHECK(rfh, return );
+  AFCHECK(form->host_frame == LocalFrameToken(rfh->GetFrameToken().value()),
+          return );
+
+  // Moves |form| into its |frame|'s FrameData::child_forms, with a special
+  // treatment of the fields: |form|'s fields are replaced with |old_form|'s
+  // fields if |form| had previously been known as |old_form|. Retaining the old
+  // fields is important because |old_form| may have been a root and therefore
+  // contained fields from other forms. The relevant old and new fields will be
+  // moved to |form|'s root later.
+  std::vector<FormFieldData> form_fields = std::move(form->fields);
+  bool child_frames_changed;
+  if (FormData* old_form = GetFormData(form->global_id(), frame)) {
+    form->fields = std::move(old_form->fields);
+    child_frames_changed = old_form->child_frames != form->child_frames;
+    *old_form = std::move(*form);
+    form = old_form;
+  } else {
+    DCHECK(!base::Contains(frame->child_forms, form->unique_renderer_id,
+                           &FormData::unique_renderer_id));
+    form->fields = {};
+    child_frames_changed = false;
+    frame->child_forms.push_back(std::move(*form));
+    form = &frame->child_forms.back();
+  }
+  DCHECK(form && form == GetFormData(form->global_id()));
+
+  // Do *NOT* modify any FrameData::child_forms after this line!
+  // Doing so may resize FrameData::child_forms, while we keep raw pointers to
+  // individual items.
+
+  // Traverses |form|'s tree starting at its root to set FrameData::parent_form
+  // and update the root form's fields, while keeping them in DOM order:
+  // - adds the fields from |form_fields| to `root->fields`;
+  // - removes fields from `root->fields` that originated from |old_form|'s
+  //   renderer form but are not in |form_fields|;
+  // - removes fields that originated from frames that have been removed from
+  //   |form| as well as fields from their descendant frames;
+  // - moves fields from former root forms that are now children of |form|
+  //   from that form to `root->fields`.
+  //
+  // We perform all these tasks in a single pre-order depth-first traversal of
+  // |form|'s tree. That is, every field of a form is visited before/after
+  // recursing into the subframes of the form that come before/after that field.
+  // Only if |form|'s tree is trivial (consists of a single form), we can take
+  // an abbreviation and just move the fields.
+  if (!frame->parent_form && form->child_frames.empty() &&
+      !child_frames_changed) {
+    form->fields = std::move(form_fields);
+  } else {
+    FrameAndForm root = GetRoot(form->global_id());
+    AFCHECK(root, return );
+    // Moves the first |max_number_of_fields_to_be_moved| fields that originated
+    // from the renderer form |source_form| from |source| to |target|.
+    // Default-initializes each source field after its move to prevent it from
+    // being moved in a future call.
+    // Calling MoveFields() repeatedly to move one field at a time runs in
+    // quadratic time due to the comparisons of the fields' renderer_form_id().
+    // The cost could be reduced to linear time by reversing the source vectors
+    // and moving fields from the back of |source|. However, the cost of
+    // reversing likely exceeds the cost of the renderer_form_id() comparisons.
+    auto MoveFields = [](size_t max_number_of_fields_to_be_moved,
+                         FormGlobalId source_form,
+                         std::vector<FormFieldData>& source,
+                         std::vector<FormFieldData>& target) {
+      DCHECK_NE(&source, &target);
+      size_t number_of_fields_moved = 0;
+      for (FormFieldData& f : source) {
+        if (f.renderer_form_id() == source_form) {
+          if (++number_of_fields_moved > max_number_of_fields_to_be_moved)
+            break;
+          target.push_back(std::move(f));
+          f = {};  // Clobber |f| in |source| so future MoveFields() skip it.
+          DCHECK(!f.renderer_form_id());
+        }
+      }
+    };
+
+    // The |frontier| contains the Nodes to be expanded in LIFO order. Each Node
+    // represents the range of fields and the next frame to be visited.
+    //
+    // A Node consists of
+    // - the Node::form whose fields and child frames are to be visited;
+    // - the Node::frame that hosts Node::form;
+    // - the Node::next_frame to be traversed after visiting the fields that
+    //   precede this frame in the form.
+    //
+    // For example, consider a Node |n| whose form has 4 child frames and at
+    // least 5 fields:
+    //   <form>
+    //     <iframe>
+    //     <input id="0">
+    //     <input id="1">
+    //     <input id="2">
+    //     <iframe>
+    //     <iframe>
+    //     <input id="3">
+    //     <input id="4">
+    //     <iframe>
+    //     <input>
+    //     ...
+    //   </form>
+    // The relative order of fields and frames is encoded in
+    // `n.form->child_frames[i].predecessor`: the value represents which field
+    // from `n.form`, if any, precedes the frame in DOM order. In this example:
+    // - `n.form->child_frames[0].predecessor == -1`;
+    // - `n.form->child_frames[1].predecessor == 2`;
+    // - `n.form->child_frames[2].predecessor == 2`;
+    // - `n.form->child_frames[3].predecessor == 4`.
+    // Then the represented field range depends of the next frame:
+    // - `n.next_frame == 0` represents the empty range;
+    // - `n.next_frame == 1` represents the fields with indices 0, 1, 2;
+    // - `n.next_frame == 2` represents the empty range;
+    // - `n.next_frame == 3` represents the fields with indices 3, 4;
+    // - `n.next_frame == 4` represents the fields with indices greater than 4.
+    //
+    // Note that the fields of `n.form` are typically not stored in
+    // `n.form->fields`:
+    // - If `n.form` refers to the passed |form| (`n.form == form`), then these
+    //   fields have been moved to |form_fields|.
+    // - Otherwise, they are stored in `n.form`'s root form.
+    //
+    // Since the relative order of the fields is the same as in the renderer
+    // form, the index |i| of a field from `n.form` translates to the |i|th
+    // field whose `renderer_form_id()` is `n.form->global_id()` in the
+    // respective vector that contains the fields from `n.form`.
+    //
+    // When the traversal expands a Node |n| from the |frontier|, we
+    // - pull these fields from |roots_on_path| (defined below) or |form_fields|
+    //   and append them to |root_fields|, the future fields of the root;
+    // - push on the |frontier|
+    //   - one Node for each child form in that frame, and
+    //   - a Node with incremented `n.next_frame` for the successor frame and
+    //     its preceding fields
+    //   in an order that ensures DOM-order traversal.
+    // The latter step is omitted if Node::next_frame is out of bounds,
+    // indicating indicating that all fields and frames have been visited
+    // already.
+    struct Node {
+      FrameData* frame;   // Not null.
+      FormData* form;     // Not null.
+      size_t next_frame;  // In the range [0, `form->child_frames.size()`].
+    };
+    base::stack<Node> frontier;
+    frontier.push({root.frame, root.form, 0});
+
+    // Fields to be moved to |root_fields| may not just come from |form_fields|
+    // or `root.form->fields`, but also from forms that used to be roots but
+    // have become children of |form|. These former roots contain the fields
+    // from their subtrees. To access these fields, we store the fields from the
+    // root as well as from former root nodes (unless they have no fields) in
+    // |roots_on_path|.
+    base::stack<FormData*> roots_on_path;
+
+    // New fields of the root form. To be populated in the tree traversal.
+    std::vector<FormFieldData> root_fields;
+    root_fields.reserve(root.form->fields.size() + form_fields.size());
+
+    size_t emergency_counter = 0;
+    while (!frontier.empty()) {
+      if (++emergency_counter > 1000) {
+        AFCHECK(false);
+        break;
+      }
+
+      Node n = frontier.top();
+      frontier.pop();
+      AFCHECK(n.frame, continue);
+      AFCHECK(n.form, continue);
+
+      // Pushes the current form on |roots_on_path| only if this is the first
+      // time we encounter the form in the traversal (Node::next_frame == 0).
+      if (n.next_frame == 0 && (n.form == root.form || !n.form->fields.empty()))
+        roots_on_path.push(n.form);
+      AFCHECK(!roots_on_path.empty(), continue);
+
+      std::vector<FormFieldData>& source =
+          n.form->global_id() == form->global_id()
+              ? form_fields
+              : roots_on_path.top()->fields;
+      // Moves the next fields from `n.form` to |root_fields|.
+      //
+      // If `n.next_frame` is in bounds, pushes on the |frontier|
+      // - one Node for each child form in that frame, and
+      // - a Node with incremented `n.next_frame` for the successor frame and
+      //   its preceding fields.
+      // The order of these pushes is inversed so that they're expanded in DOM
+      // order.
+      //
+      // If `n.next_frame` is out of bounds, all paths through |n| have been
+      // fully traversed, so if applicable, we pop `n.form` from
+      // |roots_on_path|.
+      if (n.next_frame < n.form->child_frames.size()) {
+        // [begin, end) is the range of fields from `n.form` before
+        // `n.next_frame`.
+        size_t begin = base::checked_cast<size_t>(
+            n.next_frame > 0
+                ? n.form->child_frames[n.next_frame - 1].predecessor + 1
+                : 0);
+        size_t end = base::checked_cast<size_t>(
+            n.form->child_frames[n.next_frame].predecessor + 1);
+        AFCHECK(begin <= end, continue);
+        MoveFields(end - begin, n.form->global_id(), source, root_fields);
+        frontier.push(
+            {.frame = n.frame, .form = n.form, .next_frame = n.next_frame + 1});
+        absl::optional<LocalFrameToken> local_child =
+            Resolve(*n.frame, n.form->child_frames[n.next_frame].token);
+        FrameData* child_frame;
+        // If the FrameData does not exist yet, creating it now and setting the
+        // FrameData::parent_form avoids a reparse if and when a form is seen in
+        // this child frame.
+        if (local_child && (child_frame = GetOrCreateFrame(*local_child))) {
+          child_frame->parent_form = n.form->global_id();
+          for (size_t i = child_frame->child_forms.size(); i > 0; --i) {
+            frontier.push({.frame = child_frame,
+                           .form = &child_frame->child_forms[i - 1],
+                           .next_frame = 0});
+          }
+        }
+      } else {
+        MoveFields(std::numeric_limits<size_t>::max(), n.form->global_id(),
+                   source, root_fields);
+        if (n.form == roots_on_path.top()) {
+          roots_on_path.top()->fields.clear();
+          roots_on_path.pop();
+        }
+      }
+    }
+    root.form->fields = std::move(root_fields);
+  }
+
+  // Triggers a reparse in a parent frame if `frame->parent_form` is unset.
+  //
+  // If |frame| has a parent frame and is not a fenced frame, there are two
+  // scenarios where `frame->parent_form` is unset:
+  // - The parent frame hasn't been processed by UpdateTreeOfRendererForm() yet.
+  // - The parent form did not include the correct token of |frame| in its
+  //   FormData::child_frames (for example, because loading a cross-origin page
+  //   into the <iframe> has changed |frame|'s FrameToken).
+  //
+  // In this case, we trigger a reparse in the parent frame. As a result,
+  // UpdateTreeOfRendererForm() will be called for the parent form, whose
+  // FormData::child_frames now include |frame|.
+  content::RenderFrameHost* parent_rfh = rfh->GetParent();
+  if (!frame->parent_form && parent_rfh && !IsFencedFrame(rfh)) {
+    LocalFrameToken parent_frame_token(
+        LocalFrameToken(parent_rfh->GetFrameToken().value()));
+    FrameData* parent_frame = GetFrameData(parent_frame_token);
+    if (parent_frame && parent_frame->driver) {
+      AFCHECK(parent_frame->driver->render_frame_host() == parent_rfh);
+      parent_frame->driver->TriggerReparse();
+    }
+  }
+}
+
+const FormData& FormForest::GetBrowserFormOfRendererForm(
+    const FormData& renderer_form) const {
+  AFCHECK(renderer_form.host_frame, return renderer_form);
+
+  // For calling non-const-qualified getters.
+  FormForest& mutable_this = *const_cast<FormForest*>(this);
+  const FormData* form = mutable_this.GetRoot(renderer_form.global_id()).form;
+  AFCHECK(form, return renderer_form);
+  return *form;
+}
+
+std::vector<FormData> FormForest::GetRendererFormsOfBrowserForm(
+    const FormData& browser_form,
+    const url::Origin& triggered_origin,
+    const base::flat_map<FieldGlobalId, ServerFieldType>& field_type_map)
+    const {
+  AFCHECK(browser_form.host_frame, return {browser_form});
+
+  // For calling non-const-qualified getters.
+  FormForest& mutable_this = *const_cast<FormForest*>(this);
+
+  // Reinstates the fields of |browser_form| in copies of their renderer forms.
+  // See the function's documentation in the header for details on the security
+  // policy |IsSafeToFill|.
+  std::vector<FormData> renderer_forms;
+  for (const FormFieldData& browser_field : browser_form.fields) {
+    FormGlobalId form_id = browser_field.renderer_form_id();
+
+    // Finds or creates the renderer form from which |browser_field| originated.
+    auto renderer_form =
+        base::ranges::find(renderer_forms.rbegin(), renderer_forms.rend(),
+                           form_id, &FormData::global_id);
+    if (renderer_form == renderer_forms.rend()) {
+      const FormData* original_form = mutable_this.GetFormData(form_id);
+      AFCHECK(original_form, continue);
+      renderer_forms.push_back(*original_form);
+      renderer_form = renderer_forms.rbegin();
+      renderer_form->fields.clear();  // In case |original_form| is a root form.
+    }
+    DCHECK(renderer_form != renderer_forms.rend());
+
+    auto IsSafeToFill = [&mutable_this, &browser_form, &renderer_form,
+                         &triggered_origin,
+                         &field_type_map](const FormFieldData& field) {
+      // Non-sensitive values may be filled into fields that belong to the main
+      // frame's origin. This is independent of the origin of the field that
+      // triggered the autofill, |triggered_origin|.
+      auto IsSensitiveFieldType = [](ServerFieldType field_type) {
+        switch (field_type) {
+          case CREDIT_CARD_TYPE:
+          case CREDIT_CARD_NAME_FULL:
+          case CREDIT_CARD_NAME_FIRST:
+          case CREDIT_CARD_NAME_LAST:
+            return false;
+          default:
+            return true;
+        }
+      };
+      // Fields in frames whose permissions policy allows shared-autofill may
+      // be filled if the |triggered_origin| is the main origin.
+      auto has_shared_autofill_permission = [&mutable_this](
+                                                LocalFrameToken frame_token) {
+        FrameData* frame = mutable_this.GetFrameData(frame_token);
+        return frame && frame->driver && frame->driver->render_frame_host() &&
+               frame->driver->render_frame_host()->IsFeatureEnabled(
+                   blink::mojom::PermissionsPolicyFeature::kSharedAutofill);
+      };
+
+      const url::Origin& main_origin = browser_form.main_frame_origin;
+      auto it = field_type_map.find(field.global_id());
+      ServerFieldType field_type =
+          it != field_type_map.end() ? it->second : UNKNOWN_TYPE;
+      return field.origin == triggered_origin ||
+             (field.origin == main_origin &&
+              !IsSensitiveFieldType(field_type)) ||
+             (triggered_origin == main_origin &&
+              has_shared_autofill_permission(renderer_form->host_frame));
+    };
+
+    renderer_form->fields.push_back(browser_field);
+    if (!IsSafeToFill(renderer_form->fields.back()))
+      renderer_form->fields.back().value.clear();
+  }
+
+  return renderer_forms;
+}
+
+}  // namespace internal
+}  // namespace autofill
diff --git a/components/autofill/content/browser/form_forest.h b/components/autofill/content/browser/form_forest.h
new file mode 100644
index 0000000..c89a8eb8
--- /dev/null
+++ b/components/autofill/content/browser/form_forest.h
@@ -0,0 +1,360 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_H_
+#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_H_
+
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/unique_ids.h"
+#include "content/public/browser/render_frame_host.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace autofill {
+namespace internal {
+
+// FormForest converts renderer forms into a browser form and vice versa.
+//
+// A *frame-transcending* form is a form whose logical fields live in different
+// frames. The *renderer forms* are the FormData objects as we receive them from
+// the renderers of these frames. The *browser form* of a frame-transcending
+// form is its root FormData, with all fields of its descendant FormDatas moved
+// into the root.
+// See ContentAutofillRouter for further details on the terminology and
+// motivation.
+//
+// Consider the following main frame with two frame-transcending forms:
+//
+//                    +--------------- Frame ---------------+
+//                    |                                     |
+//             +--- Form-A --+                       +--- Form-C --+
+//             |      |      |                       |             |
+//          Field-1 Frame Field-4                  Frame         Frame
+//                    |                              |             |
+//             +--- Form-B --+                     Form-D        Form-E
+//             |             |                       |             |
+//          Field-2       Field-3                 Field-5        Frame
+//                                                                 |
+//                                                               Form-F
+//                                                                 |
+//                                                              Field-6
+//
+// The renderer forms are form A, B, C, D, E, F.
+//
+// The browser form of forms A and B has the fields fields 1, 2, 3, 4.
+// Converting this browser form back to renderer forms yields Form-A and Form-B.
+//
+// Analogously, the browser form of forms C, D, E, and F has the fields 5 and 6.
+// Converting this browser form back to renderer forms yields forms C, D, E, F.
+//
+// The three key functions of FormForest are:
+// - UpdateTreeOfRendererForm()
+// - GetBrowserFormOfRendererForm()
+// - GetRendererFormsOfBrowserForm()
+//
+// UpdateTreeOfRendererForm() incrementally builds up a graph of frames, forms,
+// and fields.
+//
+// This graph is a forest in two (entirely independent) ways:
+//
+// Firstly, there may be multiple root frames. One reason is the website author
+// can disconnect an entire frame subtree from the rest of the frame tree in the
+// future using the fencedframes tag and/or disallowdocumentaccess attribute.
+// Another reason is that the frame hierarchy emerges gradually and therefore
+// some links may be unknown. For example, Form-A might point to a nonexistent
+// frame of Form-B because, after Form-A was last parsed, a cross-origin
+// navigation happened in Form-B's frame.
+//
+// Secondly, removing the root frames obtains a forest, where each tree
+// corresponds to a frame-transcending form. We call the roots of this forest
+// *root forms*. In the example, forms A and C are root forms. This is relevant
+// because filling operations happen on the granularity of root forms.
+//
+// As an invariant, UpdateTreeOfRendererForm() keeps each frame-transcending
+// form in a flattened state: fields are stored as children of their root
+// forms. The fields are ordered according to pre-order depth-first (DOM order)
+// traversal of the original tree. In our example:
+//
+//                    +--------------- Frame ---------------+
+//                    |                                     |
+//    +-------+---- Form-A ---+-------+        +-------+- Form-C -+-------+
+//    |       |       |       |       |        |       |          |       |
+// Field-1 Field-2 Field-3 Field-4  Frame   Field-5 Field-6     Frame   Frame
+//                                    |                           |       |
+//                                  Form-B                      Form-D  Form-E
+//                                                                        |
+//                                                                      Frame
+//                                                                        |
+//                                                                      Form-F
+//
+// There is no meaningful order between the fields and frames in these flattened
+// forms.
+//
+// GetBrowserFormOfRendererForm(renderer_form) simply retrieves the form node
+// of |renderer_form| and returns the root form, along with its field children
+// For example, if |renderer_form| is form B, it returns form A with fields 1–4.
+//
+// GetRendererFormsOfBrowserForm(browser_form) returns the individual renderer
+// forms that constitute |browser_form|, with their fields reinstated. For
+// example, if |browser_form| has fields 1–4, it returns form A with fields 1
+// and 4, and form B with fields 2 and 3.
+//
+// The node types in the forest always alternate as follows:
+// - The root nodes are frames.
+// - The children of frames are forms.
+// - The children of forms are frames or fields.
+// - Fields are leaves. Forms and frames may be leaves.
+//
+// Frames, forms, and fields are represented as FrameData, FormData, and
+// FormFieldData objects respectively. The graph is stored as follows:
+// - All FrameData nodes are stored directly in FormForest::frame_datas_.
+// - The FrameData -> FormData edges are stored in the FrameData::child_forms
+//   vector of FormData objects. That is, each FrameData directly holds its
+//   children.
+// - The FormData -> FrameData edges are stored in the FormData::child_frames
+//   vector of FrameTokens. To retrieve the actual FrameData child, the token
+//   is resolved to a LocalFrameToken if necessary (see Resolve()), and then
+//   looked up in FormForest::frame_datas_.
+// - The FormData -> FormFieldData edges are stored in the FormData::fields
+//   vector of FormFieldData objects. As per the aforementioned invariant,
+//   fields are only stored in root forms. Each field's original parent can be
+//   identified by FormFieldData::host_frame and FormFieldData::host_form_id.
+//
+// Reasonable usage of FormForest follows this protocol:
+// 1. Call any of the functions only for forms and fields which have the
+//    following attributes set:
+//    - FormData::host_frame
+//    - FormData::unique_renderer_id
+//    - FormFieldData::host_frame
+//    - FormFieldData::unique_renderer_id
+//    - FormFieldData::host_form_id
+// 2. Call UpdateTreeOfRendererForm(renderer_form) whenever a renderer form is
+//    seen to make FormForest aware of the (new or potentially changed) form.
+// 3. Call GetBrowserFormOfRendererForm(renderer_form) only after a preceding
+//    UpdateTreeOfRendererForm(some_renderer_form) call where |renderer_form|
+//    typically is identical to |some_renderer_form|, but technically it
+//    suffices if both forms have the same global_id().
+// 4. Call GetRendererFormsOfBrowserForm(browser_form) only if |browser_form|
+//    was previously returned by GetBrowserFormOfRendererForm(), perhaps with
+//    different FormFieldData::value, FormFieldData::is_autofilled.
+// Items 1 and 3 are mandatory for FormForest to be memory-safe.
+class FormForest {
+ public:
+  // A FrameData is a frame node in the form tree. Its children are FormData
+  // objects.
+  struct FrameData {
+    // Less-than relation on FrameData objects based on their frame token, to be
+    // used by FrameData sets.
+    struct CompareByFrameToken {
+      using is_transparent = void;
+      constexpr bool operator()(const std::unique_ptr<FrameData>& f,
+                                const std::unique_ptr<FrameData>& g) const {
+        return f && g ? f->frame_token < g->frame_token : f.get() < g.get();
+      }
+      constexpr bool operator()(const std::unique_ptr<FrameData>& f,
+                                const LocalFrameToken& g) const {
+        return f ? f->frame_token < g : true;
+      }
+      constexpr bool operator()(const LocalFrameToken& f,
+                                const std::unique_ptr<FrameData>& g) const {
+        return g ? f < g->frame_token : false;
+      }
+    };
+
+    explicit FrameData(LocalFrameToken frame_token);
+    FrameData(const FrameData&) = delete;
+    FrameData& operator=(const FrameData&) = delete;
+    ~FrameData();
+
+    // Unique identifier of the frame. This is never null.
+    const LocalFrameToken frame_token;
+    // List of forms directly contained in the frame, in the same order as the
+    // corresponding UpdateTreeOfRendererForm(child_form) calls. Modification of
+    // this vector should be kept to a minimum to ensure memory safety. Only
+    // UpdateTreeOfRendererForm() should modify it.
+    std::vector<FormData> child_forms;
+    // Unique identifier of the form in the parent frame that contains this
+    // frame. When a parent form can Resolve() a child's FrameToken, it sets
+    // itself as the parent of the child frame, even if no form in this frame
+    // has been seen yet.
+    absl::optional<FormGlobalId> parent_form = absl::nullopt;
+    // Pointer to the frame's ContentAutofillDriver. This can be null because an
+    // empty FrameData is created when a parent form can Resolve() a child's
+    // LocalFrameToken and no form from that child frame has been seen yet.
+    // However, if |child_forms| is non-empty, then driver is non-null.
+    ContentAutofillDriver* driver = nullptr;
+  };
+
+  FormForest();
+  FormForest(const FormForest&) = delete;
+  FormForest& operator=(const FormForest&&) = delete;
+  ~FormForest();
+
+  // Adds or updates |renderer_form| and |driver| to/in the relevant tree, where
+  // |driver| must be the ContentAutofillDriver of `renderer_form.host_frame`.
+  void UpdateTreeOfRendererForm(FormData renderer_form,
+                                ContentAutofillDriver* driver) {
+    UpdateTreeOfRendererForm(&renderer_form, driver);
+  }
+
+  // Returns the browser form of |renderer_form|.
+  const FormData& GetBrowserFormOfRendererForm(
+      const FormData& renderer_form) const;
+
+  // Returns the renderer forms of |browser_form|. The security policy depends
+  // on |triggered_origin| and |field_type_map|.
+  //
+  // The function reinstates each field from |browser_form| in the renderer form
+  // it originates from. These reinstated fields hold the (possibly autofilled)
+  // values from |browser_form|, provided that they are considered safe to fill
+  // according to the security policy defined below. The FormFieldData::value of
+  // unsafe fields is reset to the empty string.
+  //
+  // The |triggered_origin| should be the origin of the field from which
+  // Autofill was queried.
+  // The |field_type_map| should contain the field types of the fields in
+  // |browser_form|.
+  //
+  // A field is *safe to fill* iff at least one of the following conditions
+  // holds:
+  // (1) The field's origin is the |triggered_origin|.
+  // (2) The field's origin is the main origin and the field's type in
+  //     |field_type_map| is not sensitive (see is_sensitive_field_type()).
+  // (3) The |triggered_origin| is main origin and the field's frame's
+  //     permissions policy allows shared-autofill.
+  // See below for a future additional necessary condition.
+  //
+  // The *origin of a field* is the origin of the frame that contains the
+  // corresponding form-control element.
+  //
+  // The *main origin* is `browser_form.main_frame_origin`.
+  //
+  // A frame's *permissions policy allows shared-autofill* if that frame is a
+  // main frame or its embedding <iframe> element lists "shared-autofill" in
+  // its "allow" attribute (see https://www.w3.org/TR/permissions-policy-1/).
+  //
+  // When fenced frames (crbug/1111084) or disallowdocumentaccess (crbug/961448)
+  // ships, a necessary requirement for a field to be *safe to fill* will be:
+  // (4) No frame on the shortest path from the field on from which Autofill was
+  //     triggered to the field in question frame in the frame tree, except
+  //     perhaps the shallowest frame, is a fenced frame or has the has the
+  //     disallowdocumentaccess attribute.
+  // TODO(crbug/1201854): Implement fenced frames and/or disallowdocumentaccess
+  // if and when they ship.
+  std::vector<FormData> GetRendererFormsOfBrowserForm(
+      const FormData& browser_form,
+      const url::Origin& triggered_origin,
+      const base::flat_map<FieldGlobalId, ServerFieldType>& field_type_map)
+      const;
+
+  // Deletes all forms and fields that originate from |frame|. Fields from
+  // descendant frames of |frame| are not erased because EraseFrame() will be or
+  // has been called for them individually.
+  void EraseFrame(LocalFrameToken frame);
+
+  // Resets the object to the initial state.
+  void Reset() { frame_datas_.clear(); }
+
+  // Returns the set of FrameData nodes of the forest.
+  const base::flat_set<std::unique_ptr<FrameData>,
+                       FrameData::CompareByFrameToken>&
+  frame_datas() const {
+    return frame_datas_;
+  }
+
+ private:
+  friend class FormForestTestApi;
+
+  struct FrameAndForm {
+    constexpr explicit operator bool() {
+      DCHECK_EQ(!frame, !form);
+      return frame && form;
+    }
+
+    FrameData* frame = nullptr;
+    FormData* form = nullptr;
+  };
+
+  // Resolves a FrameToken |query| from the perspective of |reference| to the
+  // globally unique LocalFrameToken. `reference.driver` must be non-null.
+  //
+  // Frames identify each other using LocalFrameTokens and RemoteFrameTokens.
+  // - LocalFrameTokens are globally unique identifiers and hence suitable for
+  //   discrimating between frames.
+  // - RemoteFrameTokens are not unique and hence unsuitable to discriminate
+  //   between frames.
+  //
+  // Therefore, FormForest works with LocalFrameToken and resolves the
+  // RemoteFrameTokens in FormData::child_frames to LocalFrameTokens.
+  //
+  // From the perspective of a frame F, a frame G is either local or remote:
+  // - If G is local, G is hosted by the same render process as F.
+  // - If G is remote, G may be hosted by another render process.
+  //
+  // Suppose F is the parent frame of G. If G is local to F, then F refers to G
+  // in its FormData::child_frames by G's LocalFrameToken. Otherwise, if G is
+  // remote to F, then F uses a RemoteFrameToken as a placeholder to refer to G
+  // in FormData::child_frames.
+  //
+  // While LocalFrameTokens are unique identifiers at any point in time, they
+  // may change when a navigation happens in the frame:
+  // - If G is local to F and a navigation causes G's render process to be
+  //   swapped so that G becomes remote, G gets a new LocalFrameToken and F will
+  //   refer to G by a fresh RemoteFrameToken.
+  // - If G is remote to F and a navigation causes G's render process to be
+  //   swapped, then F may continue to refer to G by the same RemoteFrameToken
+  //   as before even if G's LocalFrameToken has changed.
+  // The first example is the reason why UpdateTreeOfRendererForm() may trigger
+  // a reparse in a parent frame. The second example is the reason why we do not
+  // cache LocalFrameTokens.
+  static absl::optional<LocalFrameToken> Resolve(const FrameData& reference,
+                                                 FrameToken query);
+
+  // Returns the FrameData known for |frame|, or creates a new one and returns
+  // it, in which case all members but FrameData::host_frame are uninitialized.
+  FrameData* GetOrCreateFrame(LocalFrameToken frame);
+
+  // Returns the FrameData known for |frame|, or null.
+  // May be used in const qualified methods if the return value is not mutated.
+  FrameData* GetFrameData(LocalFrameToken frame);
+
+  // Returns the FormData known for |form|, or null.
+  // The returned value will point to |frame_datas_|, meaning that all fields
+  // have been moved to their respective root forms.
+  // The |frame_data| must be null or equal to `GetFrameData(form.host_frame)`.
+  // Beware of invalidating the returned form pointer by changing its host
+  // frame's FrameData::host_forms.
+  // May be used in const qualified methods if the return value is not mutated.
+  FormData* GetFormData(const FormGlobalId& form,
+                        FrameData* frame_data = nullptr);
+
+  // Returns the non-null root frame and form of the tree that contains |form|.
+  // Beware of invalidating the returned form pointer by changing its host
+  // frame's FrameData::host_forms.
+  // May be used in const qualified methods if the return value is not mutated.
+  FrameAndForm GetRoot(FormGlobalId form);
+
+  // Adds |renderer_form| and |driver| to the relevant tree, where |driver| must
+  // be the ContentAutofillDriver of the |renderer_form|'s FormData::host_frame.
+  // Leaves `*renderer_form` in a valid but unspecified state (like after a
+  // move). In particular, `*renderer_form` and its members can be reassigned.
+  void UpdateTreeOfRendererForm(FormData* renderer_form,
+                                ContentAutofillDriver* driver);
+
+  // The FrameData nodes of the forest.
+  // The members FrameData::frame_token must not be mutated.
+  // Note that since the elements are (smart) pointers, they are not invalidated
+  // when the set is resized (unlike pointers or references to the elements).
+  base::flat_set<std::unique_ptr<FrameData>, FrameData::CompareByFrameToken>
+      frame_datas_;
+};
+
+}  // namespace internal
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_H_
diff --git a/components/autofill/content/browser/form_forest_test_api.cc b/components/autofill/content/browser/form_forest_test_api.cc
new file mode 100644
index 0000000..ed5d450
--- /dev/null
+++ b/components/autofill/content/browser/form_forest_test_api.cc
@@ -0,0 +1,89 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/content/browser/form_forest_test_api.h"
+
+#include <iomanip>
+
+namespace autofill {
+namespace internal {
+
+void FormForestTestApi::ExpandForm(base::stack<FrameForm>& frontier,
+                                   FrameForm frame_and_form) {
+  for (const FrameTokenWithPredecessor& child :
+       frame_and_form.form->child_frames) {
+    absl::optional<LocalFrameToken> local_child =
+        Resolve(*frame_and_form.frame, child.token);
+    FrameData* child_frame;
+    if (local_child && (child_frame = GetFrameData(*local_child))) {
+      for (FormData& child_form : child_frame->child_forms)
+        frontier.push({child_frame, &child_form});
+    }
+  }
+}
+
+std::ostream& FormForestTestApi::PrintTree(std::ostream& os) {
+  base::stack<FrameForm> frontier;
+  for (const std::unique_ptr<FrameData>& frame : frame_datas()) {
+    DCHECK(frame);
+    if (frame && !frame->parent_form) {
+      for (FormData& form : frame->child_forms)
+        frontier.push({frame.get(), &form});
+    }
+  }
+  TraverseTrees(frontier, [this, &os](const FormData& form) mutable {
+    int level = [this, &form] {
+      LocalFrameToken frame = form.host_frame;
+      for (int level = 0;; ++level) {
+        const FrameData* frame_data = GetFrameData(frame);
+        if (!frame_data || !frame_data->parent_form)
+          return level;
+        frame = frame_data->parent_form->frame_token;
+      }
+    }();
+    PrintForm(os, form, level);
+  });
+  return os;
+}
+
+std::ostream& FormForestTestApi::PrintForm(std::ostream& os,
+                                           const FormData& form,
+                                           int level) {
+  std::string prefix(2 * level, ' ');
+  os << prefix << "Form " << *form.unique_renderer_id << " at "
+     << form.host_frame << " at " << form.full_url.GetOrigin() << " with "
+     << form.fields.size() << " fields" << std::endl;
+  os << prefix << "Origin " << form.main_frame_origin.Serialize() << std::endl;
+  if (!form.name.empty())
+    os << prefix << "Name " << form.name << std::endl;
+  int i = 0;
+  const FrameData* frame = GetFrameData(form.host_frame);
+  if (frame) {
+    for (const FrameTokenWithPredecessor& child : form.child_frames) {
+      auto local_child = Resolve(*frame, child.token);
+      os << prefix << std::setfill(' ') << std::setw(2) << ++i << ". Frame "
+         << absl::visit([](auto x) { return x.ToString(); }, child.token)
+         << " -> " << (local_child ? local_child->ToString() : "") << std::endl;
+    }
+  }
+  i = 0;
+  for (const FormFieldData& field : form.fields) {
+    os << prefix << std::setfill(' ') << std::setw(2) << ++i << ". Field "
+       << *field.unique_renderer_id << " at " << field.host_frame << " at "
+       << field.origin.Serialize() << std::endl;
+    if (!field.id_attribute.empty())
+      os << prefix << "    ID " << field.id_attribute << std::endl;
+    if (!field.name_attribute.empty())
+      os << prefix << "    Name " << field.name_attribute << std::endl;
+    if (!field.value.empty())
+      os << prefix << "    Value " << field.value << std::endl;
+    if (!field.label.empty())
+      os << prefix << "    Label "
+         << field.label.substr(0, field.label.find('\n')) << std::endl;
+  }
+  return os;
+}
+
+}  // namespace internal
+}  // namespace autofill
diff --git a/components/autofill/content/browser/form_forest_test_api.h b/components/autofill/content/browser/form_forest_test_api.h
new file mode 100644
index 0000000..bb4ecf0
--- /dev/null
+++ b/components/autofill/content/browser/form_forest_test_api.h
@@ -0,0 +1,81 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_TEST_API_H_
+#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_TEST_API_H_
+
+#include "base/containers/stack.h"
+#include "components/autofill/content/browser/form_forest.h"
+
+namespace autofill {
+namespace internal {
+
+// Exposes some testing (and debugging) operations for FormForest.
+class FormForestTestApi {
+ public:
+  using FrameData = FormForest::FrameData;
+  using FrameForm = FormForest::FrameAndForm;
+
+  static absl::optional<LocalFrameToken> Resolve(const FrameData& local,
+                                                 FrameToken other) {
+    return FormForest::Resolve(local, other);
+  }
+
+  explicit FormForestTestApi(FormForest* ff) : ff_(ff) { DCHECK(ff_); }
+
+  FrameData* GetFrameData(LocalFrameToken frame) {
+    return ff_->GetFrameData(frame);
+  }
+
+  FormData* GetFormData(const FormGlobalId& form,
+                        FrameData* frame_data = nullptr) {
+    return ff_->GetFormData(form, frame_data);
+  }
+
+  FrameForm GetRoot(FormGlobalId form) { return ff_->GetRoot(form); }
+
+  FormForest& form_forest() { return *ff_; }
+
+  base::flat_set<std::unique_ptr<FrameData>, FrameData::CompareByFrameToken>&
+  frame_datas() {
+    return ff_->frame_datas_;
+  }
+
+  // Prints debug information.
+  std::ostream& PrintTree(std::ostream& os);
+  std::ostream& PrintForm(std::ostream& os,
+                          const FormData& form,
+                          int level = 0);
+
+  // Calls `fun(f)` for every form in the subtrees induced by |frontier| in DOM
+  // order (pre-order, depth-first).
+  template <typename UnaryFunction>
+  void TraverseTrees(base::stack<FrameForm>& frontier, UnaryFunction fun = {});
+
+ private:
+  // Adds the frame and form children for `frame_and_form.form` to |frontier|.
+  void ExpandForm(base::stack<FrameForm>& frontier, FrameForm frame_and_form);
+
+  // Non-null pointer to wrapped FormForest.
+  FormForest* ff_;
+};
+
+template <typename UnaryFunction>
+void FormForestTestApi::TraverseTrees(base::stack<FrameForm>& frontier,
+                                      UnaryFunction fun) {
+  while (!frontier.empty()) {
+    FrameForm next = frontier.top();
+    frontier.pop();
+    DCHECK(next);
+    if (!next)
+      continue;
+    fun(*next.form);
+    ExpandForm(frontier, next);
+  }
+}
+
+}  // namespace internal
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CONTENT_BROWSER_FORM_FOREST_TEST_API_H_
diff --git a/components/autofill/content/browser/form_forest_unittest.cc b/components/autofill/content/browser/form_forest_unittest.cc
new file mode 100644
index 0000000..62fbf92
--- /dev/null
+++ b/components/autofill/content/browser/form_forest_unittest.cc
@@ -0,0 +1,1377 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/strings/strcat.h"
+#include "base/strings/string_piece.h"
+#include "components/autofill/content/browser/form_forest.h"
+#include "components/autofill/content/browser/form_forest_test_api.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
+
+using FrameData = autofill::internal::FormForest::FrameData;
+using FrameDataSet =
+    base::flat_set<std::unique_ptr<FrameData>, FrameData::CompareByFrameToken>;
+
+using ::testing::AllOf;
+using ::testing::ByRef;
+using ::testing::ElementsAreArray;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::Matcher;
+using ::testing::Pointee;
+using ::testing::Property;
+using ::testing::UnorderedElementsAreArray;
+
+namespace autofill {
+namespace internal {
+namespace {
+
+// Matchers.
+
+auto Equals(const FormFieldData& exp);
+auto Equals(const FormData& exp);
+auto Equals(const FrameData& exp);
+
+template <typename T>
+auto ArrayEquals(const std::vector<T>& exp) {
+  std::vector<Matcher<T>> matchers;
+  for (const T& f : exp)
+    matchers.push_back(Equals(f));
+  return ElementsAreArray(matchers);
+}
+
+template <typename T>
+auto UnorderedArrayEquals(const std::vector<T>& exp) {
+  std::vector<Matcher<T>> matchers;
+  for (const T& f : exp)
+    matchers.push_back(Equals(f));
+  return UnorderedElementsAreArray(matchers);
+}
+
+// The relevant attributes are FormFieldData::global_id(), FormFieldData::value.
+// We additionally compare a few more attributes just for safety.
+auto Equals(const FormFieldData& exp) {
+  return AllOf(
+      Property("global_id", &FormFieldData::global_id, exp.global_id()),
+      Field("name", &FormFieldData::name, exp.name),
+      Field("host_form_id", &FormFieldData::host_form_id, exp.host_form_id),
+      Field("origin", &FormFieldData::origin, exp.origin),
+      Field("form_control_type", &FormFieldData::form_control_type,
+            exp.form_control_type),
+      Field("value", &FormFieldData::value, exp.value),
+      Field("label", &FormFieldData::label, exp.label));
+}
+
+// The relevant attributes are FormData::global_id(), FormData::fields.
+// We additionally compare a few more attributes just for safety.
+auto Equals(const FormData& exp) {
+  return AllOf(Property("global_id", &FormData::global_id, Eq(exp.global_id())),
+               Field("name", &FormData::name, exp.name),
+               Field("main_frame_origin", &FormData::main_frame_origin,
+                     exp.main_frame_origin),
+               Field("action", &FormData::action, exp.action),
+               Field("full_url", &FormData::full_url, exp.full_url),
+               Field("url", &FormData::url, exp.url),
+               Field("fields", &FormData::fields, ArrayEquals(exp.fields)));
+}
+
+// Compares all attributes of FrameData.
+auto Equals(const FrameData& exp) {
+  return AllOf(Field("frame_token", &FrameData::frame_token, exp.frame_token),
+               Field("child_forms", &FrameData::child_forms,
+                     ArrayEquals(exp.child_forms)),
+               Field("parent_forms", &FrameData::parent_form, exp.parent_form),
+               Field("driver", &FrameData::driver, exp.driver));
+}
+
+// Deep comparison of the unique_ptrs in a FrameDataSet.
+auto Equals(const FrameDataSet& exp) {
+  std::vector<Matcher<std::unique_ptr<FrameData>>> matchers;
+  for (const std::unique_ptr<FrameData>& x : exp)
+    matchers.push_back(Pointee(Equals(*x)));
+  return ElementsAreArray(matchers);
+}
+
+// Compares all attributes of FormForest. (Since frame_datas_ is private, we use
+// its accessor.)
+auto Equals(const FormForest& exp) {
+  return Property(&FormForest::frame_datas, Equals(exp.frame_datas()));
+}
+
+// Test form.
+
+// The basic test form is a credit card form with six fields: first name, last
+// name, number, month, year, CVC.
+FormData CreateForm() {
+  FormData form;
+  test::CreateTestCreditCardFormData(&form, true, false, true);
+  DCHECK_EQ(form.fields.size(), 6u);
+  return form;
+}
+
+// Creates a field type map for the form with N >= 0 repetitions of the fields
+// from CreateForm().
+auto CreateFieldTypeMap(const FormData& form) {
+  DCHECK_EQ(form.fields.size() % 6, 0u);
+  DCHECK_GT(form.fields.size() / 6, 0u);
+  base::flat_map<FieldGlobalId, ServerFieldType> map;
+  for (size_t i = 0; i < form.fields.size() / 6; ++i) {
+    map[form.fields[6 * i + 0].global_id()] = CREDIT_CARD_NAME_FIRST;
+    map[form.fields[6 * i + 1].global_id()] = CREDIT_CARD_NAME_LAST;
+    map[form.fields[6 * i + 2].global_id()] = CREDIT_CARD_NUMBER;
+    map[form.fields[6 * i + 3].global_id()] = CREDIT_CARD_EXP_MONTH;
+    map[form.fields[6 * i + 4].global_id()] = CREDIT_CARD_EXP_4_DIGIT_YEAR;
+    map[form.fields[6 * i + 5].global_id()] = CREDIT_CARD_VERIFICATION_CODE;
+  }
+  return map;
+}
+
+// A profile is a 6-bit integer, whose bits indicate different values of first
+// and last name, credit card number, expiration month, expiration year, CVC.
+using Profile = base::StrongAlias<struct ProfileTag, size_t>;
+
+// Fills the fields 0..5 of |form| with data according to |profile|, the
+// fields 6..11 with |profile|+1, etc.
+FormData WithValues(FormData& form, Profile profile = Profile(0)) {
+  DCHECK_EQ(form.fields.size() % 6, 0u);
+  DCHECK_GT(form.fields.size() / 6, 0u);
+  for (size_t i = 0; i < form.fields.size() / 6; ++i) {
+    std::bitset<6> bitset(profile.value() + i);
+    form.fields[6 * i + 0].value = bitset.test(0) ? u"Jane" : u"John";
+    form.fields[6 * i + 1].value = bitset.test(1) ? u"Doe" : u"Average";
+    form.fields[6 * i + 2].value =
+        bitset.test(2) ? u"4444333322221111" : u"4444444444444444";
+    form.fields[6 * i + 3].value = bitset.test(3) ? u"01" : u"12";
+    form.fields[6 * i + 4].value = bitset.test(4) ? u"2083" : u"2087";
+    form.fields[6 * i + 5].value = bitset.test(5) ? u"123" : u"456";
+  }
+  return form;
+}
+
+// Clears the values of all fields in |form|.
+FormData WithoutValues(FormData form) {
+  for (FormFieldData& field : form.fields)
+    field.value.clear();
+  return form;
+}
+
+// Utility functions and constants.
+
+// Use strings for non-opaque origins and URLs because constructors must not be
+// called before the test is set up.
+const std::string kMainUrl("https://main.frame.com/");
+const std::string kIframeUrl("https://iframe.frame.com/");
+const std::string kOtherUrl("https://other.frame.com/");
+const url::Origin kOpaqueOrigin;
+
+url::Origin Origin(const GURL& url) {
+  return url::Origin::Create(url);
+}
+
+url::Origin Origin(base::StringPiece url) {
+  return Origin(GURL(url));
+}
+
+LocalFrameToken Token(content::RenderFrameHost* rfh) {
+  return LocalFrameToken(rfh->GetFrameToken().value());
+}
+
+// Mimics ContentAutofillDriver::SetFormAndFrameMetaData().
+void SetMetaData(FormRendererId host_form,
+                 FormFieldData& field,
+                 content::RenderFrameHost* rfh) {
+  field.host_frame = Token(rfh);
+  field.host_form_id = host_form;
+  field.origin = rfh->GetLastCommittedOrigin();
+}
+
+void SetMetaData(FormData& form, content::RenderFrameHost* rfh) {
+  form.host_frame = Token(rfh);
+  form.main_frame_origin = rfh->GetMainFrame()->GetLastCommittedOrigin();
+  for (FormFieldData& field : form.fields)
+    SetMetaData(form.unique_renderer_id, field, rfh);
+}
+
+FormForestTestApi TestApi(FormForest& ff) {
+  return FormForestTestApi(&ff);
+}
+
+FrameDataSet& frame_datas(FormForest& ff) {
+  return TestApi(ff).frame_datas();
+}
+
+// Flattens a vector by concatenating the elements of the outer vector.
+template <typename T>
+std::vector<T> Flattened(const std::vector<std::vector<T>>& xs) {
+  std::vector<T> concat;
+  for (const auto& x : xs)
+    concat.insert(concat.end(), x.begin(), x.end());
+  return concat;
+}
+
+// Computes all permutations of |xs|.
+// Intended for testing::ValuesIn().
+template <typename T>
+std::vector<std::vector<T>> Permutations(const std::vector<T>& xs) {
+  auto factorial = [](size_t n) -> size_t {
+    return std::round(std::tgamma(n + 1));
+  };
+  std::vector<std::vector<T>> ps;
+  ps.reserve(factorial(xs.size()));
+  ps.push_back(xs);
+  base::ranges::sort(ps.front());
+  while (base::ranges::next_permutation(ps.front()))
+    ps.push_back(ps.front());
+  DCHECK_EQ(ps.size(), factorial(xs.size()));
+  return ps;
+}
+
+// Computes the permutations of |xs| and concatenates each permutation.
+// For example,
+//   FlattenedPermutations({{"a", "b"}, {"x", "y"}})
+// returns
+//   { {"a", "b", "x", "y"},
+//     {"x", "y", "a", "b"} }
+// because
+//   Permutations({{"a", "b"}, {"x", "y"}})
+// returns
+//   { {{"a", "b"}, {"x", "y"}},
+//     {{"x", "y"}, {"a", "b"}} }
+// and
+//   Flatten({{"a", "b"}, {"x", "y"}})
+// returns
+//   {"a", "b", "x", "y"}.
+// Intended for testing::ValuesIn(), in particular for
+// FormForestTestUpdateOrder.
+template <typename T>
+std::vector<std::vector<T>> FlattenedPermutations(
+    const std::vector<std::vector<T>>& xs) {
+  std::vector<std::vector<T>> result;
+  base::ranges::transform(Permutations(xs), std::back_inserter(result),
+                          &Flattened<std::string>);
+  return result;
+}
+
+class MockContentAutofillDriver : public ContentAutofillDriver {
+ public:
+  explicit MockContentAutofillDriver(content::RenderFrameHost* rfh)
+      : ContentAutofillDriver(rfh) {}
+
+  LocalFrameToken token() { return Token(render_frame_host()); }
+
+  MOCK_METHOD(void, TriggerReparse, (), (override));
+};
+
+// Fundamental test fixtures.
+
+// Test fixture for all FormForest tests.
+//
+// Within FormForestTest, we use RemoteFrameTokens only to test scenarios where
+// the token cannot be resolved to a LocalFrameToken. In any other case, frames
+// shall have LocalFrameTokens. This simplifies the mocking machinery needed
+// (that is to say, I couldn't figure out how to mock frames with
+// RemoteFrameTokens.)
+class FormForestTest : public content::RenderViewHostTestHarness {
+ public:
+  // The frame's permissions policy affects which fields may be filled (see
+  // FormForest::GetBrowserFormOfRendererForm() for details).
+  enum class Policy { kNone, kSharedAutofill };
+
+  void SetUp() override {
+    RenderViewHostTestHarness::SetUp();
+    DCHECK(kOpaqueOrigin.opaque());
+  }
+
+  void TearDown() override {
+    autofill_drivers_.clear();
+    RenderViewHostTestHarness::TearDown();
+  }
+
+ protected:
+  MockContentAutofillDriver* NavigateMainFrame(const GURL& url) {
+    content::NavigationSimulator::CreateBrowserInitiated(url, web_contents())
+        ->Commit();
+    return GetOrCreateDriver(main_rfh());
+  }
+
+  // Creates a fresh child frame of |parent| with permissions |policy| and
+  // navigates it to |url|. The frame's name appears to be optional.
+  MockContentAutofillDriver* CreateAndNavigateChildFrame(
+      ContentAutofillDriver* parent,
+      const GURL& url,
+      Policy policy,
+      base::StringPiece name) {
+    auto permissions =
+        policy != Policy::kSharedAutofill
+            ? blink::ParsedPermissionsPolicy()
+            : blink::ParsedPermissionsPolicy(
+                  {blink::ParsedPermissionsPolicyDeclaration(
+                      blink::mojom::PermissionsPolicyFeature::kSharedAutofill,
+                      {Origin(url)}, false, false)});
+    content::RenderFrameHost* rfh =
+        content::RenderFrameHostTester::For(parent->render_frame_host())
+            ->AppendChildWithPolicy(std::string(name), permissions);
+    return NavigateFrame(rfh, url);
+  }
+
+ private:
+  MockContentAutofillDriver* NavigateFrame(content::RenderFrameHost* rfh,
+                                           const GURL& url) {
+    rfh = content::NavigationSimulator::NavigateAndCommitFromDocument(url, rfh);
+    return GetOrCreateDriver(rfh);
+  }
+
+  MockContentAutofillDriver* GetOrCreateDriver(content::RenderFrameHost* rfh) {
+    auto it = autofill_drivers_.find(rfh);
+    if (it == autofill_drivers_.end()) {
+      it = autofill_drivers_
+               .emplace(rfh, std::make_unique<MockContentAutofillDriver>(rfh))
+               .first;
+    }
+    return it->second.get();
+  }
+
+  std::map<content::RenderFrameHost*,
+           std::unique_ptr<MockContentAutofillDriver>>
+      autofill_drivers_;
+};
+
+// Test fixture with a mocked frame/form tree.
+//
+// FrameInfo and FormInfo represent mocked forms and can be syntactically
+// arranged in a tree structure using designated initializers.
+class FormForestTestWithMockedTree : public FormForestTest {
+ public:
+  struct FormInfo;
+
+  struct FrameInfo {
+    std::string name = "";
+    // The default value of |url| is changed to kMainUrl or kIframeUrl in
+    // MockFormForest().
+    std::string url = "";
+    std::vector<FormInfo> forms = {};
+    FormForestTest::Policy policy = FormForestTest::Policy::kNone;
+    // The index of the last field from the parent form that precedes this
+    // frame. This is analogous to FormData::child_frames[i].predecessor.
+    int field_predecessor = std::numeric_limits<int>::max();
+  };
+
+  struct FormInfo {
+    std::string name = "";
+    FormData form = CreateForm();
+    std::vector<FrameInfo> frames = {};
+  };
+
+  struct FormSpan {
+    base::StringPiece form;
+    size_t begin = 0;
+    size_t count = base::dynamic_extent;
+  };
+
+  void TearDown() override {
+    mocked_forms_.Reset();
+    flattened_forms_.Reset();
+    drivers_.clear();
+    forms_.clear();
+    FormForestTest::TearDown();
+  }
+
+  // Initializes the |mocked_forms_| according to the frame/form tree
+  // |frame_info|.
+  MockContentAutofillDriver* MockFormForest(
+      const FrameInfo& frame_info,
+      MockContentAutofillDriver* parent_driver = nullptr,
+      FormData* parent_form = nullptr) {
+    DCHECK_EQ(!parent_driver, !parent_form);
+    GURL url(!frame_info.url.empty()
+                 ? frame_info.url
+                 : (!parent_driver ? kMainUrl : kIframeUrl));
+    MockContentAutofillDriver* driver =
+        !parent_driver
+            ? NavigateMainFrame(url)
+            : CreateAndNavigateChildFrame(parent_driver, url, frame_info.policy,
+                                          frame_info.name);
+    if (!frame_info.name.empty()) {
+      DCHECK(!base::Contains(drivers_, frame_info.name));
+      drivers_.emplace(std::string(frame_info.name), driver);
+    }
+
+    std::vector<FormData> forms;
+    for (const FormInfo& form_info : frame_info.forms) {
+      FormData data = form_info.form;
+      data.name = base::ASCIIToUTF16(form_info.name);
+      data.url = url;
+      for (FormFieldData& field : data.fields)
+        field.name = base::StrCat({data.name, u".", field.name});
+      SetMetaData(data, driver->render_frame_host());
+
+      // Creates the frames and set their predecessor field according to
+      // FrameInfo::field_predecessor. By default, the frames come after all
+      // fields.
+      for (const FrameInfo& subframe_info : form_info.frames) {
+        MockContentAutofillDriver* child =
+            MockFormForest(subframe_info, driver, &data);
+        data.child_frames.emplace_back();
+        data.child_frames.back().token = child->token();
+        data.child_frames.back().predecessor =
+            std::min(static_cast<int>(data.fields.size()),
+                     subframe_info.field_predecessor);
+      }
+
+      if (!form_info.name.empty()) {
+        DCHECK(!base::Contains(forms_, form_info.name));
+        forms_.emplace(form_info.name, data.global_id());
+      }
+      forms.push_back(data);
+    }
+
+    auto frame_data = std::make_unique<FrameData>(driver->token());
+    frame_data->child_forms = std::move(forms);
+    if (parent_form)
+      frame_data->parent_form = parent_form->global_id();
+    frame_data->driver = driver;
+    auto p = frame_datas(mocked_forms_).insert(std::move(frame_data));
+    DCHECK(p.second);
+    return driver;
+  }
+
+  // Mocks flattening of |form_fields| into their root form.
+  //
+  // Exactly one form mentioned in |form_fields| must be a root form in. The
+  // function flattens the fields specified by |form_fields| into this root, in
+  // the same order they appear in |form_fields|.
+  //
+  // MockFlattening() should be called only after MockFormForest(), as its first
+  // call copies the forms without their fields from |mocked_forms_| to
+  // |flattened_forms_|.
+  void MockFlattening(const std::vector<FormSpan>& form_fields) {
+    // Collect fields.
+    std::vector<FormFieldData> fields;
+    for (FormSpan f : form_fields) {
+      const FormData& source = GetMockedForm(f.form);
+      if (f.begin >= source.fields.size())
+        continue;
+      if (f.begin + f.count > source.fields.size())
+        f.count = base::dynamic_extent;
+      base::ranges::copy(
+          base::make_span(source.fields).subspan(f.begin, f.count),
+          std::back_inserter(fields));
+    }
+
+    // Copy |mocked_forms_| into |flattened_forms_|, without fields.
+    if (frame_datas(flattened_forms_).empty()) {
+      std::vector<std::unique_ptr<FrameData>> copy;
+      for (const auto& frame : frame_datas(mocked_forms_)) {
+        copy.push_back(std::make_unique<FrameData>(frame->frame_token));
+        copy.back()->parent_form = frame->parent_form;
+        copy.back()->child_forms = frame->child_forms;
+        for (FormData& child_form : copy.back()->child_forms)
+          child_form.fields.clear();
+        copy.back()->driver = frame->driver;
+      }
+      frame_datas(flattened_forms_) = FrameDataSet(std::move(copy));
+    }
+
+    // Copy fields to the root.
+    auto IsRoot = [this](FormSpan fs) {
+      return driver(fs.form)->IsInMainFrame();
+    };
+    auto it = base::ranges::find_if(form_fields, IsRoot);
+    DCHECK(it != form_fields.end());
+    DCHECK(base::ranges::all_of(form_fields, [&](FormSpan fs) {
+      return !IsRoot(fs) || fs.form == it->form;
+    }));
+    GetFlattenedForm(it->form).fields = fields;
+
+    // Validate flattening.
+    DCHECK_EQ(frame_datas(flattened_forms_).size(),
+              frame_datas(mocked_forms_).size());
+    auto IsRoorOrEmpty = [](const auto& frame) {
+      return !frame->parent_form ||
+             base::ranges::all_of(frame->child_forms,
+                                  &std::vector<FormFieldData>::empty,
+                                  &FormData::fields);
+    };
+    DCHECK(base::ranges::all_of(frame_datas(flattened_forms_), IsRoorOrEmpty));
+  }
+
+  MockContentAutofillDriver* driver(base::StringPiece frame_or_form_name) {
+    auto it = drivers_.find(frame_or_form_name);
+    if (it != drivers_.end()) {
+      return it->second;
+    } else {
+      LocalFrameToken frame_token =
+          GetMockedForm(frame_or_form_name).host_frame;
+      const FrameData* frame_data =
+          TestApi(mocked_forms_).GetFrameData(frame_token);
+      return static_cast<MockContentAutofillDriver*>(frame_data->driver);
+    }
+  }
+
+  FormData& GetMockedForm(base::StringPiece form_name) {
+    auto it = forms_.find(form_name);
+    DCHECK(it != forms_.end()) << form_name;
+    FormData* form = TestApi(mocked_forms_).GetFormData(it->second);
+    DCHECK(form);
+    return *form;
+  }
+
+  FormData& GetFlattenedForm(base::StringPiece form_name) {
+    DCHECK(driver(form_name)->IsInMainFrame());
+    auto it = forms_.find(form_name);
+    DCHECK(it != forms_.end()) << form_name;
+    FormData* form = TestApi(flattened_forms_).GetFormData(it->second);
+    DCHECK(form);
+    return *form;
+  }
+
+  FormForest mocked_forms_;
+  FormForest flattened_forms_;
+
+ private:
+  std::map<std::string, MockContentAutofillDriver*, std::less<>> drivers_;
+  std::map<std::string, FormGlobalId, std::less<>> forms_;
+};
+
+// Tests of FormForest::UpdateTreeOfRendererForm().
+
+class FormForestTestUpdateTree : public FormForestTestWithMockedTree {
+ public:
+  // The subject of this test fixture.
+  void UpdateTreeOfRendererForm(FormForest& ff, base::StringPiece form_name) {
+    ff.UpdateTreeOfRendererForm(GetMockedForm(form_name), driver(form_name));
+  }
+};
+
+// Tests that reset empties a FormForest.
+TEST_F(FormForestTestUpdateTree, Reset) {
+  MockFormForest({.forms = {{.name = "main"}}});
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "main");
+  EXPECT_FALSE(frame_datas(ff).empty());
+  ff.Reset();
+  EXPECT_TRUE(frame_datas(ff).empty());
+}
+
+// Tests that different root forms are not merged.
+TEST_F(FormForestTestUpdateTree, MultipleRoots) {
+  MockFormForest(
+      {.forms = {
+           {.name = "main1", .frames = {{.forms = {{.name = "child1"}}}}},
+           {.name = "main2", .frames = {{.forms = {{.name = "child2"}}}}}}});
+  MockFlattening({{"main1"}, {"child1"}});
+  MockFlattening({{"main2"}, {"child2"}});
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "main1");
+  UpdateTreeOfRendererForm(ff, "main2");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+// Tests that (only) for forms with unseen parent form TriggerReparse is called
+// on the parent frame.
+TEST_F(FormForestTestUpdateTree, TriggerReparse) {
+  MockFormForest(
+      {.forms = {
+           {.name = "main1", .frames = {{.forms = {{.name = "child1"}}}}},
+           {.name = "main2", .frames = {{.forms = {{.name = "child2"}}}}}}});
+  MockFlattening({{"main1"}, {"child1"}});
+  MockFlattening({{"main2"}, {"child2"}});
+  FormForest ff;
+  EXPECT_CALL(*driver("main1"), TriggerReparse).Times(0);
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "main1");
+  EXPECT_CALL(*driver("main2"), TriggerReparse).Times(1);
+  UpdateTreeOfRendererForm(ff, "child2");
+  EXPECT_CALL(*driver("main2"), TriggerReparse).Times(0);
+  UpdateTreeOfRendererForm(ff, "main2");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+using FormNameVector = std::vector<std::string>;
+
+// Parameterized by a list of forms, which in this order are added to the
+// FormForest.
+// Note that among the forms from the same form, the order of calling
+// UpdateTreeOfRendererForm() matters.
+// Hence, when generating permutations, use FlattenedPermutations() to keep the
+// forms from the same frame in stable order.
+class FormForestTestUpdateOrder
+    : public FormForestTestUpdateTree,
+      public ::testing::WithParamInterface<FormNameVector> {
+ protected:
+  void UpdateFormForestAccordingToParamOrder() {
+    for (const std::string& form_name : GetParam())
+      UpdateTreeOfRendererForm(ff_, form_name);
+  }
+
+  FormForest ff_;
+};
+
+class FormForestTestUpdateVerticalOrder : public FormForestTestUpdateOrder {};
+
+// Tests that children and grandchildren are merged into their root form.
+TEST_P(FormForestTestUpdateVerticalOrder, Test) {
+  MockFormForest(
+      {.forms = {
+           {.name = "main",
+            .frames = {
+                {.url = kIframeUrl,
+                 .forms = {{.name = "inner",
+                            .frames = {{.forms = {{.name = "leaf"}}}}}}}}}}});
+  MockFlattening({{"main"}, {"inner"}, {"leaf"}});
+  UpdateFormForestAccordingToParamOrder();
+  EXPECT_THAT(ff_, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateVerticalOrder,
+                         testing::ValuesIn(Permutations(FormNameVector{
+                             "main", "inner", "leaf"})));
+
+class FormForestTestUpdateHorizontalMultiFormSingleFrameOrder
+    : public FormForestTestUpdateOrder {};
+
+// Tests that siblings from the same frames are merged into their root form.
+TEST_P(FormForestTestUpdateHorizontalMultiFormSingleFrameOrder, Test) {
+  MockFormForest({.forms = {{.name = "main",
+                             .frames = {{.forms = {{.name = "child1"},
+                                                   {.name = "child2"}}}}}}});
+  MockFlattening({{"main"}, {"child1"}, {"child2"}});
+  UpdateFormForestAccordingToParamOrder();
+  EXPECT_THAT(ff_, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    FormForestTest,
+    FormForestTestUpdateHorizontalMultiFormSingleFrameOrder,
+    testing::ValuesIn(FlattenedPermutations(
+        std::vector<std::vector<std::string>>{{"main"},
+                                              {"child1", "child2"}})));
+
+class FormForestTestUpdateHorizontalMultiFrameSingleFormOrder
+    : public FormForestTestUpdateOrder {};
+
+// Tests that siblings from different frames are merged into their root form.
+TEST_P(FormForestTestUpdateHorizontalMultiFrameSingleFormOrder, Test) {
+  MockFormForest({.forms = {{.name = "main",
+                             .frames = {{.forms = {{.name = "child1"}}},
+                                        {.forms = {{.name = "child2"}}}}}}});
+  MockFlattening({{"main"}, {"child1"}, {"child2"}});
+  UpdateFormForestAccordingToParamOrder();
+  EXPECT_THAT(ff_, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    FormForestTest,
+    FormForestTestUpdateHorizontalMultiFrameSingleFormOrder,
+    testing::ValuesIn(Permutations(FormNameVector{"main", "child1",
+                                                  "child2"})));
+
+class FormForestTestUpdateHorizontalMultiFormMultiFrameOrder
+    : public FormForestTestUpdateOrder {};
+
+// Tests that siblings from multiple and the same frame are merged into their
+// root form.
+TEST_P(FormForestTestUpdateHorizontalMultiFormMultiFrameOrder, Test) {
+  auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+    return base::StrCat({kMainUrl, path});
+  };
+  MockFormForest(
+      {.url = url("main"),
+       .forms = {{.name = "main",
+                  .frames = {{.url = url("child1+2"),
+                              .forms = {{.name = "child1"}, {.name = "child2"}},
+                              .field_predecessor = -1},
+                             {.url = url("child3+4"),
+                              .forms = {{.name = "child3"}, {.name = "child4"}},
+                              .field_predecessor = 5}}}}});
+  MockFlattening({{"child1"}, {"child2"}, {"main"}, {"child3"}, {"child4"}});
+  UpdateFormForestAccordingToParamOrder();
+  EXPECT_THAT(ff_, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateHorizontalMultiFormMultiFrameOrder,
+                         testing::ValuesIn(FlattenedPermutations(
+                             std::vector<std::vector<std::string>>{
+                                 {"main"},
+                                 {"child1", "child2"},
+                                 {"child3", "child4"}})));
+
+using ChildFramePredecessors = std::tuple<int, int, int>;
+
+// Parameterized by the indices of the fields that precede child frames.
+class FormForestTestUpdateSplitForm
+    : public FormForestTestUpdateTree,
+      public ::testing::WithParamInterface<ChildFramePredecessors> {};
+
+// Tests that fields of subforms are inserted into the parent form at the
+// index as specified by FormData::child_frame_predecessors.
+TEST_P(FormForestTestUpdateSplitForm, Test) {
+  int field0 = std::get<0>(GetParam());
+  int field1 = std::get<1>(GetParam());
+  int field2 = std::get<2>(GetParam());
+  ASSERT_LE(-1, field0);
+  ASSERT_LE(field0, field1);
+  ASSERT_LE(field1, field2);
+  MockFormForest(
+      {.forms = {{.name = "main",
+                  .frames = {{.forms = {{.name = "child1"}, {.name = "child2"}},
+                              .field_predecessor = field0},
+                             {.forms = {{.name = "child3"}, {.name = "child4"}},
+                              .field_predecessor = field1},
+                             {.forms = {{.name = "child5"}, {.name = "child6"}},
+                              .field_predecessor = field2}}}}});
+  MockFlattening({{.form = "main", .count = base::as_unsigned(field0 + 1)},
+                  {"child1"},
+                  {"child2"},
+                  {.form = "main",
+                   .begin = base::as_unsigned(field0 + 1),
+                   .count = base::as_unsigned(field1 - field0)},
+                  {"child3"},
+                  {"child4"},
+                  {.form = "main",
+                   .begin = base::as_unsigned(field1 + 1),
+                   .count = base::as_unsigned(field2 - field1)},
+                  {"child5"},
+                  {"child6"},
+                  {.form = "main", .begin = base::as_unsigned(field2 + 1)}});
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "child3");
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "child4");
+  UpdateTreeOfRendererForm(ff, "child5");
+  UpdateTreeOfRendererForm(ff, "child6");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateSplitForm,
+                         testing::Values(ChildFramePredecessors{-1, -1, -1},
+                                         ChildFramePredecessors{-1, 2, 5},
+                                         ChildFramePredecessors{1, 1, 1},
+                                         ChildFramePredecessors{3, 3, 3},
+                                         ChildFramePredecessors{5, 5, 5}));
+
+class FormForestTestUpdateComplexOrder : public FormForestTestUpdateOrder {};
+
+// Tests for a complex tree that all descendants are merged into their root.
+TEST_P(FormForestTestUpdateComplexOrder, Test) {
+  auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+    return base::StrCat({kMainUrl, path});
+  };
+  MockFormForest(
+      {.url = url("main"),
+       .forms = {
+           {.name = "main",
+            .frames = {
+                {.url = url("children"),
+                 .forms = {{.name = "child1",
+                            .frames = {{.url = url("grandchild1+2"),
+                                        .forms = {{.name = "grandchild1"},
+                                                  {.name = "grandchild2"}},
+                                        .field_predecessor = -1},
+                                       {.url = url("grandchild3+4"),
+                                        .forms = {{.name = "grandchild3"},
+                                                  {.name = "grandchild4"}},
+                                        .field_predecessor = 5}}},
+                           {.name = "child2"}},
+                 .field_predecessor = 2}}}}});
+  MockFlattening({{.form = "main", .count = 3},
+                  {"grandchild1"},
+                  {"grandchild2"},
+                  {"child1"},
+                  {"grandchild3"},
+                  {"grandchild4"},
+                  {"child2"},
+                  {.form = "main", .begin = 3}});
+  UpdateFormForestAccordingToParamOrder();
+  EXPECT_THAT(ff_, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateComplexOrder,
+                         testing::ValuesIn(FlattenedPermutations(
+                             std::vector<std::vector<std::string>>{
+                                 {"main"},
+                                 {"child1", "child2"},
+                                 {"grandchild1", "grandchild2"},
+                                 {"grandchild3", "grandchild4"}})));
+
+// Tests that erasing a frame removes its form and fields.
+TEST_F(FormForestTestUpdateTree, EraseFrame) {
+  MockFormForest(
+      {.forms = {
+           {.name = "main",
+            .frames = {
+                {.url = kIframeUrl,
+                 .forms = {{.name = "inner",
+                            .frames = {{.forms = {{.name = "leaf"}}}}}}}}}}});
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "inner");
+  UpdateTreeOfRendererForm(ff, "leaf");
+  ff.EraseFrame(GetMockedForm("leaf").host_frame);
+  frame_datas(mocked_forms_).erase(GetMockedForm("leaf").host_frame);
+  MockFlattening({{"main"}, {"inner"}});
+  ASSERT_EQ(GetFlattenedForm("main").fields.size(), 12u);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+// Parameterized with a source and an optional target form and field index.
+class FormForestTestUpdateFieldChange : public FormForestTestUpdateTree {
+ protected:
+  void MockFormForest() {
+    auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+      return base::StrCat({kMainUrl, path});
+    };
+    FormForestTestWithMockedTree::MockFormForest(
+        {.url = url("main"),
+         .forms = {
+             {.name = "main",
+              .frames = {{.url = url("child1+2"),
+                          .forms = {{.name = "child1"}, {.name = "child2"}},
+                          .field_predecessor = -1},
+                         {.url = url("child3+4"),
+                          .forms = {{.name = "child3"}, {.name = "child4"}},
+                          .field_predecessor = 2},
+                         {.url = url("child5+6"),
+                          .forms = {{.name = "child5"}, {.name = "child6"}},
+                          .field_predecessor = 5}}}}});
+  }
+
+  void MockFlattening() {
+    FormForestTestWithMockedTree::MockFlattening(
+        {{"child1"},
+         {"child2"},
+         {.form = "main", .count = 3},
+         {"child3"},
+         {"child4"},
+         {.form = "main", .begin = 3, .count = 3},
+         {"child5"},
+         {"child6"},
+         {.form = "main", .begin = 6}});
+  }
+
+  void UpdateTreeOfAllForms(FormForest& ff) {
+    UpdateTreeOfRendererForm(ff, "main");
+    UpdateTreeOfRendererForm(ff, "child1");
+    UpdateTreeOfRendererForm(ff, "child2");
+    UpdateTreeOfRendererForm(ff, "child3");
+    UpdateTreeOfRendererForm(ff, "child4");
+    UpdateTreeOfRendererForm(ff, "child5");
+    UpdateTreeOfRendererForm(ff, "child6");
+  }
+};
+
+struct FieldSpec {
+  std::string form_name;
+  size_t field_index;
+};
+
+// Removes a field according to the parameter.
+class FormForestTestUpdateFieldRemove
+    : public FormForestTestUpdateFieldChange,
+      public ::testing::WithParamInterface<FieldSpec> {
+ protected:
+  void DoRemove() {
+    FormData& source_form = GetMockedForm(GetParam().form_name);
+    size_t source_index = GetParam().field_index;
+    source_form.fields.erase(source_form.fields.begin() + source_index);
+  }
+};
+
+// Tests that removing fields from a form is reflected in the form tree.
+TEST_P(FormForestTestUpdateFieldRemove, Test) {
+  MockFormForest();
+  MockFlattening();
+  FormForest ff;
+  UpdateTreeOfAllForms(ff);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+  DoRemove();
+  MockFlattening();
+  UpdateTreeOfRendererForm(ff, GetParam().form_name);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateFieldRemove,
+                         testing::Values(FieldSpec{"main", 2},
+                                         FieldSpec{"main", 3},
+                                         FieldSpec{"child1", 0},
+                                         FieldSpec{"child2", 1},
+                                         FieldSpec{"child3", 2},
+                                         FieldSpec{"child4", 3},
+                                         FieldSpec{"child5", 4},
+                                         FieldSpec{"child6", 5}));
+
+// Adds a new field according to the parameter.
+class FormForestTestUpdateFieldAdd
+    : public FormForestTestUpdateFieldChange,
+      public ::testing::WithParamInterface<FieldSpec> {
+ protected:
+  void DoAdd() {
+    FormData& target_form = GetMockedForm(GetParam().form_name);
+    size_t target_index = GetParam().field_index;
+    FormFieldData field = target_form.fields.front();
+    field.name = base::StrCat({field.name, u"_copy"});
+    field.unique_renderer_id = test::MakeFieldRendererId();
+    target_form.fields.insert(target_form.fields.begin() + target_index, field);
+  }
+};
+
+// Tests that adding a field to forms is reflected in the form tree.
+TEST_P(FormForestTestUpdateFieldAdd, Test) {
+  MockFormForest();
+  MockFlattening();
+  FormForest ff;
+  UpdateTreeOfAllForms(ff);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+  DoAdd();
+  MockFlattening();
+  UpdateTreeOfRendererForm(ff, GetParam().form_name);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestUpdateFieldAdd,
+                         testing::Values(FieldSpec{"main", 2},
+                                         FieldSpec{"main", 3},
+                                         FieldSpec{"child1", 0},
+                                         FieldSpec{"child2", 1},
+                                         FieldSpec{"child3", 2},
+                                         FieldSpec{"child4", 3},
+                                         FieldSpec{"child5", 4},
+                                         FieldSpec{"child6", 5}));
+
+struct FieldMoveSpec {
+  FieldSpec source;
+  FieldSpec target;
+};
+
+// Moves a field from one form to another according to the parameter.
+class FormForestTestUpdateFieldMove
+    : public FormForestTestUpdateFieldChange,
+      public ::testing::WithParamInterface<FieldMoveSpec> {
+ protected:
+  void DoMove() {
+    const FieldMoveSpec& p = GetParam();
+    FormData& source_form = GetMockedForm(p.source.form_name);
+    size_t source_index = p.source.field_index;
+    FormData& target_form = GetMockedForm(p.target.form_name);
+    size_t target_index = p.target.field_index;
+
+    FormFieldData field = source_form.fields[source_index];
+    field.host_form_id = target_form.unique_renderer_id;
+
+    if (source_index > target_index) {
+      source_form.fields.erase(source_form.fields.begin() + source_index);
+      target_form.fields.insert(target_form.fields.begin() + target_index,
+                                field);
+    } else {
+      target_form.fields.insert(target_form.fields.begin() + target_index,
+                                field);
+      source_form.fields.erase(source_form.fields.begin() + source_index);
+    }
+  }
+};
+
+// Tests that moving fields between forms (of the same frame) is reflected in
+// the form tree.
+TEST_P(FormForestTestUpdateFieldMove, Test) {
+  MockFormForest();
+  MockFlattening();
+  FormForest ff;
+  UpdateTreeOfAllForms(ff);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+  DoMove();
+  MockFlattening();
+  UpdateTreeOfRendererForm(ff, GetParam().source.form_name);
+  if (GetParam().source.form_name != GetParam().target.form_name)
+    UpdateTreeOfRendererForm(ff, GetParam().target.form_name);
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    FormForestTest,
+    FormForestTestUpdateFieldMove,
+    testing::Values(FieldMoveSpec{{"main", 0}, {"main", 5}},
+                    FieldMoveSpec{{"main", 5}, {"main", 0}},
+                    FieldMoveSpec{{"child1", 0}, {"child1", 5}},
+                    FieldMoveSpec{{"child1", 5}, {"child1", 0}},
+                    FieldMoveSpec{{"child1", 1}, {"child1", 4}},
+                    FieldMoveSpec{{"child1", 3}, {"child2", 3}},
+                    FieldMoveSpec{{"child3", 5}, {"child4", 0}},
+                    FieldMoveSpec{{"child6", 5}, {"child5", 0}}));
+
+// Tests that UpdateTreeOfRendererForm() converges, that is, multiple calls are
+// no-ops.
+TEST_F(FormForestTestUpdateTree, Converge) {
+  auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+    return base::StrCat({kMainUrl, path});
+  };
+  MockFormForest(
+      {.url = url("main"),
+       .forms = {
+           {.name = "main",
+            .frames = {
+                {.url = url("children"),
+                 .forms = {{.name = "child1",
+                            .frames = {{.url = url("grandchild1"),
+                                        .forms = {{.name = "grandchild1"}}},
+                                       {.url = url("grandchild2"),
+                                        .forms = {{.name = "grandchild2"}}}}},
+                           {.name = "child2"}}}}}}});
+  MockFlattening(
+      {{"main"}, {"child1"}, {"grandchild1"}, {"grandchild2"}, {"child2"}});
+
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "grandchild1");
+  UpdateTreeOfRendererForm(ff, "grandchild2");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "grandchild1");
+  UpdateTreeOfRendererForm(ff, "grandchild2");
+  UpdateTreeOfRendererForm(ff, "grandchild2");
+  UpdateTreeOfRendererForm(ff, "grandchild1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "main");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+// Tests that removing a frame from FormData::child_frames removes the fields
+// (but not the FrameData; this is taken care of by EraseFrame()).
+TEST_F(FormForestTestUpdateTree, RemoveFrame) {
+  auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+    return base::StrCat({kMainUrl, path});
+  };
+  // |child1| is a separate variable for better code formatting.
+  FormInfo child1 = {
+      .name = "child1",
+      .frames = {
+          {.url = url("grandchild1"), .forms = {{.name = "grandchild1"}}},
+          {.url = url("grandchild2"),
+           .forms = {{.name = "grandchild2",
+                      .frames = {{.url = url("greatgrandchild"),
+                                  .forms = {{.name = "greatgrandchild"}}}}}}}}};
+  MockFormForest(
+      {.url = url("main"),
+       .forms = {{.name = "main",
+                  .frames = {{.url = url("children"),
+                              .forms = {child1, {.name = "child2"}}}}}}});
+  MockFlattening({{"main"},
+                  {"child1"},
+                  {"grandchild1"},
+                  {"grandchild2"},
+                  {"greatgrandchild"},
+                  {"child2"}});
+
+  FormForest ff;
+  UpdateTreeOfRendererForm(ff, "main");
+  UpdateTreeOfRendererForm(ff, "child1");
+  UpdateTreeOfRendererForm(ff, "child2");
+  UpdateTreeOfRendererForm(ff, "grandchild1");
+  UpdateTreeOfRendererForm(ff, "grandchild2");
+  UpdateTreeOfRendererForm(ff, "greatgrandchild");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+  ASSERT_EQ(GetFlattenedForm("main").fields.size(), 6u * 6u);
+
+  // Remove the last frame of "child1", which contains "grandchild2" and
+  // indirectly "greatgrandchild".
+  GetMockedForm("child1").child_frames.pop_back();
+  TestApi(mocked_forms_)
+      .GetFrameData(GetMockedForm("grandchild2").host_frame)
+      ->parent_form.reset();
+  GetMockedForm("grandchild2").fields.clear();
+  MockFlattening({{"main"}, {"child1"}, {"grandchild1"}, {"child2"}});
+  ASSERT_EQ(GetFlattenedForm("main").fields.size(), 4u * 6u);
+
+  UpdateTreeOfRendererForm(ff, "child1");
+  EXPECT_THAT(ff, Equals(flattened_forms_));
+}
+
+// Tests of FormForest::GetBrowserFormOfRendererForm().
+
+class FormForestTestFlatten : public FormForestTestWithMockedTree {
+ protected:
+  // The subject of this test fixture.
+  FormData GetBrowserFormOfRendererForm(base::StringPiece form_name) {
+    return flattened_forms_.GetBrowserFormOfRendererForm(
+        GetMockedForm(form_name));
+  }
+};
+
+// Tests that flattening a single frame is the identity.
+TEST_F(FormForestTestFlatten, SingleFrame) {
+  MockFormForest({.url = kMainUrl, .forms = {{.name = "main"}}});
+  MockFlattening({{"main"}});
+  EXPECT_THAT(GetBrowserFormOfRendererForm("main"),
+              Equals(GetFlattenedForm("main")));
+}
+
+class FormForestTestFlattenHierarchy
+    : public FormForestTestFlatten,
+      public ::testing::WithParamInterface<std::string> {};
+
+// Tests that a non-trivial tree is flattened into the root.
+TEST_P(FormForestTestFlattenHierarchy, TwoFrames) {
+  MockFormForest(
+      {.forms = {
+           {.name = "main",
+            .frames = {{.forms = {{.name = "child1"}, {.name = "child2"}}}}},
+           {.name = "main2",
+            .frames = {{.forms = {{.name = "child3"}, {.name = "child4"}}}}}}});
+  MockFlattening({{"main"}, {"child1"}, {"child2"}});
+  MockFlattening({{"main2"}, {"child3"}, {"child4"}});
+  EXPECT_THAT(GetBrowserFormOfRendererForm(GetParam()),
+              Equals(GetFlattenedForm("main")));
+}
+
+INSTANTIATE_TEST_SUITE_P(FormForestTest,
+                         FormForestTestFlattenHierarchy,
+                         testing::Values("main", "child1", "child2"));
+
+// Tests of FormForest::GetRendererFormsOfBrowserForm().
+
+class FormForestTestUnflatten : public FormForestTestWithMockedTree {
+ protected:
+  // The subject of this test fixture.
+  std::vector<FormData> GetRendererFormsOfBrowserForm(
+      base::StringPiece form_name,
+      const url::Origin& triggered_origin,
+      const base::flat_map<FieldGlobalId, ServerFieldType>& field_type_map) {
+    return flattened_forms_.GetRendererFormsOfBrowserForm(
+        WithValues(GetFlattenedForm(form_name)), triggered_origin,
+        field_type_map);
+  }
+
+  auto FieldTypeMap(base::StringPiece form_name) {
+    return CreateFieldTypeMap(WithValues(GetFlattenedForm(form_name)));
+  }
+};
+
+// Test that solitaire main frame forms are filled as usual.
+TEST_F(FormForestTestUnflatten, MainFrame) {
+  MockFormForest({.url = kMainUrl,
+                  .forms = {{.name = "main", .frames = {}},
+                            {.name = "main2", .frames = {}}}});
+  MockFlattening({{"main"}});
+  MockFlattening({{"main2"}});
+  std::vector<FormData> expectation = {WithValues(GetMockedForm("main"))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kMainUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Test that child frame forms are filled as usual.
+TEST_F(FormForestTestUnflatten, ChildFrame) {
+  MockFormForest({.url = kMainUrl,
+                  .forms = {{.name = "main",
+                             .frames = {{.url = kIframeUrl,
+                                         .forms = {{.name = "child"}}}}}}});
+  MockFlattening({{"main"}, {"child"}});
+  std::vector<FormData> expectation = {
+      GetMockedForm("main"), WithValues(GetMockedForm("child"), Profile(1))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kIframeUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Test that a tree of forms is filled (assuming same origins), but other
+// neighboring trees are not.
+TEST_F(FormForestTestUnflatten, LargeTree) {
+  auto url = [](base::StringPiece path) {  // Needed due to crbug/1217402.
+    return base::StrCat({kMainUrl, path});
+  };
+  MockFormForest(
+      {.url = url("main"),
+       .forms =
+           {{.name = "main",
+             .frames = {{.url = url("children"),
+                         .forms =
+                             {{.name = "child1",
+                               .frames = {{.url = url("grandchild1+2"),
+                                           .forms = {{.name = "grandchild1"},
+                                                     {.name = "grandchild2"}}},
+                                          {.url = url("grandchild3+4"),
+                                           .forms = {{.name = "grandchild3"},
+                                                     {.name =
+                                                          "grandchild4"}}}}},
+                              {.name = "child2"}}}}},
+            {.name = "main2",
+             .frames = {
+                 {.url = url("nieces"),
+                  .forms = {{.name = "niece1"}, {.name = "niece2"}}}}}}});
+  MockFlattening({{"main"},
+                  {"grandchild1"},
+                  {"grandchild2"},
+                  {"child1"},
+                  {"grandchild3"},
+                  {"grandchild4"},
+                  {"child2"}});
+  MockFlattening({{"main2"}, {"niece1"}, {"niece2"}});
+  std::vector<FormData> expectation = {
+      WithValues(GetMockedForm("main"), Profile(0)),
+      WithValues(GetMockedForm("grandchild1"), Profile(1)),
+      WithValues(GetMockedForm("grandchild2"), Profile(2)),
+      WithValues(GetMockedForm("child1"), Profile(3)),
+      WithValues(GetMockedForm("grandchild3"), Profile(4)),
+      WithValues(GetMockedForm("grandchild4"), Profile(5)),
+      WithValues(GetMockedForm("child2"), Profile(6))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kMainUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Tests that (only) frames from the same origin are filled.
+TEST_F(FormForestTestUnflatten, SameOriginPolicy) {
+  MockFormForest(
+      {.url = kMainUrl,
+       .forms = {
+           {.name = "main",
+            .frames = {{.url = kOtherUrl, .forms = {{.name = "child1"}}},
+                       {.url = kIframeUrl, .forms = {{.name = "child2"}}}}}}});
+  MockFlattening({{"main"}, {"child1"}, {"child2"}});
+  std::vector<FormData> expectation = {
+      WithoutValues(GetMockedForm("main")),
+      WithoutValues(GetMockedForm("child1")),
+      WithValues(GetMockedForm("child2"), Profile(2))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kIframeUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Tests that even if a different-origin frame interrupts two same-origin
+// frames, they are filled together.
+TEST_F(FormForestTestUnflatten, InterruptedSameOriginPolicy) {
+  MockFormForest(
+      {.url = kMainUrl,
+       .forms = {
+           {.name = "main",
+            .frames = {
+                {.url = kIframeUrl,
+                 .forms = {{.name = "inner",
+                            .frames = {{.url = kMainUrl,
+                                        .forms = {{.name = "leaf"}}}}}}}}}}});
+  MockFlattening({{"main"}, {"inner"}, {"leaf"}});
+  std::vector<FormData> expectation = {
+      WithValues(GetMockedForm("main"), Profile(0)),
+      WithoutValues(GetMockedForm("inner")),
+      WithValues(GetMockedForm("leaf"), Profile(2))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kMainUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Tests that (only) non-sensitive fields are filled cross-origin into the main
+// frame's origin.
+TEST_F(FormForestTestUnflatten, MainOriginPolicy) {
+  MockFormForest(
+      {.url = kMainUrl,
+       .forms = {
+           {.name = "main",
+            .frames = {{.url = kMainUrl, .forms = {{.name = "child1"}}},
+                       {.url = kIframeUrl, .forms = {{.name = "child2"}}}}}}});
+  MockFlattening({{"main"}, {"child1"}, {"child2"}});
+  std::vector<FormData> expectation = {
+      WithValues(GetMockedForm("main"), Profile(0)),
+      WithValues(GetMockedForm("child1"), Profile(1)),
+      WithValues(GetMockedForm("child2"), Profile(2))};
+  // Clear sensitive fields.
+  for (size_t i = 2; i < expectation[0].fields.size(); ++i) {
+    expectation[0].fields[i].value.clear();
+    expectation[1].fields[i].value.clear();
+  }
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kIframeUrl),
+                                            FieldTypeMap("main")),
+              UnorderedArrayEquals(expectation));
+}
+
+// Fixture for the shared-autofill policy tests.
+class FormForestTestUnflattenSharedAutofillPolicy
+    : public FormForestTestUnflatten {
+ public:
+  void SetUp() override {
+    FormForestTestUnflatten::SetUp();
+    MockFormForest(
+        {.url = kMainUrl,
+         .forms = {
+             {.name = "main",
+              .frames = {{.url = kOtherUrl, .forms = {{.name = "disallowed"}}},
+                         {.url = kIframeUrl,
+                          .forms = {{.name = "allowed"}},
+                          .policy = Policy::kSharedAutofill}}}}});
+    ASSERT_NE(Origin("main"), Origin("allowed"));
+    ASSERT_NE(Origin("disallowed"), Origin("allowed"));
+  }
+};
+
+// Tests filling into frames with shared-autofill policy from the main origin.
+TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromMainOrigin) {
+  MockFlattening({{"main"}, {"disallowed"}, {"allowed"}});
+  std::vector<FormData> expectation = {
+      WithValues(GetMockedForm("main"), Profile(0)),
+      WithoutValues(GetMockedForm("disallowed")),
+      WithValues(GetMockedForm("allowed"), Profile(2))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kMainUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Tests filling into frames with shared-autofill policy from the main origin.
+TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromOtherOrigin) {
+  MockFlattening({{"main"}, {"disallowed"}, {"allowed"}});
+  std::vector<FormData> expectation = {
+      WithoutValues(GetMockedForm("main")),
+      WithValues(GetMockedForm("disallowed"), Profile(1)),
+      WithoutValues(GetMockedForm("allowed"))};
+  EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kOtherUrl), {}),
+              UnorderedArrayEquals(expectation));
+}
+
+// Tests irreflexivity, asymmetry, transitivity of FrameData less-than relation.
+TEST(FormForestTest, FrameDataComparator) {
+  FrameData::CompareByFrameToken less;
+  std::unique_ptr<FrameData> null;
+  auto x = std::make_unique<FrameData>(test::GetLocalFrameToken());
+  auto xx = std::make_unique<FrameData>(test::GetLocalFrameToken());
+  auto y = std::make_unique<FrameData>(
+      LocalFrameToken(base::UnguessableToken::Deserialize(
+          x->frame_token->GetHighForSerialization() + 1,
+          x->frame_token->GetLowForSerialization() + 1)));
+  ASSERT_TRUE(x->frame_token < y->frame_token);
+  EXPECT_FALSE(less(null, null));
+  EXPECT_TRUE(less(null, x));
+  EXPECT_FALSE(less(x, null));
+  EXPECT_FALSE(less(x, x));
+  EXPECT_FALSE(less(xx, xx));
+  EXPECT_FALSE(less(x, xx));
+  EXPECT_FALSE(less(xx, x));
+  EXPECT_TRUE(less(x, y));
+  EXPECT_FALSE(less(y, x));
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace autofill
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index faf441e0..69db5836 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -403,10 +403,21 @@
 
 // mojom::AutofillAgent:
 void AutofillAgent::FillForm(int32_t id, const FormData& form) {
+  // If |element_| is null or not focused, a Autofill was triggered from another
+  // frame. In this case, set |element_| to some form field as if Autofill had
+  // been triggered from that field. This is necessary because currently
+  // AutofillAgent's relies on |elemet_| in many places.
+  if (id == kCrossFrameFill && !form.fields.empty() &&
+      (element_.IsNull() || !element_.Focused())) {
+    WebDocument document = render_frame()->GetWebFrame()->GetDocument();
+    element_ = form_util::FindFormControlElementByUniqueRendererId(
+        document, form.fields.front().unique_renderer_id);
+  }
+
   if (element_.IsNull())
     return;
 
-  if (id != autofill_query_id_ && id != kNoQueryId)
+  if (id != autofill_query_id_ && id != kNoQueryId && id != kCrossFrameFill)
     return;
 
   was_last_action_fill_ = true;
@@ -431,10 +442,21 @@
 }
 
 void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
+  // If |element_| is null or not focused, a Autofill was triggered from another
+  // frame. In this case, set |element_| to some form field as if Autofill had
+  // been triggered from that field. This is necessary because currently
+  // AutofillAgent's relies on |elemet_| in many places.
+  if (id == kCrossFrameFill && !form.fields.empty() &&
+      (element_.IsNull() || !element_.Focused())) {
+    WebDocument document = render_frame()->GetWebFrame()->GetDocument();
+    element_ = form_util::FindFormControlElementByUniqueRendererId(
+        document, form.fields.front().unique_renderer_id);
+  }
+
   if (element_.IsNull())
     return;
 
-  if (id != autofill_query_id_)
+  if (id != autofill_query_id_ && id != kCrossFrameFill)
     return;
 
   ClearPreviewedForm();
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc
index 7b167c2..9db71d7 100644
--- a/components/autofill/core/browser/autofill_suggestion_generator.cc
+++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -193,8 +193,12 @@
   // Otherwise the label is the card number, or if that is empty the
   // cardholder name. The label should never repeat the value.
   if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
-    suggestion.value =
-        credit_card.CardIdentifierStringForAutofillDisplay(suggestion_nickname);
+    int obfuscation_length = base::FeatureList::IsEnabled(
+                                 autofill::features::kAutofillKeyboardAccessory)
+                                 ? 2
+                                 : 4;
+    suggestion.value = credit_card.CardIdentifierStringForAutofillDisplay(
+        suggestion_nickname, obfuscation_length);
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
     suggestion.label = credit_card.GetInfo(
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index c82171a..4ee34a0 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -909,9 +909,10 @@
       query_id, suggestions, /*autoselect_first_suggestion=*/false);
 }
 
-std::string ObfuscatedCardDigitsAsUTF8(const std::string& str) {
-  return base::UTF16ToUTF8(
-      internal::GetObfuscatedStringForCardDigits(base::ASCIIToUTF16(str)));
+std::string ObfuscatedCardDigitsAsUTF8(const std::string& str,
+                                       int obfuscation_length) {
+  return base::UTF16ToUTF8(internal::GetObfuscatedStringForCardDigits(
+      base::ASCIIToUTF16(str), obfuscation_length));
 }
 
 std::string NextMonth() {
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h
index 8ed4836..82b2a2b4 100644
--- a/components/autofill/core/browser/autofill_test_utils.h
+++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -370,7 +370,8 @@
 void GenerateTestAutofillPopup(
     AutofillExternalDelegate* autofill_external_delegate);
 
-std::string ObfuscatedCardDigitsAsUTF8(const std::string& str);
+std::string ObfuscatedCardDigitsAsUTF8(const std::string& str,
+                                       int obfuscation_length = 4);
 
 // Returns 2-digit month string, like "02", "10".
 std::string NextMonth();
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index e4ebd66..ecaf721 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -1634,13 +1634,18 @@
 
   const FormFieldData& credit_card_number_field = form.fields[1];
   GetAutofillSuggestions(form, credit_card_number_field);
-
+  int obfuscation_length = base::FeatureList::IsEnabled(
+                               autofill::features::kAutofillKeyboardAccessory)
+                               ? 2
+                               : 4;
   const std::string visa_value =
-      std::string("Visa  ") + test::ObfuscatedCardDigitsAsUTF8("3456");
+      std::string("Visa  ") +
+      test::ObfuscatedCardDigitsAsUTF8("3456", obfuscation_length);
   // Mastercard has a valid nickname. Display nickname + last four in the
   // suggestion title.
   const std::string master_card_value =
-      kArbitraryNickname + "  " + test::ObfuscatedCardDigitsAsUTF8("8765");
+      kArbitraryNickname + "  " +
+      test::ObfuscatedCardDigitsAsUTF8("8765", obfuscation_length);
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
   const std::string visa_label = std::string("04/99");
diff --git a/components/autofill/core/browser/data_model/borrowed_transliterator.cc b/components/autofill/core/browser/data_model/borrowed_transliterator.cc
index df72ad7..13944ce 100644
--- a/components/autofill/core/browser/data_model/borrowed_transliterator.cc
+++ b/components/autofill/core/browser/data_model/borrowed_transliterator.cc
@@ -5,6 +5,7 @@
 #include "components/autofill/core/browser/data_model/borrowed_transliterator.h"
 
 #include "base/logging.h"
+#include "base/no_destructor.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/browser/data_model/borrowed_transliterator.h b/components/autofill/core/browser/data_model/borrowed_transliterator.h
index d3cd161..1b9fcfd 100644
--- a/components/autofill/core/browser/data_model/borrowed_transliterator.h
+++ b/components/autofill/core/browser/data_model/borrowed_transliterator.h
@@ -6,7 +6,6 @@
 #define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_BORROWED_TRANSLITERATOR_H_
 
 #include "base/i18n/unicodestring.h"
-#include "base/no_destructor.h"
 #include "base/strings/string_piece.h"
 #include "base/synchronization/lock.h"
 #include "third_party/icu/source/common/unicode/unistr.h"
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc
index dadbda9..fbb7dbc 100644
--- a/components/autofill/core/browser/data_model/credit_card.cc
+++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -50,11 +50,14 @@
 //  - \u2022 - Bullet.
 //  - \u2006 - SIX-PER-EM SPACE (small space between bullets).
 //  - \u2060 - WORD-JOINER (makes obfuscated string undivisible).
-constexpr char16_t kMidlineEllipsis[] =
+constexpr char16_t kMidlineEllipsis4Dots[] =
     u"\u2022\u2060\u2006\u2060"
     u"\u2022\u2060\u2006\u2060"
     u"\u2022\u2060\u2006\u2060"
     u"\u2022\u2060\u2006\u2060";
+constexpr char16_t kMidlineEllipsis2Dots[] =
+    u"\u2022\u2060\u2006\u2060"
+    u"\u2022\u2060\u2006\u2060";
 
 namespace {
 
@@ -136,8 +139,13 @@
 
 namespace internal {
 
-std::u16string GetObfuscatedStringForCardDigits(const std::u16string& digits) {
-  std::u16string obfuscated_string = std::u16string(kMidlineEllipsis) + digits;
+std::u16string GetObfuscatedStringForCardDigits(const std::u16string& digits,
+                                                int obfuscation_length) {
+  DCHECK(obfuscation_length == 2 || obfuscation_length == 4);
+  std::u16string obfuscated_string =
+      std::u16string(obfuscation_length == 2 ? kMidlineEllipsis2Dots
+                                             : kMidlineEllipsis4Dots) +
+      digits;
   base::i18n::WrapStringWithLTRFormatting(&obfuscated_string);
   return obfuscated_string;
 }
@@ -898,7 +906,8 @@
 }
 
 std::u16string CreditCard::ObfuscatedLastFourDigits() const {
-  return internal::GetObfuscatedStringForCardDigits(LastFourDigits());
+  return internal::GetObfuscatedStringForCardDigits(LastFourDigits(),
+                                                    /*obfuscation_length=*/4);
 }
 
 std::string CreditCard::CardIconStringForAutofillSuggestion() const {
@@ -909,7 +918,8 @@
   return network_;
 }
 
-std::u16string CreditCard::NetworkAndLastFourDigits() const {
+std::u16string CreditCard::NetworkAndLastFourDigits(
+    int obfuscation_length) const {
   const std::u16string network = NetworkForDisplay();
   // TODO(crbug.com/734197): truncate network.
 
@@ -919,17 +929,19 @@
 
   // TODO(estade): i18n?
   const std::u16string obfuscated_string =
-      internal::GetObfuscatedStringForCardDigits(digits);
+      internal::GetObfuscatedStringForCardDigits(digits, obfuscation_length);
   return network.empty() ? obfuscated_string
                          : network + u"  " + obfuscated_string;
 }
 
 std::u16string CreditCard::CardIdentifierStringForAutofillDisplay(
-    std::u16string customized_nickname) const {
+    std::u16string customized_nickname,
+    int obfuscation_length) const {
   if (HasNonEmptyValidNickname() || !customized_nickname.empty()) {
-    return NicknameAndLastFourDigits(customized_nickname);
+    return NicknameAndLastFourDigits(customized_nickname, obfuscation_length);
   }
-  std::u16string networkAndLastFourDigits = NetworkAndLastFourDigits();
+  std::u16string networkAndLastFourDigits =
+      NetworkAndLastFourDigits(obfuscation_length);
   // Add Plex before the network and last four digits to identify it as a Google
   // Plex card.
   if (base::FeatureList::IsEnabled(features::kAutofillEnableGoogleIssuedCard) &&
@@ -1085,7 +1097,8 @@
 }
 
 std::u16string CreditCard::NicknameAndLastFourDigits(
-    std::u16string customized_nickname) const {
+    std::u16string customized_nickname,
+    int obfuscation_length) const {
   // Should call HasNonEmptyValidNickname() to check valid nickname before
   // calling this.
   DCHECK(HasNonEmptyValidNickname() || !customized_nickname.empty());
@@ -1095,7 +1108,8 @@
     return customized_nickname.empty() ? nickname_ : customized_nickname;
 
   return (customized_nickname.empty() ? nickname_ : customized_nickname) +
-         u"  " + internal::GetObfuscatedStringForCardDigits(digits);
+         u"  " +
+         internal::GetObfuscatedStringForCardDigits(digits, obfuscation_length);
 }
 
 void CreditCard::SetNumber(const std::u16string& number) {
diff --git a/components/autofill/core/browser/data_model/credit_card.h b/components/autofill/core/browser/data_model/credit_card.h
index 8ba7f16..d06c824 100644
--- a/components/autofill/core/browser/data_model/credit_card.h
+++ b/components/autofill/core/browser/data_model/credit_card.h
@@ -22,7 +22,8 @@
 struct AutofillMetadata;
 
 // A midline horizontal ellipsis (U+22EF).
-extern const char16_t kMidlineEllipsis[];
+extern const char16_t kMidlineEllipsis4Dots[];
+extern const char16_t kMidlineEllipsis2Dots[];
 
 namespace internal {
 
@@ -30,8 +31,10 @@
 // digits. To ensure that the obfuscation is placed at the left of the last four
 // digits, even for RTL languages, inserts a Left-To-Right Embedding mark at the
 // beginning and a Pop Directional Formatting mark at the end.
-// Exposed for testing.
-std::u16string GetObfuscatedStringForCardDigits(const std::u16string& digits);
+// `obfuscation_length` determines the number of dots to placed before the
+// digits. Exposed for testing.
+std::u16string GetObfuscatedStringForCardDigits(const std::u16string& digits,
+                                                int obfuscation_length);
 
 }  // namespace internal
 
@@ -285,18 +288,24 @@
   // The string used to represent the icon to be used for the autofill
   // suggestion. For ex: visaCC, googleIssuedCC, americanExpressCC, etc.
   std::string CardIconStringForAutofillSuggestion() const;
-  // A label for this card formatted as 'IssuerNetwork - ****2345'.
-  std::u16string NetworkAndLastFourDigits() const;
+  // A label for this card formatted as 'IssuerNetwork - ****2345'. By default,
+  // the `obfuscation_length` is set to 4 which would add **** to the last four
+  // digits of the card.
+  std::u16string NetworkAndLastFourDigits(int obfuscation_length = 4) const;
   // A label for this card formatted as 'Nickname - ****2345' if nickname is
   // available and valid;  otherwise, formatted as 'IssuerNetwork - ****2345'.
   // Google-issued cards have their own specific identifier, instead of
-  // displaying the issuer network name.
+  // displaying the issuer network name. By default, the `obfuscation_length` is
+  // set to 4 which would add **** to the last four digits of the card.
   std::u16string CardIdentifierStringForAutofillDisplay(
-      std::u16string customized_nickname = std::u16string()) const;
+      std::u16string customized_nickname = std::u16string(),
+      int obfuscation_length = 4) const;
+
 #if defined(OS_ANDROID)
   // Label for the card to be displayed in the manual filling view on Android.
   std::u16string CardIdentifierStringForManualFilling() const;
 #endif  // OS_ANDROID
+
   // A label for this card formatted as 'Nickname - ****2345, expires on MM/YY'
   // if nickname experiment is turned on and nickname is available; otherwise,
   // formatted as 'IssuerNetwork - ****2345, expires on MM/YY'.
@@ -370,9 +379,12 @@
   std::u16string NetworkForFill() const;
 
   // A label for this card formatted as 'Nickname - ****2345'. Always call
-  // HasNonEmptyValidNickname() before calling this.
+  // HasNonEmptyValidNickname() before calling this. By default,
+  // the `obfuscation_length` is set to 4 which would add **** to the last four
+  // digits of the card.
   std::u16string NicknameAndLastFourDigits(
-      std::u16string customized_nickname = std::u16string()) const;
+      std::u16string customized_nickname = std::u16string(),
+      int obfuscation_length = 4) const;
 
   // Sets the name_on_card_ value based on the saved name parts.
   void SetNameOnCardFromSeparateParts();
diff --git a/components/autofill/core/browser/data_model/credit_card_unittest.cc b/components/autofill/core/browser/data_model/credit_card_unittest.cc
index 2e080019..b93066c 100644
--- a/components/autofill/core/browser/data_model/credit_card_unittest.cc
+++ b/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -23,6 +23,7 @@
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/grit/components_scaled_resources.h"
@@ -93,8 +94,9 @@
   const std::u16string digits = u"1235";
   const std::u16string expected =
       std::u16string() + base::i18n::kLeftToRightEmbeddingMark +
-      kMidlineEllipsis + digits + base::i18n::kPopDirectionalFormatting;
-  EXPECT_EQ(expected, internal::GetObfuscatedStringForCardDigits(digits));
+      kMidlineEllipsis4Dots + digits + base::i18n::kPopDirectionalFormatting;
+  EXPECT_EQ(expected, internal::GetObfuscatedStringForCardDigits(
+                          digits, /*obfuscation_length=*/4));
 }
 
 // Tests credit card summary string generation.  This test simulates a variety
@@ -1715,23 +1717,27 @@
 TEST(CreditCardTest, LastFourDigits) {
   CreditCard card(base::GenerateGUID(), "https://www.example.com/");
   ASSERT_EQ(std::u16string(), card.LastFourDigits());
-  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(std::u16string()),
+  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(
+                std::u16string(), /*obfuscation_length=*/4),
             card.ObfuscatedLastFourDigits());
 
   test::SetCreditCardInfo(&card, "Baby Face Nelson", "5212341234123489", "01",
                           "2010", "1");
   ASSERT_EQ(u"3489", card.LastFourDigits());
-  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(u"3489"),
+  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(
+                u"3489", /*obfuscation_length=*/4),
             card.ObfuscatedLastFourDigits());
 
   card.SetRawInfo(CREDIT_CARD_NUMBER, u"3489");
   ASSERT_EQ(u"3489", card.LastFourDigits());
-  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(u"3489"),
+  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(
+                u"3489", /*obfuscation_length=*/4),
             card.ObfuscatedLastFourDigits());
 
   card.SetRawInfo(CREDIT_CARD_NUMBER, u"489");
   ASSERT_EQ(u"489", card.LastFourDigits());
-  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(u"489"),
+  ASSERT_EQ(internal::GetObfuscatedStringForCardDigits(
+                u"489", /*obfuscation_length=*/4),
             card.ObfuscatedLastFourDigits());
 }
 
@@ -1901,4 +1907,27 @@
             true, testingTimes.next_year_.month, testingTimes.next_year_.year,
             CreditCard::FULL_SERVER_CARD, CreditCard::EXPIRED}));
 
+#if defined(OS_ANDROID)
+class CreditCardTestForKeyboardAccessory : public testing::Test {
+ public:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        autofill::features::kAutofillKeyboardAccessory);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(CreditCardTestForKeyboardAccessory, GetObfuscatedStringForCardDigits) {
+  const std::u16string digits = u"1235";
+  const std::u16string expected =
+      std::u16string() + base::i18n::kLeftToRightEmbeddingMark +
+      kMidlineEllipsis2Dots + digits + base::i18n::kPopDirectionalFormatting;
+
+  EXPECT_EQ(expected, internal::GetObfuscatedStringForCardDigits(
+                          digits, /*obfuscation_length=*/2));
+}
+#endif  // OS_ANDROID
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/payments/autofill_credit_card_filling_infobar_delegate_mobile.cc b/components/autofill/core/browser/payments/autofill_credit_card_filling_infobar_delegate_mobile.cc
index 4e934854..7452164 100644
--- a/components/autofill/core/browser/payments/autofill_credit_card_filling_infobar_delegate_mobile.cc
+++ b/components/autofill/core/browser/payments/autofill_credit_card_filling_infobar_delegate_mobile.cc
@@ -27,7 +27,8 @@
 #if defined(OS_IOS)
       card_label_(card.NetworkAndLastFourDigits()),
 #else
-      card_label_(std::u16string(kMidlineEllipsis) + card.LastFourDigits()),
+      card_label_(std::u16string(kMidlineEllipsis4Dots) +
+                  card.LastFourDigits()),
 #endif
       card_sub_label_(card.AbbreviatedExpirationDateForDisplay(false)) {
 }
diff --git a/components/autofill/core/common/autofill_constants.h b/components/autofill/core/common/autofill_constants.h
index 86911c5..5d3e154e 100644
--- a/components/autofill/core/common/autofill_constants.h
+++ b/components/autofill/core/common/autofill_constants.h
@@ -50,6 +50,10 @@
 // is initiated from the browser.
 constexpr int kNoQueryId = -1;
 
+// Special query id used between the browser and the renderer when the action
+// is initiated from the browser.
+constexpr int kCrossFrameFill = -2;
+
 // Options bitmask values for AutofillHostMsg_ShowPasswordSuggestions IPC
 enum ShowPasswordSuggestionsOptions {
   SHOW_ALL = 1 << 0 /* show all credentials, not just ones matching username */,
diff --git a/components/cast_streaming/public/config_conversions.cc b/components/cast_streaming/public/config_conversions.cc
index 4822eb2..77cc948 100644
--- a/components/cast_streaming/public/config_conversions.cc
+++ b/components/cast_streaming/public/config_conversions.cc
@@ -16,7 +16,7 @@
 media::VideoCodecProfile ToVideoDecoderConfigCodecProfile(
     openscreen::cast::VideoCodec codec) {
   switch (codec) {
-    // TODO(b/186875732): Determine the values for Hevc and Vp9 experimentally.
+    // TODO(b/186875732): Determine values for Hevc, Vp9, Av1 experimentally.
     case openscreen::cast::VideoCodec::kH264:
       return media::VideoCodecProfile::H264PROFILE_BASELINE;
     case openscreen::cast::VideoCodec::kHevc:
@@ -25,6 +25,8 @@
       return media::VideoCodecProfile::VP8PROFILE_MIN;
     case openscreen::cast::VideoCodec::kVp9:
       return media::VideoCodecProfile::VP9PROFILE_PROFILE0;
+    case openscreen::cast::VideoCodec::kAv1:
+      return media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN;
     case openscreen::cast::VideoCodec::kNotSpecified:
       break;
   }
@@ -59,6 +61,8 @@
       return media::VideoCodec::kCodecHEVC;
     case openscreen::cast::VideoCodec::kVp9:
       return media::VideoCodec::kCodecVP9;
+    case openscreen::cast::VideoCodec::kAv1:
+      return media::VideoCodec::kCodecAV1;
     case openscreen::cast::VideoCodec::kNotSpecified:
       break;
   }
diff --git a/components/crash/content/browser/BUILD.gn b/components/crash/content/browser/BUILD.gn
index 5d51207..b2b08636e 100644
--- a/components/crash/content/browser/BUILD.gn
+++ b/components/crash/content/browser/BUILD.gn
@@ -8,7 +8,7 @@
   import("//build/config/android/config.gni")
 }
 
-# TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+# TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
 assert(!is_fuchsia)
 
 source_set("browser") {
diff --git a/components/crash/core/app/BUILD.gn b/components/crash/core/app/BUILD.gn
index 10786e81..6b77473 100644
--- a/components/crash/core/app/BUILD.gn
+++ b/components/crash/core/app/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
+# TODO(crbug.com/1226159): Complete crash reporting integration on Fuchsia.
 assert(!is_fuchsia)
 
 import("//components/gwp_asan/buildflags/buildflags.gni")
diff --git a/components/download/internal/background_service/BUILD.gn b/components/download/internal/background_service/BUILD.gn
index be17f61..82c4184 100644
--- a/components/download/internal/background_service/BUILD.gn
+++ b/components/download/internal/background_service/BUILD.gn
@@ -123,6 +123,8 @@
     ":*",
     "//components/download/content/factory",
     "//components/download/internal/background_service/ios:background_service",
+    "//components/download/internal/background_service/ios:unit_tests",
+    "//ios/chrome/browser/download/background_service:background_service",
   ]
 
   deps = [
diff --git a/components/download/internal/background_service/ios/BUILD.gn b/components/download/internal/background_service/ios/BUILD.gn
index dc9ecbc..5d02711 100644
--- a/components/download/internal/background_service/ios/BUILD.gn
+++ b/components/download/internal/background_service/ios/BUILD.gn
@@ -9,6 +9,8 @@
     "background_download_service_impl.h",
     "background_download_task_helper.h",
     "background_download_task_helper.mm",
+    "entry_utils.cc",
+    "entry_utils.h",
   ]
 
   visibility = [
@@ -33,6 +35,7 @@
     ":background_service",
     "//base",
     "//base/test:test_support",
+    "//components/download/internal/background_service:common",
     "//components/download/internal/background_service/test:test_support",
     "//components/download/public/background_service/test:test_support",
     "//net",
@@ -44,5 +47,6 @@
   sources = [
     "background_download_service_impl_unittest.cc",
     "background_download_task_helper_unittest.mm",
+    "entry_utils_unittest.cc",
   ]
 }
diff --git a/components/download/internal/background_service/ios/background_download_service_impl.cc b/components/download/internal/background_service/ios/background_download_service_impl.cc
index 1d43967..1a5297e 100644
--- a/components/download/internal/background_service/ios/background_download_service_impl.cc
+++ b/components/download/internal/background_service/ios/background_download_service_impl.cc
@@ -9,9 +9,11 @@
 #include "base/logging.h"
 #include "base/notreached.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "components/download/internal/background_service/client_set.h"
 #include "components/download/internal/background_service/config.h"
 #include "components/download/internal/background_service/entry.h"
 #include "components/download/internal/background_service/ios/background_download_task_helper.h"
+#include "components/download/internal/background_service/ios/entry_utils.h"
 #include "components/download/public/background_service/client.h"
 #include "components/download/public/background_service/download_metadata.h"
 #include "components/download/public/background_service/download_params.h"
@@ -31,7 +33,7 @@
 }  // namespace
 
 BackgroundDownloadServiceImpl::BackgroundDownloadServiceImpl(
-    std::unique_ptr<DownloadClientMap> clients,
+    std::unique_ptr<ClientSet> clients,
     std::unique_ptr<Model> model,
     std::unique_ptr<BackgroundDownloadTaskHelper> download_helper)
     : config_(std::make_unique<Configuration>()),
@@ -119,15 +121,18 @@
 void BackgroundDownloadServiceImpl::OnModelReady(bool success) {
   init_success_ = success;
   if (!success) {
-    for (const auto& client_it : *clients_.get())
-
-      client_it.second->OnServiceUnavailable();
+    // Report service failure to clients.
+    for (DownloadClient client_id : clients_->GetRegisteredClients())
+      clients_->GetClient(client_id)->OnServiceUnavailable();
     return;
   }
 
-  // TODO(xingliu): Create list of metadata and call OnServiceInitialized().
-  for (const auto& client_it : *clients_.get())
-    client_it.second->OnServiceUnavailable();
+  // Report download metadata to clients.
+  auto metadata_map = util::MapEntriesToMetadataForClients(
+      clients_->GetRegisteredClients(), model_->PeekEntries());
+  for (DownloadClient client_id : clients_->GetRegisteredClients())
+    clients_->GetClient(client_id)->OnServiceInitialized(
+        /*state_lost=*/false, metadata_map[client_id]);
 }
 
 void BackgroundDownloadServiceImpl::OnModelHardRecoverComplete(bool success) {}
@@ -171,13 +176,12 @@
     const std::string& guid,
     bool success,
     const base::FilePath& file_path) {
-  auto it = clients_->find(download_client);
-  if (it == clients_->end())
+  download::Client* client = clients_->GetClient(download_client);
+  if (!client)
     return;
 
   // TODO(xingliu): Plumb more details from platform api for failure reasons and
   // bytes downloaded.
-  download::Client* client = it->second.get();
   if (!success) {
     model_->Remove(guid);
     client->OnDownloadFailed(guid, CompletionInfo(),
@@ -194,10 +198,10 @@
     DownloadClient download_client,
     const std::string& guid,
     int64_t bytes_downloaded) {
-  auto it = clients_->find(download_client);
-  if (it == clients_->end())
+  download::Client* client = clients_->GetClient(download_client);
+  if (!client)
     return;
-  download::Client* client = it->second.get();
+
   client->OnDownloadUpdated(guid, /*bytes_uploaded*/ 0u,
                             static_cast<uint64_t>(bytes_downloaded));
 }
diff --git a/components/download/internal/background_service/ios/background_download_service_impl.h b/components/download/internal/background_service/ios/background_download_service_impl.h
index 07497e6..7b59332 100644
--- a/components/download/internal/background_service/ios/background_download_service_impl.h
+++ b/components/download/internal/background_service/ios/background_download_service_impl.h
@@ -19,6 +19,7 @@
 namespace download {
 
 class BackgroundDownloadTaskHelper;
+class ClientSet;
 class Model;
 struct Configuration;
 struct DownloadParams;
@@ -28,7 +29,7 @@
                                       public Model::Client {
  public:
   BackgroundDownloadServiceImpl(
-      std::unique_ptr<DownloadClientMap> clients,
+      std::unique_ptr<ClientSet> clients,
       std::unique_ptr<Model> model,
       std::unique_ptr<BackgroundDownloadTaskHelper> download_helper);
   ~BackgroundDownloadServiceImpl() override;
@@ -72,8 +73,7 @@
 
   std::unique_ptr<Configuration> config_;
   ServiceConfigImpl service_config_;
-  // TODO(xingliu): Ping clients for all events.
-  std::unique_ptr<DownloadClientMap> clients_;
+  std::unique_ptr<ClientSet> clients_;
   std::unique_ptr<Model> model_;
   std::unique_ptr<BackgroundDownloadTaskHelper> download_helper_;
   absl::optional<bool> init_success_;
diff --git a/components/download/internal/background_service/ios/background_download_service_impl_unittest.cc b/components/download/internal/background_service/ios/background_download_service_impl_unittest.cc
index 5c28b33..fce552c 100644
--- a/components/download/internal/background_service/ios/background_download_service_impl_unittest.cc
+++ b/components/download/internal/background_service/ios/background_download_service_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "components/download/internal/background_service/client_set.h"
 #include "components/download/internal/background_service/ios/background_download_task_helper.h"
 #include "components/download/internal/background_service/test/test_store.h"
 #include "components/download/public/background_service/test/mock_client.h"
@@ -63,10 +64,11 @@
     client_ = client.get();
     auto clients = std::make_unique<DownloadClientMap>();
     clients->insert(std::make_pair(DownloadClient::TEST, std::move(client)));
+    auto client_set = std::make_unique<ClientSet>(std::move(clients));
     auto download_helper = std::make_unique<MockBackgroundDownloadTaskHelper>();
     download_helper_ = download_helper.get();
     service_ = std::make_unique<BackgroundDownloadServiceImpl>(
-        std::move(clients), std::move(model), std::move(download_helper));
+        std::move(client_set), std::move(model), std::move(download_helper));
   }
 
   BackgroundDownloadService* service() { return service_.get(); }
@@ -94,6 +96,7 @@
 
 TEST_F(BackgroundDownloadServiceImplTest, InitSuccess) {
   EXPECT_EQ(ServiceStatus::STARTING_UP, service()->GetStatus());
+  EXPECT_CALL(*client_, OnServiceInitialized(false, _));
   store_->TriggerInit(/*success=*/true, empty_entries());
   EXPECT_EQ(ServiceStatus::READY, service()->GetStatus());
 }
diff --git a/components/download/internal/background_service/ios/entry_utils.cc b/components/download/internal/background_service/ios/entry_utils.cc
new file mode 100644
index 0000000..5c190db
--- /dev/null
+++ b/components/download/internal/background_service/ios/entry_utils.cc
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/ios/entry_utils.h"
+
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/public/background_service/download_metadata.h"
+
+namespace download {
+namespace util {
+
+std::map<DownloadClient, std::vector<DownloadMetaData>>
+MapEntriesToMetadataForClients(const std::set<DownloadClient>& clients,
+                               const std::vector<Entry*>& entries) {
+  std::map<DownloadClient, std::vector<DownloadMetaData>> categorized;
+
+  for (auto* entry : entries) {
+    DownloadClient client = entry->client;
+    if (clients.find(client) == clients.end())
+      continue;
+
+    DownloadMetaData meta_data;
+    meta_data.guid = entry->guid;
+    // iOS currently doesn't support pause.
+    meta_data.paused = false;
+    meta_data.current_size = entry->bytes_downloaded;
+    if (entry->state == Entry::State::COMPLETE) {
+      // TODO(xingliu): Implement the response headers and url chain with
+      // NSURLSession.
+      meta_data.completion_info =
+          CompletionInfo(entry->target_file_path, entry->bytes_downloaded,
+                         entry->url_chain, entry->response_headers);
+    }
+
+    categorized[client].emplace_back(std::move(meta_data));
+  }
+
+  return categorized;
+}
+
+}  // namespace util
+}  // namespace download
diff --git a/components/download/internal/background_service/ios/entry_utils.h b/components/download/internal/background_service/ios/entry_utils.h
new file mode 100644
index 0000000..87f7792
--- /dev/null
+++ b/components/download/internal/background_service/ios/entry_utils.h
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IOS_ENTRY_UTILS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IOS_ENTRY_UTILS_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "components/download/public/background_service/clients.h"
+
+namespace download {
+
+struct DownloadMetaData;
+struct Entry;
+
+namespace util {
+
+// Creates a map of DownloadMetaData for each client. Only works on iOS.
+std::map<DownloadClient, std::vector<DownloadMetaData>>
+MapEntriesToMetadataForClients(const std::set<DownloadClient>& clients,
+                               const std::vector<Entry*>& entries);
+
+}  // namespace util
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IOS_ENTRY_UTILS_H_
diff --git a/components/download/internal/background_service/ios/entry_utils_unittest.cc b/components/download/internal/background_service/ios/entry_utils_unittest.cc
new file mode 100644
index 0000000..b1a72f8
--- /dev/null
+++ b/components/download/internal/background_service/ios/entry_utils_unittest.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/ios/entry_utils.h"
+
+#include "components/download/internal/background_service/test/entry_utils.h"
+#include "components/download/public/background_service/download_metadata.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const base::FilePath::CharType kFilePath[] =
+    FILE_PATH_LITERAL("downloaded_file.zip");
+
+namespace download {
+namespace {
+
+TEST(EntryUtilsTest, MapEntriesToClients) {
+  Entry entry1 = test::BuildBasicEntry();
+  entry1.bytes_downloaded = 10u;
+  Entry entry2 = test::BuildBasicEntry(Entry::State::COMPLETE);
+  entry2.bytes_downloaded = 20u;
+  entry2.target_file_path = base::FilePath(kFilePath);
+
+  std::vector<Entry*> entries = {&entry1, &entry2};
+  auto metadata_map =
+      util::MapEntriesToMetadataForClients({DownloadClient::TEST}, entries);
+  EXPECT_EQ(1u, metadata_map.size());
+  EXPECT_EQ(2u, metadata_map[DownloadClient::TEST].size());
+  const DownloadMetaData& metadata1 = metadata_map[DownloadClient::TEST][0];
+  const DownloadMetaData& metadata2 = metadata_map[DownloadClient::TEST][1];
+  EXPECT_EQ(entry1.guid, metadata1.guid);
+  EXPECT_EQ(entry1.bytes_downloaded, metadata1.current_size);
+  EXPECT_FALSE(metadata1.completion_info.has_value());
+
+  EXPECT_EQ(entry2.guid, metadata2.guid);
+  EXPECT_EQ(entry2.bytes_downloaded, metadata2.current_size);
+  EXPECT_TRUE(metadata2.completion_info.has_value());
+  EXPECT_EQ(entry2.bytes_downloaded,
+            metadata2.completion_info.value().bytes_downloaded);
+  EXPECT_EQ(entry2.target_file_path, metadata2.completion_info.value().path);
+}
+
+}  // namespace
+}  // namespace download
diff --git a/components/download/internal/background_service/test/BUILD.gn b/components/download/internal/background_service/test/BUILD.gn
index 38b487a4..098f81a 100644
--- a/components/download/internal/background_service/test/BUILD.gn
+++ b/components/download/internal/background_service/test/BUILD.gn
@@ -13,6 +13,8 @@
   testonly = true
 
   sources = [
+    "entry_utils.cc",
+    "entry_utils.h",
     "test_store.cc",
     "test_store.h",
   ]
@@ -23,8 +25,6 @@
       "black_hole_log_sink.h",
       "download_params_utils.cc",
       "download_params_utils.h",
-      "entry_utils.cc",
-      "entry_utils.h",
       "mock_controller.cc",
       "mock_controller.h",
       "mock_download_driver_client.cc",
@@ -46,9 +46,7 @@
     "//testing/gmock",
   ]
 
-  if (!is_ios) {
-    public_deps += [ "//net:test_support" ]
-  }
+  public_deps += [ "//net:test_support" ]
 
   deps = [ "//components/download/internal/background_service:storage" ]
   if (!is_ios) {
diff --git a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
index 89bb5f58..e4a3608 100644
--- a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
+++ b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
@@ -775,7 +775,9 @@
 TEST_F(FeedApiTest, ShouldMakeFeedQueryRequestConsumesQuota) {
   LoadStreamStatus status = LoadStreamStatus::kNoStatus;
   for (; status == LoadStreamStatus::kNoStatus;
-       status = stream_->ShouldMakeFeedQueryRequest(kForYouStream)
+       status = stream_
+                    ->ShouldMakeFeedQueryRequest(kForYouStream,
+                                                 LoadType::kInitialLoad)
                     .load_stream_status) {
   }
 
@@ -2310,6 +2312,109 @@
   EXPECT_FALSE(on_clear_all.called());
 }
 
+TEST_F(FeedApiTest, ManualRefreshSuccess) {
+  response_translator_.InjectResponse(MakeTypicalInitialModelState());
+  TestForYouSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+  ASSERT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+
+  response_translator_.InjectResponse(MakeTypicalRefreshModelState());
+  CallbackReceiver<bool> callback;
+  stream_->ManualRefresh(surface, callback.Bind());
+  WaitForIdleTaskQueue();
+  EXPECT_EQ(absl::optional<bool>(true), callback.GetResult());
+  EXPECT_EQ("3 slices", surface.DescribeUpdates());
+  EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+            metrics_reporter_->load_stream_status);
+  // Verify stored state is equivalent to in-memory model.
+  EXPECT_STRINGS_EQUAL(
+      stream_->GetModel(surface.GetStreamType())->DumpStateForTesting(),
+      ModelStateFor(kForYouStream, store_.get()));
+}
+
+TEST_F(FeedApiTest, ManualRefreshFailsBecauseNetworkRequestFails) {
+  response_translator_.InjectResponse(MakeTypicalInitialModelState());
+  TestForYouSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+  ASSERT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+  EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+            metrics_reporter_->load_stream_status);
+  std::string original_store_dump =
+      ModelStateFor(surface.GetStreamType(), store_.get());
+  EXPECT_STRINGS_EQUAL(
+      stream_->GetModel(surface.GetStreamType())->DumpStateForTesting(),
+      original_store_dump);
+
+  // Since we didn't inject a network response, the network update will fail.
+  // The store should not be updated.
+  CallbackReceiver<bool> callback;
+  stream_->ManualRefresh(surface, callback.Bind());
+  WaitForIdleTaskQueue();
+  EXPECT_EQ(absl::optional<bool>(false), callback.GetResult());
+  EXPECT_EQ("cant-refresh", surface.DescribeUpdates());
+  EXPECT_EQ(LoadStreamStatus::kProtoTranslationFailed,
+            metrics_reporter_->load_stream_status);
+  EXPECT_STRINGS_EQUAL(ModelStateFor(surface.GetStreamType(), store_.get()),
+                       original_store_dump);
+}
+
+TEST_F(FeedApiTest, ManualRefreshSuccessAfterUnload) {
+  response_translator_.InjectResponse(MakeTypicalInitialModelState());
+  TestForYouSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+  ASSERT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+
+  UnloadModel(surface.GetStreamType());
+  WaitForIdleTaskQueue();
+
+  response_translator_.InjectResponse(MakeTypicalRefreshModelState());
+  CallbackReceiver<bool> callback;
+  stream_->ManualRefresh(surface, callback.Bind());
+  WaitForIdleTaskQueue();
+  EXPECT_EQ(absl::optional<bool>(true), callback.GetResult());
+  EXPECT_EQ("3 slices", surface.DescribeUpdates());
+  EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+            metrics_reporter_->load_stream_status);
+  // Verify stored state is equivalent to in-memory model.
+  EXPECT_STRINGS_EQUAL(
+      stream_->GetModel(surface.GetStreamType())->DumpStateForTesting(),
+      ModelStateFor(kForYouStream, store_.get()));
+}
+
+TEST_F(FeedApiTest, ManualRefreshSuccessAfterPreviousLoadFailure) {
+  TestForYouSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+  EXPECT_EQ("loading -> cant-refresh", surface.DescribeUpdates());
+
+  response_translator_.InjectResponse(MakeTypicalRefreshModelState());
+  CallbackReceiver<bool> callback;
+  stream_->ManualRefresh(surface, callback.Bind());
+  WaitForIdleTaskQueue();
+  EXPECT_EQ(absl::optional<bool>(true), callback.GetResult());
+  EXPECT_EQ("no-cards -> 3 slices", surface.DescribeUpdates());
+  EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+            metrics_reporter_->load_stream_status);
+  // Verify stored state is equivalent to in-memory model.
+  EXPECT_STRINGS_EQUAL(
+      stream_->GetModel(surface.GetStreamType())->DumpStateForTesting(),
+      ModelStateFor(kForYouStream, store_.get()));
+}
+
+TEST_F(FeedApiTest, ManualRefreshFailesWhenLoadingInProgress) {
+  response_translator_.InjectResponse(MakeTypicalInitialModelState());
+  TestForYouSurface surface(stream_.get());
+  // Don't call WaitForIdleTaskQueue to finish the loading.
+
+  response_translator_.InjectResponse(MakeTypicalRefreshModelState());
+  CallbackReceiver<bool> callback;
+  stream_->ManualRefresh(surface, callback.Bind());
+  WaitForIdleTaskQueue();
+  // Manual refresh should fail immediately when loading is still in progress.
+  EXPECT_EQ(absl::optional<bool>(false), callback.GetResult());
+  // The initial loading should finish.
+  EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+}
+
 // Keep instantiations at the bottom.
 INSTANTIATE_TEST_SUITE_P(FeedApiTest,
                          FeedStreamTestForAllStreamTypes,
diff --git a/components/feed/core/v2/api_test/feed_api_test.cc b/components/feed/core/v2/api_test/feed_api_test.cc
index 9ee5994..4f39915 100644
--- a/components/feed/core/v2/api_test/feed_api_test.cc
+++ b/components/feed/core/v2/api_test/feed_api_test.cc
@@ -677,6 +677,7 @@
     const StreamType& stream_type,
     LoadStreamStatus load_from_store_status,
     LoadStreamStatus final_status,
+    bool is_initial_load,
     bool loaded_new_content_from_network,
     base::TimeDelta stored_content_age,
     int content_count,
@@ -685,10 +686,10 @@
   load_stream_status = final_status;
   LOG(INFO) << "OnLoadStream: " << final_status
             << " (store status: " << load_from_store_status << ")";
-  MetricsReporter::OnLoadStream(stream_type, load_from_store_status,
-                                final_status, loaded_new_content_from_network,
-                                stored_content_age, content_count,
-                                std::move(latencies));
+  MetricsReporter::OnLoadStream(
+      stream_type, load_from_store_status, final_status, is_initial_load,
+      loaded_new_content_from_network, stored_content_age, content_count,
+      std::move(latencies));
 }
 void TestMetricsReporter::OnLoadMoreBegin(const StreamType& stream_type,
                                           SurfaceId surface_id) {
diff --git a/components/feed/core/v2/api_test/feed_api_test.h b/components/feed/core/v2/api_test/feed_api_test.h
index 874adff..140a3be4 100644
--- a/components/feed/core/v2/api_test/feed_api_test.h
+++ b/components/feed/core/v2/api_test/feed_api_test.h
@@ -381,6 +381,7 @@
   void OnLoadStream(const StreamType& stream_type,
                     LoadStreamStatus load_from_store_status,
                     LoadStreamStatus final_status,
+                    bool is_initial_load,
                     bool loaded_new_content_from_network,
                     base::TimeDelta stored_content_age,
                     int content_count,
diff --git a/components/feed/core/v2/enums.h b/components/feed/core/v2/enums.h
index cc37dc65..3541599 100644
--- a/components/feed/core/v2/enums.h
+++ b/components/feed/core/v2/enums.h
@@ -24,6 +24,22 @@
   kQueryNextPage = 10,
 };
 
+// Denotes how the stream content loading is used for.
+enum class LoadType {
+  // Loads the stream model into memory. If successful, this directly forces a
+  // model load in |FeedStream()| before completing the task.
+  kInitialLoad = 0,
+  // Loads additional content from the network when the model is already loaded.
+  kLoadMore = 1,
+  // Refreshes the stored stream data from the network, on the background. This
+  // will fail if the model is already loaded.
+  kBackgroundRefresh = 2,
+  // Refreshes the stored stream data from the network, per the user request.
+  // The stored stream data and the loaded model will not be affected if the
+  // network request fails.
+  kManualRefresh = 3,
+};
+
 // This must be kept in sync with FeedLoadStreamStatus in enums.xml.
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc
index 93e51fa..1be12c5 100644
--- a/components/feed/core/v2/feed_stream.cc
+++ b/components/feed/core/v2/feed_stream.cc
@@ -183,24 +183,24 @@
     return feedwire::DiscoverLaunchResult::CARDS_UNSPECIFIED;
 
   // If we should not load the stream, abort and send a zero-state update.
-  LaunchResult do_not_attempt_reason = ShouldAttemptLoad(stream_type);
+  LaunchResult do_not_attempt_reason =
+      ShouldAttemptLoad(stream_type, LoadType::kInitialLoad);
   if (do_not_attempt_reason.load_stream_status != LoadStreamStatus::kNoStatus) {
     LoadStreamTask::Result result(stream_type,
                                   do_not_attempt_reason.load_stream_status);
     result.launch_result = do_not_attempt_reason.launch_result;
-    InitialStreamLoadComplete(std::move(result));
+    StreamLoadComplete(std::move(result));
     return do_not_attempt_reason.launch_result;
   }
 
   stream.model_loading_in_progress = true;
 
-  stream.surface_updater->LoadStreamStarted();
+  stream.surface_updater->LoadStreamStarted(/*manual_refreshing=*/false);
   LoadStreamTask::Options options;
   options.stream_type = stream_type;
   task_queue_.AddTask(std::make_unique<LoadStreamTask>(
       options, this,
-      base::BindOnce(&FeedStream::InitialStreamLoadComplete,
-                     base::Unretained(this))));
+      base::BindOnce(&FeedStream::StreamLoadComplete, base::Unretained(this))));
   return feedwire::DiscoverLaunchResult::CARDS_UNSPECIFIED;
 }
 
@@ -231,8 +231,13 @@
   }
 }
 
-void FeedStream::InitialStreamLoadComplete(LoadStreamTask::Result result) {
+void FeedStream::StreamLoadComplete(LoadStreamTask::Result result) {
+  DCHECK(result.load_type == LoadType::kInitialLoad ||
+         result.load_type == LoadType::kManualRefresh);
+
   Stream& stream = GetStream(result.stream_type);
+  if (result.load_type == LoadType::kManualRefresh)
+    UnloadModel(result.stream_type);
   if (result.update_request) {
     auto model = std::make_unique<StreamModel>();
     model->Update(std::move(result.update_request));
@@ -256,6 +261,7 @@
   }
   metrics_reporter_->OnLoadStream(
       stream.type, result.load_from_store_status, result.final_status,
+      result.load_type == LoadType::kInitialLoad,
       result.loaded_new_content_from_network, result.stored_content_age,
       content_count, std::move(result.latencies));
 
@@ -272,7 +278,7 @@
     if (result.stream_type.IsForYou()) {
       if (!HasUnreadContent(kWebFeedStream)) {
         LoadStreamTask::Options options;
-        options.load_type = LoadStreamTask::LoadType::kBackgroundRefresh;
+        options.load_type = LoadType::kBackgroundRefresh;
         options.stream_type = kWebFeedStream;
         options.abort_if_unread_content = true;
         task_queue_.AddTask(std::make_unique<LoadStreamTask>(
@@ -282,14 +288,24 @@
       }
     }
   }
+
+  if (result.load_type == LoadType::kManualRefresh) {
+    std::vector<base::OnceCallback<void(bool)>> moved_callbacks =
+        std::move(stream.refresh_complete_callbacks);
+    for (auto& callback : moved_callbacks) {
+      std::move(callback).Run(result.loaded_new_content_from_network);
+    }
+  }
 }
 
 void FeedStream::OnEnterBackground() {
   metrics_reporter_->OnEnterBackground();
   if (GetFeedConfig().upload_actions_on_enter_background) {
     task_queue_.AddTask(std::make_unique<UploadActionsTask>(
-        this, base::BindOnce(&FeedStream::UploadActionsComplete,
-                             base::Unretained(this))));
+        this,
+        /*launch_reliability_logger=*/nullptr,
+        base::BindOnce(&FeedStream::UploadActionsComplete,
+                       base::Unretained(this))));
   }
 }
 
@@ -462,7 +478,7 @@
   }
   // We want to abort early to avoid showing a loading spinner if it's not
   // necessary.
-  if (ShouldMakeFeedQueryRequest(surface.GetStreamType(), /*is_load_more=*/true,
+  if (ShouldMakeFeedQueryRequest(surface.GetStreamType(), LoadType::kLoadMore,
                                  /*consume_quota=*/false)
           .load_stream_status != LoadStreamStatus::kNoStatus) {
     return std::move(callback).Run(false);
@@ -501,6 +517,31 @@
   }
 }
 
+void FeedStream::ManualRefresh(const FeedStreamSurface& surface,
+                               base::OnceCallback<void(bool)> callback) {
+  Stream& stream = GetStream(surface.GetStreamType());
+
+  // Bail out immediately if loading in progress.
+  if (stream.model_loading_in_progress) {
+    return std::move(callback).Run(false);
+  }
+  stream.model_loading_in_progress = true;
+
+  stream.surface_updater->LoadStreamStarted(/*manual_refreshing=*/true);
+
+  // Have at most one in-flight refresh request per stream.
+  stream.refresh_complete_callbacks.push_back(std::move(callback));
+  if (stream.refresh_complete_callbacks.size() == 1) {
+    LoadStreamTask::Options options;
+    options.stream_type = surface.GetStreamType();
+    options.load_type = LoadType::kManualRefresh;
+    task_queue_.AddTask(std::make_unique<LoadStreamTask>(
+        options, this,
+        base::BindOnce(&FeedStream::StreamLoadComplete,
+                       base::Unretained(this))));
+  }
+}
+
 void FeedStream::ExecuteOperations(
     const StreamType& stream_type,
     std::vector<feedstore::DataOperation> operations) {
@@ -509,6 +550,7 @@
     DLOG(ERROR) << "Calling ExecuteOperations before the model is loaded";
     return;
   }
+  // TODO(crbug.com/1227897): Convert this to a task.
   return model->ExecuteOperations(std::move(operations));
 }
 
@@ -699,16 +741,20 @@
 }
 
 LaunchResult FeedStream::ShouldAttemptLoad(const StreamType& stream_type,
+                                           LoadType load_type,
                                            bool model_loading) {
-  // Don't try to load the model if it's already loaded, or in the process of
-  // being loaded. Because |ShouldAttemptLoad()| is used both before and during
-  // the load process, we need to ignore this check when |model_loading| is
-  // true.
   Stream& stream = GetStream(stream_type);
-  if (stream.model || (!model_loading && stream.model_loading_in_progress)) {
-    // TODO(iwells): log the end of the launch flow if stream.model exists
-    return {LoadStreamStatus::kModelAlreadyLoaded,
-            feedwire::DiscoverLaunchResult::CARDS_UNSPECIFIED};
+  if (load_type == LoadType::kInitialLoad ||
+      load_type == LoadType::kBackgroundRefresh) {
+    // For initial load or background refresh, the model should not be loaded
+    // or in the process of being loaded. Because |ShouldAttemptLoad()| is used
+    // both before and during the load process, we need to ignore this check
+    // when |model_loading| is true.
+    if (stream.model || (!model_loading && stream.model_loading_in_progress)) {
+      // TODO(iwells): log the end of the launch flow if stream.model exists
+      return {LoadStreamStatus::kModelAlreadyLoaded,
+              feedwire::DiscoverLaunchResult::CARDS_UNSPECIFIED};
+    }
   }
 
   if (!IsArticlesListVisible()) {
@@ -755,24 +801,24 @@
 
 LaunchResult FeedStream::ShouldMakeFeedQueryRequest(
     const StreamType& stream_type,
-    bool is_load_more,
+    LoadType load_type,
     bool consume_quota) {
   Stream& stream = GetStream(stream_type);
-  if (!is_load_more) {
-    // Time has passed since calling |ShouldAttemptLoad()|, call it again to
-    // confirm we should still attempt loading.
-    const LaunchResult should_not_attempt_reason =
-        ShouldAttemptLoad(stream_type, /*model_loading=*/true);
-    if (should_not_attempt_reason.load_stream_status !=
-        LoadStreamStatus::kNoStatus) {
-      return should_not_attempt_reason;
-    }
-  } else {
+  if (load_type == LoadType::kLoadMore) {
     // LoadMore requires a next page token.
     if (!stream.model || stream.model->GetNextPageToken().empty()) {
       return {LoadStreamStatus::kCannotLoadMoreNoNextPageToken,
               feedwire::DiscoverLaunchResult::CARDS_UNSPECIFIED};
     }
+  } else if (load_type != LoadType::kManualRefresh) {
+    // Time has passed since calling |ShouldAttemptLoad()|, call it again to
+    // confirm we should still attempt loading.
+    const LaunchResult should_not_attempt_reason =
+        ShouldAttemptLoad(stream_type, load_type, /*model_loading=*/true);
+    if (should_not_attempt_reason.load_stream_status !=
+        LoadStreamStatus::kNoStatus) {
+      return should_not_attempt_reason;
+    }
   }
 
   if (delegate_->IsOffline()) {
@@ -780,9 +826,10 @@
             feedwire::DiscoverLaunchResult::NO_CARDS_REQUEST_ERROR_NO_INTERNET};
   }
 
-  if (consume_quota && !request_throttler_.RequestQuota(
-                           !is_load_more ? NetworkRequestType::kFeedQuery
-                                         : NetworkRequestType::kNextPage)) {
+  if (consume_quota &&
+      !request_throttler_.RequestQuota((load_type != LoadType::kLoadMore)
+                                           ? NetworkRequestType::kFeedQuery
+                                           : NetworkRequestType::kNextPage)) {
     return {LoadStreamStatus::kCannotLoadFromNetworkThrottled,
             feedwire::DiscoverLaunchResult::NO_CARDS_REQUEST_ERROR_OTHER};
   }
@@ -885,7 +932,8 @@
 void FeedStream::ExecuteRefreshTask(RefreshTaskId task_id) {
   StreamType stream_type = StreamType::ForTaskId(task_id);
   LoadStreamStatus do_not_attempt_reason =
-      ShouldAttemptLoad(stream_type).load_stream_status;
+      ShouldAttemptLoad(stream_type, LoadType::kBackgroundRefresh)
+          .load_stream_status;
 
   // If `do_not_attempt_reason` indicates the stream shouldn't be loaded, it's
   // unlikely that criteria will change, so we skip rescheduling.
@@ -905,7 +953,7 @@
 
   LoadStreamTask::Options options;
   options.stream_type = stream_type;
-  options.load_type = LoadStreamTask::LoadType::kBackgroundRefresh;
+  options.load_type = LoadType::kBackgroundRefresh;
   options.refresh_even_when_not_stale = true;
   task_queue_.AddTask(std::make_unique<LoadStreamTask>(
       options, this,
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h
index 23e7db55..1e23cc2a 100644
--- a/components/feed/core/v2/feed_stream.h
+++ b/components/feed/core/v2/feed_stream.h
@@ -110,6 +110,8 @@
   PersistentKeyValueStoreImpl& GetPersistentKeyValueStore() override;
   void LoadMore(const FeedStreamSurface& surface,
                 base::OnceCallback<void(bool)> callback) override;
+  void ManualRefresh(const FeedStreamSurface& surface,
+                     base::OnceCallback<void(bool)> callback) override;
   void ExecuteOperations(
       const StreamType& stream_type,
       std::vector<feedstore::DataOperation> operations) override;
@@ -209,6 +211,7 @@
   // Determines if we should attempt loading the stream or refreshing at all.
   // Returns |LoadStreamStatus::kNoStatus| if loading may be attempted.
   LaunchResult ShouldAttemptLoad(const StreamType& stream_type,
+                                 LoadType load_type,
                                  bool model_loading = false);
 
   // Whether the last scheduled refresh was missed.
@@ -220,7 +223,7 @@
   // consumed. This can be used to predict the likely result on a subsequent
   // call.
   LaunchResult ShouldMakeFeedQueryRequest(const StreamType& stream_type,
-                                          bool is_load_more = false,
+                                          LoadType load_type,
                                           bool consume_quota = true);
 
   // Returns true if a FeedQuery request made right now should be made without
@@ -306,6 +309,7 @@
     ContentIdSet content_ids;
     std::vector<UnreadContentNotifier> unread_content_notifiers;
     std::vector<base::OnceCallback<void(bool)>> load_more_complete_callbacks;
+    std::vector<base::OnceCallback<void(bool)>> refresh_complete_callbacks;
     bool is_activity_logging_enabled = false;
   };
 
@@ -328,7 +332,7 @@
                                               int sequence_number);
   void UnloadModelIfNoSurfacesAttachedTask(const StreamType& stream_type);
 
-  void InitialStreamLoadComplete(LoadStreamTask::Result result);
+  void StreamLoadComplete(LoadStreamTask::Result result);
   void LoadMoreComplete(LoadMoreTask::Result result);
   void BackgroundRefreshComplete(LoadStreamTask::Result result);
   void LoadTaskComplete(const LoadStreamTask::Result& result);
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc
index 0f3b01f..adecfb8 100644
--- a/components/feed/core/v2/metrics_reporter.cc
+++ b/components/feed/core/v2/metrics_reporter.cc
@@ -543,6 +543,7 @@
     const StreamType& stream_type,
     LoadStreamStatus load_from_store_status,
     LoadStreamStatus final_status,
+    bool is_initial_load,
     bool loaded_new_content_from_network,
     base::TimeDelta stored_content_age,
     int content_count,
@@ -551,10 +552,14 @@
            << " final_status=" << final_status;
   load_latencies_ = std::move(load_latencies);
 
+  std::string load_type_name = is_initial_load ? "Initial" : "ManualRefresh";
   base::UmaHistogramEnumeration(
       base::StrCat({"ContentSuggestions.", HistogramReplacement(stream_type),
-                    "LoadStreamStatus.Initial"}),
+                    "LoadStreamStatus.", load_type_name}),
       final_status);
+  if (!is_initial_load)
+    return;
+
   if (load_from_store_status != LoadStreamStatus::kNoStatus) {
     base::UmaHistogramEnumeration(
         base::StrCat({"ContentSuggestions.", HistogramReplacement(stream_type),
diff --git a/components/feed/core/v2/metrics_reporter.h b/components/feed/core/v2/metrics_reporter.h
index 955a707..98ea422 100644
--- a/components/feed/core/v2/metrics_reporter.h
+++ b/components/feed/core/v2/metrics_reporter.h
@@ -67,6 +67,7 @@
   virtual void OnLoadStream(const StreamType& stream_type,
                             LoadStreamStatus load_from_store_status,
                             LoadStreamStatus final_status,
+                            bool is_initial_load,
                             bool loaded_new_content_from_network,
                             base::TimeDelta stored_content_age,
                             int content_count,
diff --git a/components/feed/core/v2/metrics_reporter_unittest.cc b/components/feed/core/v2/metrics_reporter_unittest.cc
index dc055ca..4148c90 100644
--- a/components/feed/core/v2/metrics_reporter_unittest.cc
+++ b/components/feed/core/v2/metrics_reporter_unittest.cc
@@ -186,6 +186,7 @@
 TEST_F(MetricsReporterTest, ReportsLoadStreamStatus) {
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kLoadedFromNetwork,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/true,
                           /*stored_content_age=*/base::TimeDelta::FromDays(5),
                           /*content_count=*/12,
@@ -204,6 +205,7 @@
 TEST_F(MetricsReporterTest, WebFeed_ReportsLoadStreamStatus) {
   reporter_->OnLoadStream(kWebFeedStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kLoadedFromNetwork,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/true,
                           /*stored_content_age=*/base::TimeDelta::FromDays(5),
                           /*content_count=*/12,
@@ -222,6 +224,7 @@
 TEST_F(MetricsReporterTest, OnLoadStreamDoesNotReportLoadedCardCountOnFailure) {
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kDataInStoreIsExpired,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/false,
                           /*stored_content_age=*/base::TimeDelta::FromDays(5),
                           /*content_count=*/12,
@@ -230,9 +233,30 @@
   histogram_.ExpectTotalCount("ContentSuggestions.Feed.LoadedCardCount", 0);
 }
 
+TEST_F(MetricsReporterTest, ReportsLoadStreamStatusForManualRefresh) {
+  reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
+                          LoadStreamStatus::kLoadedFromNetwork,
+                          /*is_initial_load=*/false,
+                          /*loaded_new_content_from_network=*/true,
+                          /*stored_content_age=*/base::TimeDelta::FromDays(5),
+                          /*content_count=*/12,
+                          std::make_unique<LoadLatencyTimes>());
+
+  histogram_.ExpectUniqueSample(
+      "ContentSuggestions.Feed.LoadStreamStatus.Initial",
+      LoadStreamStatus::kLoadedFromNetwork, 0);
+  histogram_.ExpectUniqueSample(
+      "ContentSuggestions.Feed.LoadStreamStatus.InitialFromStore",
+      LoadStreamStatus::kDataInStoreIsStale, 0);
+  histogram_.ExpectUniqueSample(
+      "ContentSuggestions.Feed.LoadStreamStatus.ManualRefresh",
+      LoadStreamStatus::kLoadedFromNetwork, 1);
+}
+
 TEST_F(MetricsReporterTest, ReportsLoadStreamStatusIgnoresNoStatusFromStore) {
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kNoStatus,
                           LoadStreamStatus::kLoadedFromNetwork,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/true,
                           /*stored_content_age=*/base::TimeDelta(),
                           /*content_count=*/12,
@@ -243,11 +267,15 @@
       LoadStreamStatus::kLoadedFromNetwork, 1);
   histogram_.ExpectTotalCount(
       "ContentSuggestions.Feed.LoadStreamStatus.InitialFromStore", 0);
+  histogram_.ExpectUniqueSample(
+      "ContentSuggestions.Feed.LoadStreamStatus.UserRefresh",
+      LoadStreamStatus::kLoadedFromNetwork, 0);
 }
 
 TEST_F(MetricsReporterTest, ReportsContentAgeBlockingRefresh) {
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kLoadedFromNetwork,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/true,
                           /*stored_content_age=*/base::TimeDelta::FromDays(5),
                           /*content_count=*/12,
@@ -261,6 +289,7 @@
 TEST_F(MetricsReporterTest, ReportsContentAgeNoRefresh) {
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kLoadedFromStore,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/false,
                           /*stored_content_age=*/base::TimeDelta::FromDays(5),
                           /*content_count=*/12,
@@ -274,12 +303,13 @@
 TEST_F(MetricsReporterTest, DoNotReportContentAgeWhenNotPositive) {
   reporter_->OnLoadStream(
       kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
-      LoadStreamStatus::kLoadedFromStore,
+      LoadStreamStatus::kLoadedFromStore, /*is_initial_load=*/true,
       /*loaded_new_content_from_network=*/false,
       /*stored_content_age=*/-base::TimeDelta::FromSeconds(1),
       /*content_count=*/12, std::make_unique<LoadLatencyTimes>());
   reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kDataInStoreIsStale,
                           LoadStreamStatus::kLoadedFromStore,
+                          /*is_initial_load=*/true,
                           /*loaded_new_content_from_network=*/false,
                           /*stored_content_age=*/base::TimeDelta(),
                           /*content_count=*/12,
@@ -299,6 +329,7 @@
     latencies->StepComplete(LoadLatencyTimes::kUploadActions);
     reporter_->OnLoadStream(kForYouStream, LoadStreamStatus::kNoStatus,
                             LoadStreamStatus::kLoadedFromNetwork,
+                            /*is_initial_load=*/true,
                             /*loaded_new_content_from_network=*/true,
                             /*stored_content_age=*/base::TimeDelta(),
                             /*content_count=*/12, std::move(latencies));
diff --git a/components/feed/core/v2/public/feed_api.h b/components/feed/core/v2/public/feed_api.h
index 0a153d4..26e73db 100644
--- a/components/feed/core/v2/public/feed_api.h
+++ b/components/feed/core/v2/public/feed_api.h
@@ -82,6 +82,11 @@
   virtual void LoadMore(const FeedStreamSurface& surface,
                         base::OnceCallback<void(bool)> callback) = 0;
 
+  // Refresh the feed content by fetching the fresh content from the server.
+  // Calls |callback| when complete. If the fetch fails, the parameter is false.
+  virtual void ManualRefresh(const FeedStreamSurface& surface,
+                             base::OnceCallback<void(bool)> callback) = 0;
+
   // Request to fetch and image for use in the feed. Calls |callback|
   // with the network response when complete. The returned ImageFetchId can be
   // passed to CancelImageFetch() to cancel the request.
diff --git a/components/feed/core/v2/public/test/stub_feed_api.h b/components/feed/core/v2/public/test/stub_feed_api.h
index f29e4d1..24663a8 100644
--- a/components/feed/core/v2/public/test/stub_feed_api.h
+++ b/components/feed/core/v2/public/test/stub_feed_api.h
@@ -43,6 +43,8 @@
   void ExecuteRefreshTask(RefreshTaskId task_id) override {}
   void LoadMore(const FeedStreamSurface& surface,
                 base::OnceCallback<void(bool)> callback) override {}
+  void ManualRefresh(const FeedStreamSurface& surface,
+                     base::OnceCallback<void(bool)> callback) override {}
   ImageFetchId FetchImage(
       const GURL& url,
       base::OnceCallback<void(NetworkResponse)> callback) override;
diff --git a/components/feed/core/v2/surface_updater.cc b/components/feed/core/v2/surface_updater.cc
index b739862..48f0856 100644
--- a/components/feed/core/v2/surface_updater.cc
+++ b/components/feed/core/v2/surface_updater.cc
@@ -261,9 +261,9 @@
   surfaces_.RemoveObserver(surface);
 }
 
-void SurfaceUpdater::LoadStreamStarted() {
+void SurfaceUpdater::LoadStreamStarted(bool manual_refreshing) {
   load_stream_failed_ = false;
-  loading_initial_ = true;
+  loading_initial_ = !manual_refreshing;
   load_stream_started_ = true;
   SendStreamUpdateIfNeeded();
 }
diff --git a/components/feed/core/v2/surface_updater.h b/components/feed/core/v2/surface_updater.h
index 7e24cd5..7c3aab9 100644
--- a/components/feed/core/v2/surface_updater.h
+++ b/components/feed/core/v2/surface_updater.h
@@ -49,7 +49,7 @@
                     feedwire::DiscoverLaunchResult loading_not_allowed_reason);
   void SurfaceRemoved(FeedStreamSurface* surface);
   // Called to indicate the initial model load is in progress.
-  void LoadStreamStarted();
+  void LoadStreamStarted(bool manual_refreshing);
   void LoadStreamComplete(bool success,
                           LoadStreamStatus load_stream_status,
                           feedwire::DiscoverLaunchResult launch_result);
diff --git a/components/feed/core/v2/tasks/load_more_task.cc b/components/feed/core/v2/tasks/load_more_task.cc
index f805fc5..e34d552 100644
--- a/components/feed/core/v2/tasks/load_more_task.cc
+++ b/components/feed/core/v2/tasks/load_more_task.cc
@@ -52,13 +52,14 @@
     return Done(LoadStreamStatus::kLoadMoreModelIsNotLoaded);
 
   LoadStreamStatus final_status =
-      stream_.ShouldMakeFeedQueryRequest(stream_type_, /*is_load_more=*/true)
+      stream_.ShouldMakeFeedQueryRequest(stream_type_, LoadType::kLoadMore)
           .load_stream_status;
   if (final_status != LoadStreamStatus::kNoStatus)
     return Done(final_status);
 
   upload_actions_task_ = std::make_unique<UploadActionsTask>(
       &stream_,
+      /*launch_reliability_logger=*/nullptr,
       base::BindOnce(&LoadMoreTask::UploadActionsComplete, GetWeakPtr()));
   upload_actions_task_->Execute(base::DoNothing());
 }
diff --git a/components/feed/core/v2/tasks/load_stream_task.cc b/components/feed/core/v2/tasks/load_stream_task.cc
index 3352fb97..e37a1fb 100644
--- a/components/feed/core/v2/tasks/load_stream_task.cc
+++ b/components/feed/core/v2/tasks/load_stream_task.cc
@@ -32,7 +32,6 @@
 
 namespace feed {
 namespace {
-using LoadType = LoadStreamTask::LoadType;
 using Result = LoadStreamTask::Result;
 
 feedwire::FeedQuery::RequestReason GetRequestReason(
@@ -40,6 +39,7 @@
     LoadType load_type) {
   switch (load_type) {
     case LoadType::kInitialLoad:
+    case LoadType::kManualRefresh:
       return stream_type.IsForYou() ? feedwire::FeedQuery::MANUAL_REFRESH
                                     : feedwire::FeedQuery::INTERACTIVE_WEB_FEED;
     case LoadType::kBackgroundRefresh:
@@ -48,6 +48,9 @@
                  // TODO(b/185848601): Switch back to PREFETCHED_WEB_FEED when
                  // the server supports it.
                  : feedwire::FeedQuery::INTERACTIVE_WEB_FEED;
+    case LoadType::kLoadMore:
+      NOTREACHED();
+      return feedwire::FeedQuery::MANUAL_REFRESH;
   }
 }
 
@@ -69,6 +72,7 @@
       launch_reliability_logger_(
           stream_.GetLaunchReliabilityLogger(options.stream_type)) {
   DCHECK(options.stream_type.IsValid()) << "A stream type must be chosen";
+  DCHECK(options.load_type != LoadType::kLoadMore);
   latencies_ = std::make_unique<LoadLatencyTimes>();
 }
 
@@ -105,7 +109,7 @@
 
   // First, ensure we still should load the model.
   LaunchResult should_not_attempt_reason =
-      stream_.ShouldAttemptLoad(options_.stream_type,
+      stream_.ShouldAttemptLoad(options_.stream_type, options_.load_type,
                                 /*model_loading=*/true);
   if (should_not_attempt_reason.load_stream_status !=
       LoadStreamStatus::kNoStatus) {
@@ -144,6 +148,14 @@
 
 void LoadStreamTask::PassedPreconditions() {
   launch_reliability_logger_.LogCacheReadStart();
+
+  if (options_.load_type == LoadType::kManualRefresh) {
+    std::vector<feedstore::StoredAction> empty_pending_actions;
+    LoadFromNetwork(std::move(empty_pending_actions),
+                    /*need_to_read_pending_actions=*/true);
+    return;
+  }
+
   // Use |kLoadNoContent| to short-circuit loading from store if we don't
   // need the full stream state.
   auto load_from_store_type =
@@ -185,15 +197,34 @@
     stale_store_state_ = std::move(result.update_request);
   }
 
-  LaunchResult should_make_request =
-      stream_.ShouldMakeFeedQueryRequest(options_.stream_type);
+  LoadFromNetwork(std::move(result.pending_actions),
+                  /*need_to_read_pending_actions=*/false);
+}
+
+void LoadStreamTask::LoadFromNetwork(
+    std::vector<feedstore::StoredAction> pending_actions_from_store,
+    bool need_to_read_pending_actions) {
+  // Don't consume quota if refreshed by user.
+  LaunchResult should_make_request = stream_.ShouldMakeFeedQueryRequest(
+      options_.stream_type, options_.load_type,
+      /*consume_quota=*/options_.load_type != LoadType::kManualRefresh);
   if (should_make_request.load_stream_status != LoadStreamStatus::kNoStatus)
     return Done(should_make_request);
 
   // If making a request, first try to upload pending actions.
-  upload_actions_task_ = std::make_unique<UploadActionsTask>(
-      std::move(result.pending_actions), &stream_, &launch_reliability_logger_,
-      base::BindOnce(&LoadStreamTask::UploadActionsComplete, GetWeakPtr()));
+  if (!need_to_read_pending_actions) {
+    // If pending actions are read from the store, pass them for uploading.
+    upload_actions_task_ = std::make_unique<UploadActionsTask>(
+        std::move(pending_actions_from_store), &stream_,
+        &launch_reliability_logger_,
+        base::BindOnce(&LoadStreamTask::UploadActionsComplete, GetWeakPtr()));
+  } else {
+    // Otherwise, no pending action can't be passed. We will read them from
+    // the store and upload them.
+    upload_actions_task_ = std::make_unique<UploadActionsTask>(
+        &stream_, &launch_reliability_logger_,
+        base::BindOnce(&LoadStreamTask::UploadActionsComplete, GetWeakPtr()));
+  }
   upload_actions_task_->Execute(base::DoNothing());
 }
 
@@ -231,6 +262,7 @@
     // Query*FeedDiscoverApi.
     switch (options_.load_type) {
       case LoadType::kInitialLoad:
+      case LoadType::kManualRefresh:
         network.SendApiRequest<QueryInteractiveFeedDiscoverApi>(
             request, gaia,
             base::BindOnce(&LoadStreamTask::QueryApiRequestComplete,
@@ -242,6 +274,9 @@
             base::BindOnce(&LoadStreamTask::QueryApiRequestComplete,
                            GetWeakPtr()));
         break;
+      case LoadType::kLoadMore:
+        NOTREACHED();
+        break;
     }
   } else {
     // Other requests use GWS.
@@ -270,8 +305,6 @@
   launch_reliability_logger_.LogRequestSent(
       network_request_id_, response_info.loader_start_time_ticks);
 
-  DCHECK(!stream_.GetModel(options_.stream_type));
-
   network_response_info_ = response_info;
 
   if (response_info.status_code != 200) {
diff --git a/components/feed/core/v2/tasks/load_stream_task.h b/components/feed/core/v2/tasks/load_stream_task.h
index 5e4a875..162444f 100644
--- a/components/feed/core/v2/tasks/load_stream_task.h
+++ b/components/feed/core/v2/tasks/load_stream_task.h
@@ -32,18 +32,9 @@
 // Loads the stream model from storage or network. If data is refreshed from the
 // network, it is persisted to |FeedStore| by overwriting any existing stream
 // data.
-// This task has two modes, see |LoadStreamTask::LoadType|.
+// This task has three modes, see |LoadType| in enums.h.
 class LoadStreamTask : public offline_pages::Task {
  public:
-  enum class LoadType {
-    // Loads the stream model into memory. If successful, this directly forces a
-    // model load in |FeedStream()| before completing the task.
-    kInitialLoad,
-    // Refreshes the stored stream data from the network. This will fail if the
-    // model is already loaded.
-    kBackgroundRefresh,
-  };
-
   struct Options {
     // The stream type to load.
     StreamType stream_type;
@@ -69,7 +60,7 @@
     base::TimeDelta stored_content_age;
     // Set of content IDs present in the feed.
     ContentIdSet content_ids;
-    LoadType load_type;
+    LoadType load_type = LoadType::kInitialLoad;
     std::unique_ptr<StreamModelUpdateRequest> update_request;
     absl::optional<RequestSchedule> request_schedule;
 
@@ -106,6 +97,10 @@
   void ResumeAtStart();
   bool CheckPreconditions();
   void PassedPreconditions();
+
+  void LoadFromNetwork(
+      std::vector<feedstore::StoredAction> pending_actions_from_store,
+      bool need_to_read_pending_actions);
   void LoadFromStoreComplete(LoadStreamFromStoreTask::Result result);
   void UploadActionsComplete(UploadActionsTask::Result result);
   void QueryApiRequestComplete(
diff --git a/components/feed/core/v2/tasks/upload_actions_task.cc b/components/feed/core/v2/tasks/upload_actions_task.cc
index 6f963a7..9ef0447d 100644
--- a/components/feed/core/v2/tasks/upload_actions_task.cc
+++ b/components/feed/core/v2/tasks/upload_actions_task.cc
@@ -137,10 +137,12 @@
 
 UploadActionsTask::UploadActionsTask(
     FeedStream* stream,
+    LaunchReliabilityLogger* launch_reliability_logger,
     base::OnceCallback<void(UploadActionsTask::Result)> callback)
     : stream_(*stream),
       read_pending_actions_(true),
-      callback_(std::move(callback)) {
+      callback_(std::move(callback)),
+      launch_reliability_logger_(launch_reliability_logger) {
   gaia_ = stream_.GetSyncSignedInGaia();
 }
 
diff --git a/components/feed/core/v2/tasks/upload_actions_task.h b/components/feed/core/v2/tasks/upload_actions_task.h
index eae0688..3c6f78d 100644
--- a/components/feed/core/v2/tasks/upload_actions_task.h
+++ b/components/feed/core/v2/tasks/upload_actions_task.h
@@ -71,6 +71,7 @@
   // Same as above, but reads pending actions and consistency token from the
   // store and uploads those.
   UploadActionsTask(FeedStream* stream,
+                    LaunchReliabilityLogger* launch_reliability_logger,
                     base::OnceCallback<void(Result)> callback);
 
   ~UploadActionsTask() override;
diff --git a/components/feed/core/v2/test/stream_builder.cc b/components/feed/core/v2/test/stream_builder.cc
index feccf87..f40e151 100644
--- a/components/feed/core/v2/test/stream_builder.cc
+++ b/components/feed/core/v2/test/stream_builder.cc
@@ -198,42 +198,45 @@
     default;
 
 std::unique_ptr<StreamModelUpdateRequest>
-StreamModelUpdateRequestGenerator::MakeFirstPage(int first_cluster_id) const {
+StreamModelUpdateRequestGenerator::MakeFirstPage(int first_cluster_id,
+                                                 int num_cards) const {
   bool include_notice_card =
       (privacy_notice_fulfilled && first_cluster_id == 0);
 
   auto initial_update = std::make_unique<StreamModelUpdateRequest>();
-  const int i = first_cluster_id;
-  const int j = first_cluster_id + 1;
   initial_update->source =
       StreamModelUpdateRequest::Source::kInitialLoadFromStore;
-  initial_update->content.push_back(
-      include_notice_card ? MakeNoticeCardContent(i) : MakeContent(i));
-  initial_update->content.push_back(MakeContent(j));
+  initial_update->stream_structures = {MakeClearAll(), MakeStream()};
 
-  initial_update->stream_structures = {
-      MakeClearAll(),
-      MakeStream(),
-      include_notice_card ? MakeNoticeCardCluster(i, MakeRootId())
-                          : MakeCluster(i, MakeRootId()),
-      include_notice_card ? MakeNoticeCardContentNode(i, MakeClusterId(i))
-                          : MakeContentNode(i, MakeClusterId(i)),
-      MakeCluster(j, MakeRootId()),
-      MakeContentNode(j, MakeClusterId(j))};
+  for (int i = first_cluster_id; i < first_cluster_id + num_cards; ++i) {
+    if (include_notice_card && i == first_cluster_id) {
+      initial_update->content.push_back(MakeNoticeCardContent(i));
+      initial_update->stream_structures.push_back(
+          MakeNoticeCardCluster(i, MakeRootId()));
+      initial_update->stream_structures.push_back(
+          MakeNoticeCardContentNode(i, MakeClusterId(i)));
+    } else {
+      initial_update->content.push_back(MakeContent(i));
+      initial_update->stream_structures.push_back(MakeCluster(i, MakeRootId()));
+      initial_update->stream_structures.push_back(
+          MakeContentNode(i, MakeClusterId(i)));
+    }
+  }
 
-  initial_update->shared_states.push_back(MakeSharedState(i));
+  initial_update->shared_states.push_back(MakeSharedState(first_cluster_id));
   *initial_update->stream_data.mutable_content_id() = MakeRootId();
-  *initial_update->stream_data.add_shared_state_ids() = MakeSharedStateId(i);
+  *initial_update->stream_data.add_shared_state_ids() =
+      MakeSharedStateId(first_cluster_id);
   initial_update->stream_data.set_next_page_token("page-2");
   initial_update->stream_data.set_signed_in(signed_in);
   initial_update->stream_data.set_logging_enabled(logging_enabled);
   initial_update->stream_data.set_privacy_notice_fulfilled(
       privacy_notice_fulfilled);
 
-  initial_update->stream_data.add_content_ids(
-      initial_update->content[0].content_id().id());
-  initial_update->stream_data.add_content_ids(
-      initial_update->content[1].content_id().id());
+  for (int i = 0; i < num_cards; ++i) {
+    initial_update->stream_data.add_content_ids(
+        initial_update->content[i].content_id().id());
+  }
   feedstore::SetLastAddedTime(last_added_time, initial_update->stream_data);
 
   return initial_update;
@@ -287,6 +290,19 @@
   return generator.MakeFirstPage(first_cluster_id);
 }
 
+std::unique_ptr<StreamModelUpdateRequest> MakeTypicalRefreshModelState(
+    int first_cluster_id,
+    base::Time last_added_time,
+    bool signed_in,
+    bool logging_enabled) {
+  StreamModelUpdateRequestGenerator generator;
+  generator.last_added_time = last_added_time;
+  generator.signed_in = signed_in;
+  generator.logging_enabled = logging_enabled;
+  generator.privacy_notice_fulfilled = false;
+  return generator.MakeFirstPage(first_cluster_id, /*num_cards=*/3);
+}
+
 std::unique_ptr<StreamModelUpdateRequest> MakeTypicalNextPageState(
     int page_number,
     base::Time last_added_time,
diff --git a/components/feed/core/v2/test/stream_builder.h b/components/feed/core/v2/test/stream_builder.h
index f1f3b49..651bde8 100644
--- a/components/feed/core/v2/test/stream_builder.h
+++ b/components/feed/core/v2/test/stream_builder.h
@@ -65,7 +65,8 @@
   ~StreamModelUpdateRequestGenerator();
 
   std::unique_ptr<StreamModelUpdateRequest> MakeFirstPage(
-      int first_cluster_id = 0) const;
+      int first_cluster_id = 0,
+      int num_cards = 2) const;
 
   std::unique_ptr<StreamModelUpdateRequest> MakeNextPage(
       int page_number = 2,
@@ -86,6 +87,19 @@
     bool signed_in = true,
     bool logging_enabled = true,
     bool privacy_notice_fulfilled = false);
+// Returns data operations to create a typical stream for refreshing:
+// Root
+// |-Cluster 2
+// |  |-Content 2
+// |-Cluster 3
+// |  |-Content 3
+// |-Cluster 4
+//    |-Content 4
+std::unique_ptr<StreamModelUpdateRequest> MakeTypicalRefreshModelState(
+    int first_cluster_id = 2,
+    base::Time last_added_time = kTestTimeEpoch,
+    bool signed_in = true,
+    bool logging_enabled = true);
 // Root
 // |-Cluster 2
 // |  |-Content 2
diff --git a/components/feedback/feedback_uploader.cc b/components/feedback/feedback_uploader.cc
index 9b2b5ff4..2ee47ef 100644
--- a/components/feedback/feedback_uploader.cc
+++ b/components/feedback/feedback_uploader.cc
@@ -177,7 +177,7 @@
           data:
             "The free-form text that user has entered and useful debugging "
             "logs (UI logs, Chrome logs, kernel logs, auto update engine logs, "
-            "ARC++ logs, etc.). The logs are anonymized to remove any "
+            "ARC++ logs, etc.). The logs are redacted to remove any "
             "user-private data. The user can view the system information "
             "before sending, and choose to send the feedback report without "
             "system information and the logs (unchecking 'Send system "
@@ -190,7 +190,11 @@
           setting:
             "This feature cannot be disabled by settings and is only activated "
             "by direct user request."
-          policy_exception_justification: "Not implemented."
+          chrome_policy {
+            UserFeedbackAllowed {
+              UserFeedbackAllowed: false
+            }
+          }
         })");
   auto resource_request = std::make_unique<network::ResourceRequest>();
   resource_request->url = feedback_post_url_;
diff --git a/components/handoff/handoff_manager.h b/components/handoff/handoff_manager.h
index 5457e67..7bf06d3 100644
--- a/components/handoff/handoff_manager.h
+++ b/components/handoff/handoff_manager.h
@@ -33,11 +33,19 @@
 // method is idempotent.
 - (void)updateActiveURL:(const GURL&)url;
 
+// The active title is defined as the title of the most recently accessed tab.
+// This method should be called any time the active title might have changed.
+// This method is idempotent.
+// -updateActiveURL: should be called prior since the URL identifier is
+// required while the title is optional.
+- (void)updateActiveTitle:(const std::u16string&)title;
+
 @end
 
 #if defined(OS_IOS)
 @interface HandoffManager (TestingOnly)
 - (NSURL*)userActivityWebpageURL;
+- (NSString*)userActivityTitle;
 @end
 #endif
 
diff --git a/components/handoff/handoff_manager.mm b/components/handoff/handoff_manager.mm
index 88376f3..9be5a95 100644
--- a/components/handoff/handoff_manager.mm
+++ b/components/handoff/handoff_manager.mm
@@ -8,6 +8,7 @@
 #include "base/mac/objc_release_properties.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/notreached.h"
+#include "base/strings/sys_string_conversions.h"
 #include "net/base/mac/url_conversions.h"
 
 #if defined(OS_IOS)
@@ -72,6 +73,13 @@
   [self updateUserActivity];
 }
 
+- (void)updateActiveTitle:(const std::u16string&)title {
+  // Assume the activity has already been created since the page navigation
+  // will complete before the page title loads. No need to re-create it, just
+  // set the title. If the activity has not been created, ignore the update.
+  self.userActivity.title = base::SysUTF16ToNSString(title);
+}
+
 - (BOOL)shouldUseActiveURL {
   return _activeURL.SchemeIsHTTPOrHTTPS();
 }
@@ -111,5 +119,9 @@
   return self.userActivity.webpageURL;
 }
 
+- (NSString*)userActivityTitle {
+  return self.userActivity.title;
+}
+
 @end
 #endif
diff --git a/components/history/core/browser/browsing_history_service.cc b/components/history/core/browser/browsing_history_service.cc
index db8552f..55b7dde 100644
--- a/components/history/core/browser/browsing_history_service.cc
+++ b/components/history/core/browser/browsing_history_service.cc
@@ -648,6 +648,7 @@
     if (const base::Value* events = results_value->FindListKey("event")) {
       state->remote_results.reserve(state->remote_results.size() +
                                     events->GetList().size());
+      std::string host_name_utf8 = base::UTF16ToUTF8(state->search_text);
       for (const base::Value& event : events->GetList()) {
         if (!event.is_dict())
           continue;
@@ -664,8 +665,15 @@
         if (!ids || ids->GetList().empty())
           continue;
 
-        // Ignore any URLs that should not be shown in the history page.
         GURL gurl(*url);
+        if (state->original_options.host_only) {
+          // Do post filter to skip entries that do not have the correct
+          // hostname.
+          if (gurl.host() != host_name_utf8)
+            continue;
+        }
+
+        // Ignore any URLs that should not be shown in the history page.
         if (driver_->ShouldHideWebHistoryUrl(gurl))
           continue;
 
diff --git a/components/history/core/browser/browsing_history_service_unittest.cc b/components/history/core/browser/browsing_history_service_unittest.cc
index 7a5e097..918b85b8 100644
--- a/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/components/history/core/browser/browsing_history_service_unittest.cc
@@ -41,6 +41,9 @@
 const char kUrl5[] = "http://www.five.com";
 const char kUrl6[] = "http://www.six.com";
 const char kUrl7[] = "http://www.seven.com";
+const char kUrl8[] = "http://eight.com";
+const char kUrl9[] = "http://nine.com/eight.com";
+const char kUrl10[] = "http://ten.com/eight";
 const char kIconUrl1[] = "http://www.one.com/favicon.ico";
 
 const HistoryEntry::EntryType kLocal = HistoryEntry::LOCAL_ENTRY;
@@ -253,8 +256,14 @@
 
   TestBrowsingHistoryDriver::QueryResult QueryHistory(
       const QueryOptions& options) {
+    return QueryHistory(std::u16string(), options);
+  }
+
+  TestBrowsingHistoryDriver::QueryResult QueryHistory(
+      const std::u16string& query_text,
+      const QueryOptions& options) {
     size_t previous_results_count = driver()->GetQueryResults().size();
-    service()->QueryHistory(std::u16string(), options);
+    service()->QueryHistory(query_text, options);
     BlockUntilHistoryProcessesPendingRequests();
     const std::vector<TestBrowsingHistoryDriver::QueryResult> all_results =
         driver()->GetQueryResults();
@@ -405,6 +414,23 @@
       {{kUrl3, 3, kRemote}, {kUrl2, 2, kRemote}}, QueryHistory(options));
 }
 
+TEST_F(BrowsingHistoryServiceTest, QueryHistoryHostOnlyRemote) {
+  AddHistory({{kUrl8, 1, kRemote}, {kUrl9, 2, kRemote}, {kUrl10, 3, kRemote}});
+
+  QueryOptions options;
+  options.max_count = 0;
+  options.host_only = false;
+  VerifyQueryResult(
+      /*reached_beginning*/ true,
+      /*has_synced_results*/ true,
+      {{kUrl10, 3, kRemote}, {kUrl9, 2, kRemote}, {kUrl8, 1, kRemote}},
+      QueryHistory(u"eight.com", options));
+  options.host_only = true;
+  VerifyQueryResult(/*reached_beginning*/ true,
+                    /*has_synced_results*/ true, {{kUrl8, 1, kRemote}},
+                    QueryHistory(u"eight.com", options));
+}
+
 TEST_F(BrowsingHistoryServiceTest, QueryHistoryLocalPagingPartial) {
   AddHistory({{kUrl1, 1, kLocal}, {kUrl2, 2, kLocal}, {kUrl3, 3, kLocal}});
   VerifyQueryResult(/*reached_beginning*/ false,
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index 9017009..e7c675c 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -1645,9 +1645,12 @@
 void HistoryBackend::QueryHistoryText(const std::u16string& text_query,
                                       const QueryOptions& options,
                                       QueryResults* result) {
-  URLRows text_matches;
-  db_->GetTextMatchesWithAlgorithm(text_query, options.matching_algorithm,
-                                   &text_matches);
+  URLRows text_matches =
+      options.host_only
+          ? GetMatchesForHost(text_query)
+          : db_->GetTextMatchesWithAlgorithm(
+                text_query, options.matching_algorithm.value_or(
+                                query_parser::MatchingAlgorithm::DEFAULT));
 
   std::vector<URLResult> matching_visits;
   VisitVector visits;  // Declare outside loop to prevent re-construction.
@@ -1683,6 +1686,23 @@
     result->set_reached_beginning(true);
 }
 
+URLRows HistoryBackend::GetMatchesForHost(const std::u16string& host_name) {
+  URLRows results;
+  URLDatabase::URLEnumerator iter;
+
+  if (db_ && db_->InitURLEnumeratorForEverything(&iter)) {
+    URLRow row;
+    std::string host_name_utf8 = base::UTF16ToUTF8(host_name);
+    while (iter.GetNextURL(&row)) {
+      if (row.url().is_valid() && row.url().host() == host_name_utf8) {
+        results.push_back(std::move(row));
+      }
+    }
+  }
+
+  return results;
+}
+
 RedirectList HistoryBackend::QueryRedirectsFrom(const GURL& from_url) {
   if (!db_)
     return {};
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index f1bdf6c..cb3e8d9 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -645,6 +645,10 @@
                         const QueryOptions& options,
                         QueryResults* result);
 
+  // Performs a brute force search over the database to find any host names that
+  // match the `host_name` string. Returns any matches.
+  URLRows GetMatchesForHost(const std::u16string& host_name);
+
   // Clusters ------------------------------------------------------------------
 
   // Convert `AnnotatedVisitRow`s to `AnnotatedVisit`s. Drops rows without
diff --git a/components/history/core/browser/history_querying_unittest.cc b/components/history/core/browser/history_querying_unittest.cc
index 8f0ff53..b4e6cbb 100644
--- a/components/history/core/browser/history_querying_unittest.cc
+++ b/components/history/core/browser/history_querying_unittest.cc
@@ -34,23 +34,36 @@
   const int days_ago;
   base::Time time;  // Filled by SetUp.
 } test_entries[] = {
-  // This one is visited super long ago so it will be in a different database
-  // from the next appearance of it at the end.
-  {"http://example.com/", "Other", 180},
+    // This one is visited super long ago so it will be in a different database
+    // from the next appearance of it at the end.
+    {"http://example.com/", "Other", 180},
 
-  // These are deliberately added out of chronological order. The history
-  // service should sort them by visit time when returning query results.
-  // The correct index sort order is 4 2 3 1 7 6 5 0.
-  {"http://www.google.com/1", "Title PAGEONE FOO some text", 10},
-  {"http://www.google.com/3", "Title PAGETHREE BAR some hello world", 8},
-  {"http://www.google.com/2", "Title PAGETWO FOO some more blah blah blah", 9},
+    // These are deliberately added out of chronological order. The history
+    // service should sort them by visit time when returning query results.
+    // The correct index sort order is 4 2 3 1 7 6 5 0.
+    {"http://www.google.com/1", "Title PAGEONE FOO some text", 10},
+    {"http://www.google.com/3", "Title PAGETHREE BAR some hello world", 8},
+    {"http://www.google.com/2", "Title PAGETWO FOO some more blah blah blah",
+     9},
 
-  // A more recent visit of the first one.
-  {"http://example.com/", "Other", 6},
+    // A more recent visit of the first one.
+    {"http://example.com/", "Other", 6},
 
-  {"http://www.google.com/6", "Title I'm the second oldest", 13},
-  {"http://www.google.com/4", "Title four", 12},
-  {"http://www.google.com/5", "Title five", 11},
+    {"http://www.google.com/6", "Title I'm the second oldest", 13},
+    {"http://www.google.com/4", "Title four", 12},
+    {"http://www.google.com/5", "Title five", 11},
+
+    // Tricky URLs to test query history by hostname. Will be sorted by visit
+    // order.
+    // These URLs should all match the hostname example.test.
+    {"http://example.test/", "Host Normal HTTP", 14},
+    {"http://example.test/page_1", "Host HTTP path1", 15},
+    {"https://example.test/page_2", "Host HTTPS path2", 16},
+    {"http://example.test:8080/page_3", "Host HTTP port", 17},
+    // These URLs should not match the hostname.
+    {"http://evil.test/example", "Host Evil domain", 18},
+    {"http://evil.com/example.test", "Host Evil path", 19},
+    {"https://random.test/", "Host random example.test", 20},
 };
 
 // Returns true if the nth result in the given results set matches. It will
@@ -214,7 +227,7 @@
   // Test duplicate collapsing. 0 is an older duplicate of 4, and should not
   // appear in the result set.
   QueryHistory(std::string(), options, &results);
-  EXPECT_EQ(7U, results.size());
+  EXPECT_EQ(14U, results.size());
 
   EXPECT_TRUE(NthResultIs(results, 0, 4));
   EXPECT_TRUE(NthResultIs(results, 1, 2));
@@ -223,6 +236,13 @@
   EXPECT_TRUE(NthResultIs(results, 4, 7));
   EXPECT_TRUE(NthResultIs(results, 5, 6));
   EXPECT_TRUE(NthResultIs(results, 6, 5));
+  EXPECT_TRUE(NthResultIs(results, 7, 8));
+  EXPECT_TRUE(NthResultIs(results, 8, 9));
+  EXPECT_TRUE(NthResultIs(results, 9, 10));
+  EXPECT_TRUE(NthResultIs(results, 10, 11));
+  EXPECT_TRUE(NthResultIs(results, 11, 12));
+  EXPECT_TRUE(NthResultIs(results, 12, 13));
+  EXPECT_TRUE(NthResultIs(results, 13, 14));
 
   // Next query a time range. The beginning should be inclusive, the ending
   // should be exclusive.
@@ -360,6 +380,34 @@
   EXPECT_TRUE(NthResultIs(results, 1, 3));
 }
 
+TEST_F(HistoryQueryTest, HostSearch) {
+  ASSERT_TRUE(history_.get());
+
+  QueryOptions options;
+  QueryResults results;
+
+  // Query all normal search to make sure all entries appear.
+  options.host_only = false;
+  QueryHistory("example.test", options, &results);
+  EXPECT_EQ(7U, results.size());
+  EXPECT_TRUE(NthResultIs(results, 0, 8));
+  EXPECT_TRUE(NthResultIs(results, 1, 9));
+  EXPECT_TRUE(NthResultIs(results, 2, 10));
+  EXPECT_TRUE(NthResultIs(results, 3, 11));
+  EXPECT_TRUE(NthResultIs(results, 4, 12));
+  EXPECT_TRUE(NthResultIs(results, 5, 13));
+  EXPECT_TRUE(NthResultIs(results, 6, 14));
+
+  // Query with host_only = true to make sure only the host entries show up.
+  options.host_only = true;
+  QueryHistory("example.test", options, &results);
+  EXPECT_EQ(4U, results.size());
+  EXPECT_TRUE(NthResultIs(results, 0, 8));
+  EXPECT_TRUE(NthResultIs(results, 1, 9));
+  EXPECT_TRUE(NthResultIs(results, 2, 10));
+  EXPECT_TRUE(NthResultIs(results, 3, 11));
+}
+
 // Tests max_count feature for text search queries.
 TEST_F(HistoryQueryTest, TextSearchCount) {
   ASSERT_TRUE(history_.get());
@@ -414,7 +462,7 @@
 TEST_F(HistoryQueryTest, Paging) {
   // Since results are fetched 1 and 2 at a time, entry #0 and #6 will not
   // be de-duplicated.
-  int expected_results[] = { 4, 2, 3, 1, 7, 6, 5, 0 };
+  int expected_results[] = {4, 2, 3, 1, 7, 6, 5, 8, 9, 10, 11, 12, 13, 14, 0};
   TestPaging(std::string(), expected_results, base::size(expected_results));
 }
 
diff --git a/components/history/core/browser/history_types.cc b/components/history/core/browser/history_types.cc
index 6adacac..b5a7a76 100644
--- a/components/history/core/browser/history_types.cc
+++ b/components/history/core/browser/history_types.cc
@@ -156,6 +156,16 @@
 
 QueryOptions::QueryOptions() = default;
 
+QueryOptions::~QueryOptions() = default;
+
+QueryOptions::QueryOptions(const QueryOptions&) = default;
+
+QueryOptions::QueryOptions(QueryOptions&&) noexcept = default;
+
+QueryOptions& QueryOptions::operator=(const QueryOptions&) = default;
+
+QueryOptions& QueryOptions::operator=(QueryOptions&&) noexcept = default;
+
 void QueryOptions::SetRecentDayRange(int days_ago) {
   end_time = base::Time::Now();
   begin_time = end_time - base::TimeDelta::FromDays(days_ago);
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index 135abf0..e55ac2bf 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -215,6 +215,11 @@
 
 struct QueryOptions {
   QueryOptions();
+  QueryOptions(const QueryOptions&);
+  QueryOptions(QueryOptions&&) noexcept;
+  QueryOptions& operator=(const QueryOptions&);
+  QueryOptions& operator=(QueryOptions&&) noexcept;
+  ~QueryOptions();
 
   // The time range to search for matches in. The beginning is inclusive and
   // the ending is exclusive. Either one (or both) may be null.
@@ -254,8 +259,14 @@
   DuplicateHandling duplicate_policy = REMOVE_ALL_DUPLICATES;
 
   // Allows the caller to specify the matching algorithm for text queries.
-  query_parser::MatchingAlgorithm matching_algorithm =
-      query_parser::MatchingAlgorithm::DEFAULT;
+  // query_parser::MatchingAlgorithm matching_algorithm =
+  // query_parser::MatchingAlgorithm::DEFAULT;
+  absl::optional<query_parser::MatchingAlgorithm> matching_algorithm =
+      absl::nullopt;
+
+  // Whether the history query should only search through hostnames.
+  // When this is true, the matching_algorithm field is ignored.
+  bool host_only = false;
 
   // Helpers to get the effective parameters values, since a value of 0 means
   // "unspecified".
diff --git a/components/history/core/browser/url_database.cc b/components/history/core/browser/url_database.cc
index 4e02e88..54eb9e4 100644
--- a/components/history/core/browser/url_database.cc
+++ b/components/history/core/browser/url_database.cc
@@ -404,20 +404,18 @@
   return true;
 }
 
-bool URLDatabase::GetTextMatches(const std::u16string& query,
-                                 URLRows* results) {
-  return GetTextMatchesWithAlgorithm(
-      query, query_parser::MatchingAlgorithm::DEFAULT, results);
+URLRows URLDatabase::GetTextMatches(const std::u16string& query) {
+  return GetTextMatchesWithAlgorithm(query,
+                                     query_parser::MatchingAlgorithm::DEFAULT);
 }
 
-bool URLDatabase::GetTextMatchesWithAlgorithm(
+URLRows URLDatabase::GetTextMatchesWithAlgorithm(
     const std::u16string& query,
-    query_parser::MatchingAlgorithm algorithm,
-    URLRows* results) {
+    query_parser::MatchingAlgorithm algorithm) {
   query_parser::QueryNodeVector query_nodes;
   query_parser::QueryParser::ParseQueryNodes(query, algorithm, &query_nodes);
 
-  results->clear();
+  URLRows results;
   sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE hidden = 0"));
 
@@ -440,10 +438,10 @@
       URLResult info;
       FillURLRow(statement, &info);
       if (info.url().is_valid())
-        results->push_back(info);
+        results.push_back(info);
     }
   }
-  return !results->empty();
+  return results;
 }
 
 bool URLDatabase::InitKeywordSearchTermsTable() {
diff --git a/components/history/core/browser/url_database.h b/components/history/core/browser/url_database.h
index 827b1ec..ebb9438 100644
--- a/components/history/core/browser/url_database.h
+++ b/components/history/core/browser/url_database.h
@@ -183,14 +183,14 @@
 
   // Performs a brute force search over the database to find any URLs or titles
   // which match the `query` string, using the default text matching algorithm.
-  // Returns any matches in `results`.
-  bool GetTextMatches(const std::u16string& query, URLRows* results);
+  // Returns any matches.
+  URLRows GetTextMatches(const std::u16string& query);
 
   // Same as GetTextMatches, using `algorithm` as the text matching
   // algorithm.
-  bool GetTextMatchesWithAlgorithm(const std::u16string& query,
-                                   query_parser::MatchingAlgorithm algorithm,
-                                   URLRows* results);
+  URLRows GetTextMatchesWithAlgorithm(
+      const std::u16string& query,
+      query_parser::MatchingAlgorithm algorithm);
 
   // Keyword Search Terms ------------------------------------------------------
 
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc
index 7b5eca06..ed19a97 100644
--- a/components/history_clusters/core/history_clusters_service.cc
+++ b/components/history_clusters/core/history_clusters_service.cc
@@ -236,7 +236,7 @@
 
 void HistoryClustersService::QueryClusters(
     const std::string& query,
-    const base::Time max_time,
+    base::Time end_time,
     const size_t max_count,
     QueryClustersCallback callback,
     base::CancelableTaskTracker* task_tracker) {
@@ -250,8 +250,8 @@
     return;
   }
 
-  // TODO(crbug.com/1220765): The service does not support paging at the moment.
-  // Thus `max_time` and `max_count` are ignored.
+  // TODO(crbug.com/1220765): Fully support pagination using `end_time` and
+  //  `max_count`.
   auto on_visits_callback = base::BindOnce(
       &ClusteringBackend::GetClusters, backend_weak_factory_->GetWeakPtr(),
       base::BindOnce(&FilterClustersMatchingQuery, query)
@@ -261,33 +261,39 @@
   history_service_->GetRecentClusterIdsAndAnnotatedVisits(
       base::Time::Min(), kMaxVisitsToCluster.Get(),
       base::BindOnce(
-          [](const IncompleteVisitMap& incomplete_visit_context_annotations,
+          [](const IncompleteVisitMap& incomplete_visits,
+             const base::Time& end_time,
              history::ClusterIdsAndAnnotatedVisitsResult result) {
             auto& visits = result.annotated_visits;
 
             // Append incomplete visits to `visits` too, as otherwise they will
             // be mysteriously missing from the Clusters UI. They haven't
             // recorded the page end metrics yet, but that's fine.
-            for (const auto& item : incomplete_visit_context_annotations) {
-              auto& incomplete_visit_context_annotation = item.second;
-              if (incomplete_visit_context_annotation.url_row.id() == 0 ||
-                  incomplete_visit_context_annotation.visit_row.visit_id == 0) {
+            for (const auto& item : incomplete_visits) {
+              auto& incomplete_visit = item.second;
+              if (incomplete_visit.url_row.id() == 0 ||
+                  incomplete_visit.visit_row.visit_id == 0) {
                 // Discard incomplete visits that don't have visit_ids yet.
                 continue;
               }
 
-              visits.push_back(
-                  {incomplete_visit_context_annotation.url_row,
-                   incomplete_visit_context_annotation.visit_row,
-                   incomplete_visit_context_annotation.context_annotations,
-                   // Content annotations not provided, but it's not provided
-                   // for complete visits either.
-                   {}});
+              if (!end_time.is_null() &&
+                  incomplete_visit.visit_row.visit_time >= end_time) {
+                // Discard incomplete visits are outside the `end_time` bound.
+                continue;
+              }
+
+              visits.push_back({incomplete_visit.url_row,
+                                incomplete_visit.visit_row,
+                                incomplete_visit.context_annotations,
+                                // Content annotations not provided, but it's
+                                // not provided for complete visits either.
+                                {}});
             }
 
             return visits;
           },
-          incomplete_visit_context_annotations_)
+          incomplete_visit_context_annotations_, end_time)
           .Then(std::move(on_visits_callback)),
       task_tracker);
 }
@@ -314,7 +320,7 @@
     // TODO(tommycli): Make sure we are hitting the local database, and not the
     //  remote model service once cluster persistence is ready.
     QueryClusters(
-        /*query=*/"", /*max_time=*/base::Time::Now(), /* max_count=*/0,
+        /*query=*/"", /*end_time=*/base::Time(), /*max_count=*/0,
         base::BindOnce(&HistoryClustersService::PopulateClusterKeywordCache,
                        weak_ptr_factory_.GetWeakPtr()),
         &cache_query_task_tracker_);
diff --git a/components/history_clusters/core/history_clusters_service.h b/components/history_clusters/core/history_clusters_service.h
index 5848b134..bb0fa86 100644
--- a/components/history_clusters/core/history_clusters_service.h
+++ b/components/history_clusters/core/history_clusters_service.h
@@ -75,14 +75,15 @@
   void CompleteVisitContextAnnotationsIfReady(int64_t nav_id);
 
   // Returns the freshest clusters created from the user visit history based on
-  // the parameters in `query_params`.
+  // `query`, `end_time`, and `max_count`. `end_time` is an exclusive upper
+  // bound, and should be set to `base::Time()` if the caller wants everything.
   // The returned clusters are sorted in reverse-chronological order based on
   // their highest scoring visit. The visits within each cluster are sorted by
   // score, from highest to lowest.
   using QueryClustersCallback =
       base::OnceCallback<void(std::vector<mojom::ClusterPtr>)>;
   void QueryClusters(const std::string& query,
-                     base::Time max_time,
+                     base::Time end_time,
                      size_t max_count,
                      QueryClustersCallback callback,
                      base::CancelableTaskTracker* task_tracker);
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc
index 3589c5c..4c9f555 100644
--- a/components/lens/lens_features.cc
+++ b/components/lens/lens_features.cc
@@ -16,6 +16,15 @@
 const base::Feature kLensRegionSearch{"LensRegionSearch",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText1{
+    &kLensRegionSearch, "use-menu-item-alt-text-1", false};
+
+const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText2{
+    &kLensRegionSearch, "use-menu-item-alt-text-2", false};
+
+const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText3{
+    &kLensRegionSearch, "use-menu-item-alt-text-3", false};
+
 constexpr base::FeatureParam<int> kMaxPixels{&kLensStandalone,
                                              "dimensions-max-pixels", 1000};
 
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h
index d44e555..52d80d7 100644
--- a/components/lens/lens_features.h
+++ b/components/lens/lens_features.h
@@ -18,6 +18,15 @@
 // Enables Lens Region Search from the context menu.
 extern const base::Feature kLensRegionSearch;
 
+// Enables alternate option 1 for the Region Search context menu item text.
+extern const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText1;
+
+// Enables alternate option 2 for the Region Search context menu item text.
+extern const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText2;
+
+// Enables alternate option 3 for the Region Search context menu item text.
+extern const base::FeatureParam<bool> kRegionSearchUseMenuItemAltText3;
+
 // Returns the max pixel width/height for the image to be sent to Lens.
 extern int GetMaxPixels();
 
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index 4978a1d..e05e4452 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -187,10 +187,20 @@
         "//components/metrics/android/java_templates/MetricsSwitches.java.tmpl"
   }
 
+  java_cpp_enum("java_enum_srcjar") {
+    # External code should depend on ":metrics_java" instead.
+    visibility = [ ":*" ]
+    sources = [ "stability_metrics_helper.h" ]
+  }
+
   android_library("metrics_java") {
     # Right now, this only includes the Java switches. But if we need more Java
     # files, they should be added here as necessary.
-    srcjar_deps = [ ":java_switches_srcjar" ]
+    srcjar_deps = [
+      ":java_enum_srcjar",
+      ":java_switches_srcjar",
+    ]
+    deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ]
   }
 }
 
diff --git a/components/metrics/stability_metrics_helper.h b/components/metrics/stability_metrics_helper.h
index 77e0d16d..7105af9 100644
--- a/components/metrics/stability_metrics_helper.h
+++ b/components/metrics/stability_metrics_helper.h
@@ -18,6 +18,7 @@
 // The values here correspond to values in the Stability message in
 // system_profile.proto.
 // This must stay 1-1 with the StabilityEventType enum in enums.xml.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.metrics
 enum class StabilityEventType {
   kPageLoad = 2,
   kRendererCrash = 3,
diff --git a/components/omnibox/browser/search_suggestion_parser.cc b/components/omnibox/browser/search_suggestion_parser.cc
index f292303..4eed0714 100644
--- a/components/omnibox/browser/search_suggestion_parser.cc
+++ b/components/omnibox/browser/search_suggestion_parser.cc
@@ -472,23 +472,27 @@
 
   // 5th element: Optional key-value pairs from the Suggest server.
   const base::ListValue* types = nullptr;
-  const base::ListValue* relevances = nullptr;
   const base::ListValue* experiment_stats = nullptr;
   const base::ListValue* suggestion_details = nullptr;
-  const base::ListValue* subtype_identifiers = nullptr;
   const base::DictionaryValue* extras = nullptr;
   const base::Value* suggestsubtypes = nullptr;
   int prefetch_index = -1;
 
+  absl::optional<base::Value::ConstListView> subtype_identifiers;
+  absl::optional<base::Value::ConstListView> relevances;
+
   if (root_list.size() > 4u && root_list[4].GetAsDictionary(&extras)) {
     extras->GetList("google:suggesttype", &types);
 
     suggestsubtypes = extras->FindPath("google:suggestsubtypes");
 
     // Discard this list if its size does not match that of the suggestions.
-    if (extras->GetList("google:suggestrelevance", &relevances) &&
-        (relevances->GetSize() != results_list.size()))
-      relevances = nullptr;
+    const base::Value* relevances_value =
+        extras->FindListKey("google:suggestrelevance");
+    if (relevances_value &&
+        relevances_value->GetList().size() == results_list.size()) {
+      relevances = relevances_value->GetList();
+    }
     extras->GetInteger("google:verbatimrelevance",
                        &results->verbatim_relevance);
 
@@ -540,9 +544,11 @@
       suggestion_details = nullptr;
 
     // Legacy code: Get subtype identifiers.
-    if (extras->GetList("google:subtypeid", &subtype_identifiers) &&
-        subtype_identifiers->GetSize() != results_list.size()) {
-      subtype_identifiers = nullptr;
+    const base::Value* subtype_identifiers_value =
+        extras->FindListKey("google:subtypeid");
+    if (subtype_identifiers_value &&
+        subtype_identifiers_value->GetList().size() == results_list.size()) {
+      subtype_identifiers = subtype_identifiers_value->GetList();
     }
 
     // Store the metadata that came with the response in case we need to pass it
@@ -577,16 +583,23 @@
       continue;
 
     // Apply valid suggested relevance scores; discard invalid lists.
-    if (relevances != nullptr && !relevances->GetInteger(index, &relevance))
-      relevances = nullptr;
+    if (relevances) {
+      const auto& val = (*relevances)[index];
+      if (!val.is_int()) {
+        relevances = absl::nullopt;
+      } else {
+        relevance = val.GetInt();
+      }
+    }
+
     AutocompleteMatchType::Type match_type =
         AutocompleteMatchType::SEARCH_SUGGEST;
 
     // Legacy code: if the server sends us a single subtype ID, place it beside
     // other subtypes.
     if (subtype_identifiers) {
-      int subtype_identifier = 0;
-      subtype_identifiers->GetInteger(index, &subtype_identifier);
+      int subtype_identifier =
+          (*subtype_identifiers)[index].GetIfInt().value_or(0);
 
       if (subtype_identifier != 0) {
         subtypes[index].emplace_back(subtype_identifier);
@@ -616,7 +629,7 @@
         }
         results->navigation_results.push_back(NavigationResult(
             scheme_classifier, url, match_type, subtypes[index], title,
-            deletion_url, is_keyword_result, relevance, relevances != nullptr,
+            deletion_url, is_keyword_result, relevance, relevances.has_value(),
             input.text()));
       }
     } else {
@@ -685,7 +698,7 @@
           base::CollapseWhitespace(match_contents, false),
           match_contents_prefix, annotation, additional_query_params,
           deletion_url, image_dominant_color, image_url, is_keyword_result,
-          relevance, relevances != nullptr, should_prefetch, trimmed_input));
+          relevance, relevances.has_value(), should_prefetch, trimmed_input));
 
       if (suggestion_group_id) {
         results->suggest_results.back().set_suggestion_group_id(
@@ -695,6 +708,6 @@
         results->suggest_results.back().SetAnswer(answer);
     }
   }
-  results->relevances_from_server = relevances != nullptr;
+  results->relevances_from_server = relevances.has_value();
   return true;
 }
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 72aa6df24..6ed9b213 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -254,6 +254,10 @@
 const base::Feature kRichAutocompletion{"OmniboxRichAutocompletion",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Feature used to enable Suggestion Answers in the NTP Realbox.
+const base::Feature kNtpRealboxSuggestionAnswers{
+    "NtpRealboxSuggestionAnswers", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Feature used to enable the second batch of Pedals (Safety Check, etc.).
 const base::Feature kOmniboxPedalsBatch2{"OmniboxPedalsBatch2",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h
index 1f425fd..57f29ed1 100644
--- a/components/omnibox/common/omnibox_features.h
+++ b/components/omnibox/common/omnibox_features.h
@@ -68,6 +68,7 @@
 extern const base::Feature kCompactSuggestions;
 extern const base::Feature kMostVisitedTiles;
 extern const base::Feature kRichAutocompletion;
+extern const base::Feature kNtpRealboxSuggestionAnswers;
 extern const base::Feature kOmniboxPedalsBatch2;
 extern const base::Feature kOmniboxPedalsBatch2NonEnglish;
 extern const base::Feature kOmniboxPedalsBatch3;
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 86aa8d5..3453aaa 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -1214,6 +1214,8 @@
 PasswordStoreChangeList LoginDatabase::UpdateLogin(const PasswordForm& form,
                                                    UpdateLoginError* error) {
   TRACE_EVENT0("passwords", "LoginDatabase::UpdateLogin");
+  base::UmaHistogramBoolean("PasswordManager.UpdateLoginPasswordIssuesHasValue",
+                            form.password_issues.has_value());
   if (error) {
     *error = UpdateLoginError::kNone;
   }
@@ -1296,23 +1298,36 @@
   bool password_changed =
       form.password_value != old_primary_key_password.decrypted_password;
 
+  PasswordForm form_with_encrypted_password = form;
+  form_with_encrypted_password.encrypted_password = encrypted_password;
+
   InsecureCredentialsChanged insecure_changed(false);
   // TODO(crbug.com/1223022): It should be the responsibility of the caller to
   // set `password_issues` to empty instead of leaving it nullopt in this case.
   // Remove this once all `UpdateLogin` calls have been checked.
-  if (password_changed && !form.password_issues.has_value()) {
+  if (password_changed) {
     insecure_changed = UpdateInsecureCredentials(
         FormPrimaryKey(old_primary_key_password.primary_key),
         base::flat_map<InsecureType, InsecurityMetadata>());
+    form_with_encrypted_password.password_issues =
+        base::flat_map<InsecureType, InsecurityMetadata>();
   } else if (form.password_issues.has_value()) {
     insecure_changed = UpdateInsecureCredentials(
         FormPrimaryKey(old_primary_key_password.primary_key),
         form.password_issues.value());
   }
 
+  // Make sure that the form included in the `PasswordStoreChangeList` contains
+  // password issues info.
+  if (!form_with_encrypted_password.password_issues.has_value()) {
+    // TODO(crbug.com/1223022): Re-evaluate this once all places that call
+    // UpdateLogin have been changed to populate the |password_issues| field.
+    PopulateFormWithPasswordIssues(
+        FormPrimaryKey(old_primary_key_password.primary_key),
+        &form_with_encrypted_password);
+  }
+
   PasswordStoreChangeList list;
-  PasswordForm form_with_encrypted_password = form;
-  form_with_encrypted_password.encrypted_password = encrypted_password;
   FillFormInStore(&form_with_encrypted_password);
   list.emplace_back(PasswordStoreChange::UPDATE,
                     std::move(form_with_encrypted_password),
@@ -1534,15 +1549,7 @@
         s.ColumnByteLength(COLUMN_MOVING_BLOCKED_FOR));
     form->moving_blocked_for_list = DeserializeGaiaIdHashVector(pickle);
   }
-
-  std::vector<InsecureCredential> insecure_credentials =
-      insecure_credentials_table_.GetRows(FormPrimaryKey(*primary_key));
-  base::flat_map<InsecureType, InsecurityMetadata> issues;
-  for (const auto& insecure_credential : insecure_credentials) {
-    issues[insecure_credential.insecure_type] = InsecurityMetadata(
-        insecure_credential.create_time, insecure_credential.is_muted);
-  }
-  form->password_issues = std::move(issues);
+  PopulateFormWithPasswordIssues(FormPrimaryKey(*primary_key), form);
 
   return ENCRYPTION_RESULT_SUCCESS;
 }
@@ -2177,6 +2184,18 @@
                                       : PasswordForm::Store::kProfileStore;
 }
 
+void LoginDatabase::PopulateFormWithPasswordIssues(FormPrimaryKey primary_key,
+                                                   PasswordForm* form) const {
+  std::vector<InsecureCredential> insecure_credentials =
+      insecure_credentials_table_.GetRows(primary_key);
+  base::flat_map<InsecureType, InsecurityMetadata> issues;
+  for (const auto& insecure_credential : insecure_credentials) {
+    issues[insecure_credential.insecure_type] = InsecurityMetadata(
+        insecure_credential.create_time, insecure_credential.is_muted);
+  }
+  form->password_issues = std::move(issues);
+}
+
 InsecureCredentialsChanged LoginDatabase::UpdateInsecureCredentials(
     FormPrimaryKey primary_key,
     const base::flat_map<InsecureType, InsecurityMetadata>& password_issues) {
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h
index 46ccbc18..2de9177fd 100644
--- a/components/password_manager/core/browser/login_database.h
+++ b/components/password_manager/core/browser/login_database.h
@@ -17,6 +17,7 @@
 #include "build/build_config.h"
 #include "components/password_manager/core/browser/field_info_table.h"
 #include "components/password_manager/core/browser/insecure_credentials_table.h"
+#include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_change.h"
 #include "components/password_manager/core/browser/password_store_sync.h"
@@ -327,6 +328,11 @@
   // kAccountStore depending on the value of `is_account_store_`.
   void FillFormInStore(PasswordForm* form) const;
 
+  // Reads the insecure credentials corresponding to the `primary_key` from the
+  // database and fills them into `form->password_issues`.
+  void PopulateFormWithPasswordIssues(FormPrimaryKey primary_key,
+                                      PasswordForm* form) const;
+
   // Updates data in the `insecure_credentials_table_` with the password issues
   // data from `password_issues`. Returns whether any insecure credential entry
   // was changed.
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index 91c3831..1cb17f05 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -103,8 +103,9 @@
   form.in_store = PasswordForm::Store::kProfileStore;
   form.moving_blocked_for_list.push_back(GaiaIdHash::FromGaiaId("user1"));
   form.moving_blocked_for_list.push_back(GaiaIdHash::FromGaiaId("user2"));
+
   // TODO(crbug.com/1223022): Once all places that operate changes on forms
-  //  via UpdateLogin properly set |password_issues|, setting them to an empty
+  // via UpdateLogin properly set |password_issues|, setting them to an empty
   // map should be part of the default constructor.
   form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
   return form;
@@ -1324,6 +1325,14 @@
   ASSERT_EQ(2U, result.size());
   result.clear();
 
+  // TODO(crbug.com/1223022): Once all places that operate changes on forms
+  // via UpdateLogin properly set |password_issues|, setting them to an empty
+  // map should be part of the default constructor.
+  complete_form.password_issues =
+      base::flat_map<InsecureType, InsecurityMetadata>();
+  incomplete_form.password_issues =
+      base::flat_map<InsecureType, InsecurityMetadata>();
+
   // Simulate the user changing their password.
   complete_form.password_value = u"new_password";
   complete_form.date_synced = base::Time::Now();
@@ -1334,14 +1343,6 @@
   complete_form.in_store = PasswordForm::Store::kProfileStore;
   incomplete_form.in_store = PasswordForm::Store::kProfileStore;
 
-  // And |password_issues| should be set to empty.
-  // TODO(crbug.com/1223022): Once all places that operate changes on forms
-  // via UpdateLogin properly set |password_issues|, setting them to an empty
-  // map should be part of the default constructor.
-  complete_form.password_issues =
-      base::flat_map<InsecureType, InsecurityMetadata>();
-  incomplete_form.password_issues =
-      base::flat_map<InsecureType, InsecurityMetadata>();
 
   // Both still exist now.
   EXPECT_TRUE(db().GetAutofillableLogins(&result));
@@ -1418,6 +1419,10 @@
   form.skip_zero_click = true;
   form.moving_blocked_for_list.push_back(GaiaIdHash::FromGaiaId("gaia_id"));
 
+  // TODO(crbug.com/1223022): Once all places that operate changes on forms
+  // via UpdateLogin properly set |password_issues|, setting them to an empty
+  // map should be part of the default constructor.
+  form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
   PasswordStoreChangeList changes = db().UpdateLogin(form);
   EXPECT_EQ(UpdateChangeForForm(form, /*password_changed=*/true), changes);
   ASSERT_EQ(1U, changes.size());
@@ -1426,12 +1431,6 @@
   // When we retrieve the form from the store, it should have |in_store| set.
   form.in_store = PasswordForm::Store::kProfileStore;
 
-  // And |password_issues| should be empty
-  // TODO(crbug.com/1223022): Once all places that operate changes on forms
-  // via UpdateLogin properly set |password_issues|, setting them to an empty
-  // map should be part of the default constructor.
-  form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
-
   std::vector<std::unique_ptr<PasswordForm>> result;
   EXPECT_TRUE(db().GetLogins(PasswordFormDigest(form), &result));
   ASSERT_EQ(1U, result.size());
@@ -1462,6 +1461,11 @@
   form.skip_zero_click = true;
   form.moving_blocked_for_list.push_back(GaiaIdHash::FromGaiaId("gaia_id"));
 
+  // TODO(crbug.com/1223022): Once all places that operate changes on forms
+  // via UpdateLogin properly set |password_issues|, setting them to an empty
+  // map should be part of the default constructor.
+  form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
+
   PasswordStoreChangeList changes = db().UpdateLogin(form);
   EXPECT_EQ(UpdateChangeForForm(form, /*password_changed=*/false), changes);
   ASSERT_EQ(1U, changes.size());
@@ -1469,11 +1473,6 @@
 
   // When we retrieve the form from the store, it should have |in_store| set.
   form.in_store = PasswordForm::Store::kProfileStore;
-  // And |password_issues| should be empty
-  // TODO(crbug.com/1223022): Once all places that operate changes on forms
-  // via UpdateLogin properly set |password_issues|, setting them to an empty
-  // map should be part of the default constructor.
-  form.password_issues = base::flat_map<InsecureType, InsecurityMetadata>();
 
   std::vector<std::unique_ptr<PasswordForm>> result;
   ASSERT_TRUE(db().GetLogins(PasswordFormDigest(form), &result));
@@ -2766,7 +2765,6 @@
 
 TEST_F(LoginDatabaseTest, UpdateLoginWithNoInsecureCredentialInformation) {
   PasswordForm form = GenerateExamplePasswordForm();
-  ignore_result(db().AddLogin(form));
   InsecureCredential insecure_credential{form.signon_realm, form.username_value,
                                          base::Time(), InsecureType::kLeaked,
                                          IsMuted(false)};
@@ -2775,15 +2773,13 @@
       insecure_credential.create_time, insecure_credential.is_muted);
   form.password_issues = std::move(issues);
 
-  ASSERT_EQ(UpdateChangeForForm(form, /*password_changed=*/false,
-                                /*insecure_changed=*/true),
-            db().UpdateLogin(form, nullptr));
+  ignore_result(db().AddLogin(form));
   ASSERT_THAT(db().insecure_credentials_table().GetAllRows(),
               ElementsAre(insecure_credential));
 
   PasswordForm no_info_form = form;
-  form.password_issues = absl::nullopt;
-  EXPECT_EQ(UpdateChangeForForm(no_info_form, /*password_changed=*/false,
+  no_info_form.password_issues.reset();
+  EXPECT_EQ(UpdateChangeForForm(form, /*password_changed=*/false,
                                 /*insecure_changed=*/false),
             db().UpdateLogin(no_info_form, nullptr));
   EXPECT_THAT(db().insecure_credentials_table().GetAllRows(),
diff --git a/components/password_manager/core/browser/password_store_change.cc b/components/password_manager/core/browser/password_store_change.cc
index 1ffe955..cb58aa46 100644
--- a/components/password_manager/core/browser/password_store_change.cc
+++ b/components/password_manager/core/browser/password_store_change.cc
@@ -49,7 +49,8 @@
          form().new_password_value == other.form().new_password_value &&
          form().date_last_used == other.form().date_last_used &&
          form().date_created == other.form().date_created &&
-         form().blocked_by_user == other.form().blocked_by_user;
+         form().blocked_by_user == other.form().blocked_by_user &&
+         form().password_issues == other.form().password_issues;
 }
 
 }  // namespace password_manager
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index 7c7e573..858fff4ff 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -331,6 +331,7 @@
   testonly = true
   sources = [
     "junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java",
+    "junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java",
   ]
   deps = [
     ":java",
@@ -338,8 +339,10 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//components/browser_ui/bottomsheet/android:java",
     "//components/payments/content/android:service_java",
     "//components/payments/mojom:mojom_java",
+    "//components/url_formatter/android:url_formatter_java",
     "//content/public/android:content_java",
     "//mojo/public/java:system_java",
     "//third_party/android_deps:material_design_java",
@@ -349,6 +352,7 @@
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
+    "//ui/android:ui_no_recycler_view_java",
     "//url:gurl_java",
     "//url:gurl_junit_test_support",
     "//url:origin_java",
diff --git a/components/payments/content/android/java/res/layout/secure_payment_confirmation_authn_ui.xml b/components/payments/content/android/java/res/layout/secure_payment_confirmation_authn_ui.xml
index e503e30..bf41a82 100644
--- a/components/payments/content/android/java/res/layout/secure_payment_confirmation_authn_ui.xml
+++ b/components/payments/content/android/java/res/layout/secure_payment_confirmation_authn_ui.xml
@@ -10,6 +10,7 @@
 
     <!-- Drag handlebar -->
     <ImageView
+        android:id="@+id/handlebar"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
@@ -20,6 +21,7 @@
 
     <ScrollView
         android:id="@+id/scroll_view"
+        android:layout_below="@id/handlebar"
         android:layout_height="wrap_content"
         android:layout_width="match_parent">
 
@@ -28,7 +30,8 @@
             android:layout_width="match_parent"
             android:textDirection="locale"
             android:paddingHorizontal="@dimen/secure_payment_confirmation_ui_large_padding"
-            android:paddingVertical="@dimen/secure_payment_confirmation_ui_medium_padding">
+            android:paddingTop="@dimen/secure_payment_confirmation_ui_small_padding"
+            android:paddingBottom="@dimen/secure_payment_confirmation_ui_large_padding">
 
             <!-- Shopping cart image -->
             <ImageView
@@ -96,9 +99,9 @@
                 <ImageView
                     android:id="@+id/payment_icon"
                     android:importantForAccessibility="no"
-                    android:layout_height="@dimen/secure_payment_confirmation_ui_medium_padding"
-                    android:layout_width="@dimen/secure_payment_confirmation_ui_medium_padding"
-                    android:scaleType="centerCrop"/>
+                    android:layout_height="@dimen/secure_payment_confirmation_ui_icon_width"
+                    android:layout_width="@dimen/secure_payment_confirmation_ui_icon_height"
+                    android:scaleType="centerInside"/>
 
                 <TextView
                     android:id="@+id/payment"
@@ -153,15 +156,12 @@
                 android:layout_below="@id/total_label"
                 android:layout_marginVertical="@dimen/secure_payment_confirmation_ui_medium_padding"/>
 
-            <!-- TODO(crbug.com/1227823): Clean up spacing between continue and cancel buttons.-->
             <!-- "Continue" button -->
             <org.chromium.ui.widget.ButtonCompat
                 android:id="@+id/continue_button"
                 android:layout_below="@id/total_divider"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
-                android:layout_marginBottom="@dimen/secure_payment_confirmation_ui_button_spacing"
-                android:layout_marginHorizontal="@dimen/secure_payment_confirmation_ui_large_padding"
                 android:text="@string/payments_continue_button"
                 style="@style/FilledButton.Flat"/>
 
@@ -171,8 +171,6 @@
                 android:layout_below="@id/continue_button"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
-                android:layout_marginBottom="@dimen/secure_payment_confirmation_ui_large_padding"
-                android:layout_marginHorizontal="@dimen/secure_payment_confirmation_ui_large_padding"
                 android:text="@string/cancel"
                 style="@style/TextButton"/>
 
diff --git a/components/payments/content/android/java/res/layout/secure_payment_confirmation_enrollment_ui.xml b/components/payments/content/android/java/res/layout/secure_payment_confirmation_enrollment_ui.xml
index 7648043..88ac28256 100644
--- a/components/payments/content/android/java/res/layout/secure_payment_confirmation_enrollment_ui.xml
+++ b/components/payments/content/android/java/res/layout/secure_payment_confirmation_enrollment_ui.xml
@@ -10,24 +10,27 @@
 
     <!-- Drag handlebar -->
     <ImageView
+        android:id="@+id/handlebar"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal"
-        android:paddingTop="@dimen/secure_payment_confirmation_ui_drag_handle_spacing"
+        android:paddingVertical="@dimen/secure_payment_confirmation_ui_drag_handle_spacing"
         android:importantForAccessibility="no"
         android:layout_centerHorizontal="true"
         android:src="@drawable/drag_handlebar" />
 
     <ScrollView
         android:id="@+id/scroll_view"
+        android:layout_below="@id/handlebar"
         android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        >
+        android:layout_width="match_parent">
 
         <RelativeLayout
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:textDirection="locale">
+            android:textDirection="locale"
+            android:paddingTop="@dimen/secure_payment_confirmation_ui_small_padding"
+            android:paddingBottom="@dimen/secure_payment_confirmation_ui_large_padding">
 
             <!-- Shopping cart image -->
             <ImageView
@@ -36,7 +39,7 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:scaleType="centerInside"
-                android:paddingVertical="@dimen/secure_payment_confirmation_ui_medium_padding"/>
+                android:paddingBottom="@dimen/secure_payment_confirmation_ui_medium_padding"/>
 
             <!-- "Check out faster next time" label -->
             <TextView
@@ -74,9 +77,9 @@
                 <ImageView
                     android:id="@+id/payment_icon"
                     android:importantForAccessibility="no"
-                    android:layout_height="@dimen/secure_payment_confirmation_ui_medium_padding"
-                    android:layout_width="@dimen/secure_payment_confirmation_ui_medium_padding"
-                    android:scaleType="centerCrop"/>
+                    android:layout_height="@dimen/secure_payment_confirmation_ui_icon_width"
+                    android:layout_width="@dimen/secure_payment_confirmation_ui_icon_height"
+                    android:scaleType="centerInside"/>
 
                 <TextView
                     android:id="@+id/payment"
@@ -115,7 +118,6 @@
                 android:layout_below="@id/continue_button"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
-                android:layout_marginBottom="@dimen/secure_payment_confirmation_ui_large_padding"
                 android:layout_marginHorizontal="@dimen/secure_payment_confirmation_ui_large_padding"
                 android:text="@string/cancel"
                 style="@style/TextButton"/>
diff --git a/components/payments/content/android/java/res/values/dimens.xml b/components/payments/content/android/java/res/values/dimens.xml
index 4bffaa6..5b46f95 100644
--- a/components/payments/content/android/java/res/values/dimens.xml
+++ b/components/payments/content/android/java/res/values/dimens.xml
@@ -20,13 +20,13 @@
     <dimen name="payments_request_bottom_bar_vertical_padding">10dp</dimen>
     <dimen name="payments_request_bottom_bar_horizontal_padding">16dp</dimen>
 
-    <!-- TODO(crbug.com/1227823): Clean up spacing between continue and cancel buttons.-->
     <!-- Secure Payment Confirmation UI spacing -->
     <dimen name="secure_payment_confirmation_ui_large_padding">24dp</dimen>
     <dimen name="secure_payment_confirmation_ui_medium_padding">16dp</dimen>
     <dimen name="secure_payment_confirmation_ui_small_padding">8dp</dimen>
-    <dimen name="secure_payment_confirmation_ui_button_spacing">12dp</dimen>
     <dimen name="secure_payment_confirmation_ui_drag_handle_spacing">6dp</dimen>
+    <dimen name="secure_payment_confirmation_ui_icon_width">20dp</dimen>
+    <dimen name="secure_payment_confirmation_ui_icon_height">32dp</dimen>
     <dimen name="secure_payment_confirmation_authn_ui_label_size">60dp</dimen>
     <dimen name="secure_payment_confirmation_authn_ui_amount_currency_spacing">4dp</dimen>
 
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
index 0abe591..eccb842b 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -869,8 +869,8 @@
             assert mBrowserPaymentRequest.getSelectedPaymentApp() != null;
             assert mSpcAuthnUiController == null;
 
-            mSpcAuthnUiController = new SecurePaymentConfirmationAuthnController();
-            boolean success = mSpcAuthnUiController.show(mWebContents,
+            mSpcAuthnUiController = SecurePaymentConfirmationAuthnController.create(mWebContents);
+            boolean success = mSpcAuthnUiController.show(
                     mBrowserPaymentRequest.getSelectedPaymentApp().getDrawableIcon(),
                     mBrowserPaymentRequest.getSelectedPaymentApp().getLabel(), getRawTotal(),
                     (response) -> {
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java
index 573abdef..d27ed01 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java
@@ -8,6 +8,8 @@
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
+import androidx.annotation.VisibleForTesting;
+
 import org.chromium.base.Callback;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
@@ -31,6 +33,7 @@
  * component that needs to interact with another component does that through this controller.
  */
 public class SecurePaymentConfirmationAuthnController {
+    private final WebContents mWebContents;
     private Runnable mHider;
     private Callback<Boolean> mResponseCallback;
     private SecurePaymentConfirmationAuthnView mView;
@@ -116,23 +119,33 @@
         }
     };
 
-    /** Constructs the SPC Authn UI component controller. */
-    public SecurePaymentConfirmationAuthnController() {}
+    /**
+     * Constructs the SPC Authn UI component controller.
+     *
+     * @param webContents The WebContents of the merchant.
+     */
+    public static SecurePaymentConfirmationAuthnController create(WebContents webContents) {
+        return webContents != null ? new SecurePaymentConfirmationAuthnController(webContents)
+                                   : null;
+    }
+
+    private SecurePaymentConfirmationAuthnController(WebContents webContents) {
+        mWebContents = webContents;
+    }
 
     /**
      * Shows the SPC Authn UI.
      *
-     * @param webContents The WebContents of the merchant.
      * @param paymentIcon The icon of the payment instrument.
      * @param paymentInstrumentLabel The label to display for the payment instrument.
      * @param total The total amount of the transaction.
      * @param callback The function to call on sheet dismiss; false if it failed.
      */
-    public boolean show(WebContents webContents, Drawable paymentIcon,
-            String paymentInstrumentLabel, PaymentItem total, Callback<Boolean> callback) {
-        if (mHider != null || webContents == null) return false;
+    public boolean show(Drawable paymentIcon, String paymentInstrumentLabel, PaymentItem total,
+            Callback<Boolean> callback) {
+        if (mHider != null) return false;
 
-        WindowAndroid windowAndroid = webContents.getTopLevelNativeWindow();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         if (windowAndroid == null) return false;
         Context context = windowAndroid.getContext().get();
         if (context == null) return false;
@@ -143,7 +156,7 @@
         PropertyModel model =
                 new PropertyModel.Builder(SecurePaymentConfirmationAuthnProperties.ALL_KEYS)
                         .with(SecurePaymentConfirmationAuthnProperties.STORE_ORIGIN,
-                                webContents.getVisibleUrl().getOrigin())
+                                mWebContents.getVisibleUrl().getOrigin())
                         .with(SecurePaymentConfirmationAuthnProperties.PAYMENT_ICON, paymentIcon)
                         .with(SecurePaymentConfirmationAuthnProperties.PAYMENT_INSTRUMENT_LABEL,
                                 paymentInstrumentLabel)
@@ -173,6 +186,7 @@
 
         boolean isShowSuccess =
                 bottomSheet.requestShowContent(mBottomSheetContent, /*animate=*/true);
+
         if (!isShowSuccess) {
             hide();
             return false;
@@ -188,6 +202,16 @@
         mHider = null;
     }
 
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public SecurePaymentConfirmationAuthnView getView() {
+        return mView;
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public boolean isHidden() {
+        return mHider == null;
+    }
+
     private String formatPaymentItem(PaymentItem paymentItem) {
         CurrencyFormatter formatter =
                 new CurrencyFormatter(paymentItem.amount.currency, Locale.getDefault());
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java
new file mode 100644
index 0000000..4c8b3970
--- /dev/null
+++ b/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java
@@ -0,0 +1,246 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.payments.secure_payment_confirmation;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.Callback;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
+import org.chromium.components.payments.CurrencyFormatter;
+import org.chromium.components.payments.CurrencyFormatterJni;
+import org.chromium.components.url_formatter.UrlFormatter;
+import org.chromium.components.url_formatter.UrlFormatterJni;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.payments.mojom.PaymentCurrencyAmount;
+import org.chromium.payments.mojom.PaymentItem;
+import org.chromium.ui.base.WindowAndroid;
+import org.chromium.url.GURL;
+
+import java.lang.ref.WeakReference;
+
+/** A test for SecurePaymentConfirmationAuthn. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE,
+        shadows = {SecurePaymentConfirmationAuthnTest.ShadowBottomSheetControllerProvider.class})
+public class SecurePaymentConfirmationAuthnTest {
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.WARN);
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private WebContents mWebContents;
+
+    private boolean mIsPaymentConfirmed;
+    private boolean mIsPaymentCancelled;
+    private Callback<Boolean> mCallback;
+
+    private PaymentItem mTotal;
+    private Drawable mDrawable;
+    private SecurePaymentConfirmationAuthnController mAuthnController;
+
+    /** The shadow of BottomSheetControllerProvider. Not to use outside the test. */
+    @Implements(BottomSheetControllerProvider.class)
+    /* package */ static class ShadowBottomSheetControllerProvider {
+        private static BottomSheetController sBottomSheetController;
+
+        @Implementation
+        public static BottomSheetController from(WindowAndroid windowAndroid) {
+            return sBottomSheetController;
+        }
+
+        private static void setBottomSheetController(BottomSheetController controller) {
+            sBottomSheetController = controller;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        WindowAndroid windowAndroid = Mockito.mock(WindowAndroid.class);
+        setWindowAndroid(windowAndroid, mWebContents);
+        Mockito.doReturn(new WeakReference<Context>(RuntimeEnvironment.application))
+                .when(windowAndroid)
+                .getContext();
+        Mockito.when(mWebContents.getVisibleUrl().getOrigin()).thenReturn(GURL.emptyGURL());
+
+        // Create formatter mocks
+        UrlFormatter.Natives urlFormatterJniMock = Mockito.mock(UrlFormatter.Natives.class);
+        CurrencyFormatter.Natives currencyFormatterJniMock =
+                Mockito.mock(CurrencyFormatter.Natives.class);
+        mJniMocker.mock(UrlFormatterJni.TEST_HOOKS, urlFormatterJniMock);
+        mJniMocker.mock(CurrencyFormatterJni.TEST_HOOKS, currencyFormatterJniMock);
+        Mockito.doReturn("example.com")
+                .when(urlFormatterJniMock)
+                .formatUrlForDisplayOmitScheme(Mockito.anyString());
+        Mockito.doReturn("$1.00")
+                .when(currencyFormatterJniMock)
+                .format(Mockito.anyLong(), Mockito.any(CurrencyFormatter.class),
+                        Mockito.anyString());
+
+        mDrawable = Mockito.mock(Drawable.class);
+        mTotal = new PaymentItem();
+        mTotal.amount = new PaymentCurrencyAmount();
+        mTotal.amount.currency = "USD";
+        mTotal.amount.value = "1.00";
+        mCallback = (response) -> {
+            if (response) {
+                mIsPaymentConfirmed = true;
+            } else {
+                mIsPaymentCancelled = true;
+            }
+        };
+
+        ShadowBottomSheetControllerProvider.setBottomSheetController(
+                createBottomSheetController(/*requestShowContentResponse=*/true));
+    }
+
+    @After
+    public void tearDown() {
+        if (mAuthnController != null) mAuthnController.hide();
+    }
+
+    private void createAuthnController() {
+        mAuthnController = SecurePaymentConfirmationAuthnController.create(mWebContents);
+    }
+
+    private BottomSheetController createBottomSheetController(boolean requestShowContentResponse) {
+        BottomSheetController controller = Mockito.mock(BottomSheetController.class);
+        Mockito.doReturn(requestShowContentResponse)
+                .when(controller)
+                .requestShowContent(Mockito.any(BottomSheetContent.class), Mockito.anyBoolean());
+        return controller;
+    }
+
+    private boolean show() {
+        if (mAuthnController == null) return false;
+
+        mIsPaymentConfirmed = false;
+        mIsPaymentCancelled = false;
+        return mAuthnController.show(mDrawable, "paymentInstrumentLabel", mTotal, mCallback);
+    }
+
+    private void setWindowAndroid(WindowAndroid windowAndroid, WebContents webContents) {
+        Mockito.doReturn(windowAndroid).when(webContents).getTopLevelNativeWindow();
+    }
+
+    private void setContext(Context context) {
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
+        Mockito.doReturn(new WeakReference<Context>(context)).when(windowAndroid).getContext();
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testOnAuthnConfirmation() {
+        createAuthnController();
+        show();
+        mAuthnController.getView().mContinueButton.performClick();
+        Assert.assertTrue(mIsPaymentConfirmed);
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testOnAuthnCancellation() {
+        createAuthnController();
+        show();
+        mAuthnController.getView().mCancelButton.performClick();
+        Assert.assertTrue(mIsPaymentCancelled);
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testHide() {
+        createAuthnController();
+        show();
+        mAuthnController.hide();
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testRequestShowContentFalse() {
+        createAuthnController();
+        ShadowBottomSheetControllerProvider.setBottomSheetController(
+                createBottomSheetController(/*requestShowContentResponse=*/false));
+        Assert.assertFalse(show());
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testCreateWithNullWebContents() {
+        mWebContents = null;
+        createAuthnController();
+        Assert.assertNull(mAuthnController);
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testShowWithNullWindowAndroid() {
+        setWindowAndroid(null, mWebContents);
+        createAuthnController();
+        Assert.assertFalse(show());
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testShowWithNullContext() {
+        setContext(null);
+        createAuthnController();
+        Assert.assertFalse(show());
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testShowWithNullBottomSheetController() {
+        ShadowBottomSheetControllerProvider.setBottomSheetController(null);
+        createAuthnController();
+        Assert.assertFalse(show());
+        Assert.assertTrue(mAuthnController.isHidden());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testShowTwiceWithHide() {
+        createAuthnController();
+        Assert.assertTrue(show());
+        mAuthnController.hide();
+        Assert.assertTrue(show());
+    }
+
+    @Test
+    @Feature({"Payments"})
+    public void testShowTwiceWithoutHide() {
+        createAuthnController();
+        Assert.assertTrue(show());
+        Assert.assertFalse(show());
+    }
+}
diff --git a/components/pdf/browser/pdf_navigation_throttle.cc b/components/pdf/browser/pdf_navigation_throttle.cc
index 6e188dce..49e54c6 100644
--- a/components/pdf/browser/pdf_navigation_throttle.cc
+++ b/components/pdf/browser/pdf_navigation_throttle.cc
@@ -45,6 +45,10 @@
     // `WebContents::OpenURL()`, so use `LoadURLWithParams()` directly instead.
     web_contents_->GetController().LoadURLWithParams(
         content::NavigationController::LoadURLParams(params));
+
+    // Note that we don't need to register the stream's URL loader as a
+    // subresource, as `MimeHandlerViewGuest::ReadyToCommitNavigation()` will
+    // handle this as soon as we navigate to a non-`kPdfExtensionId` URL.
   }
 
  private:
diff --git a/components/pdf/browser/pdf_url_loader_request_interceptor.cc b/components/pdf/browser/pdf_url_loader_request_interceptor.cc
index 4b82657..acb259b 100644
--- a/components/pdf/browser/pdf_url_loader_request_interceptor.cc
+++ b/components/pdf/browser/pdf_url_loader_request_interceptor.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "components/pdf/browser/pdf_stream_delegate.h"
+#include "components/pdf/browser/plugin_response_writer.h"
 #include "content/public/browser/url_loader_request_interceptor.h"
 #include "content/public/browser/web_contents.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -19,17 +20,28 @@
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "services/network/public/mojom/url_loader.mojom-forward.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
 
 namespace pdf {
 
 namespace {
 
+void FinishLoader(std::unique_ptr<PluginResponseWriter> /*response_writer*/) {
+  // Implicitly deletes `PluginResponseWriter` after loading completes.
+}
+
 void CreateLoaderAndStart(
-    PdfStreamDelegate::StreamInfo stream,
+    const GURL& source_url,
+    const GURL& original_url,
     const network::ResourceRequest& request,
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
-  // TODO(crbug.com/1123621): Synthesize response body.
+  auto response_writer = std::make_unique<PluginResponseWriter>(
+      source_url, original_url, std::move(client));
+
+  auto* unowned_response_writer = response_writer.get();
+  unowned_response_writer->Start(
+      base::BindOnce(FinishLoader, std::move(response_writer)));
 }
 
 }  // namespace
@@ -87,7 +99,8 @@
   if (tentative_resource_request.url != stream->original_url)
     return {};
 
-  return base::BindOnce(&CreateLoaderAndStart, std::move(stream.value()));
+  return base::BindOnce(&CreateLoaderAndStart, std::move(stream->stream_url),
+                        std::move(stream->original_url));
 }
 
 }  // namespace pdf
diff --git a/components/pdf/browser/pdf_url_loader_request_interceptor_unittest.cc b/components/pdf/browser/pdf_url_loader_request_interceptor_unittest.cc
index 5086960..1354095 100644
--- a/components/pdf/browser/pdf_url_loader_request_interceptor_unittest.cc
+++ b/components/pdf/browser/pdf_url_loader_request_interceptor_unittest.cc
@@ -7,15 +7,20 @@
 #include <memory>
 #include <utility>
 
+#include "base/run_loop.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/pdf/browser/fake_pdf_stream_delegate.h"
+#include "components/pdf/browser/mock_url_loader_client.h"
 #include "components/pdf/browser/pdf_stream_delegate.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
 #include "content/public/test/test_renderer_host.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "pdf/pdf_features.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -24,6 +29,8 @@
 
 namespace {
 
+using ::testing::NiceMock;
+
 class PdfURLLoaderRequestInterceptorTest
     : public content::RenderViewHostTestHarness {
  protected:
@@ -63,6 +70,22 @@
   }
 };
 
+void RunRequestHandler(
+    content::URLLoaderRequestInterceptor::RequestHandler request_handler) {
+  base::RunLoop run_loop;
+
+  NiceMock<MockURLLoaderClient> mock_client;
+  EXPECT_CALL(mock_client, OnReceiveResponse).WillOnce([&run_loop]() {
+    run_loop.Quit();
+  });
+
+  mojo::Receiver<network::mojom::URLLoaderClient> client_receiver(&mock_client);
+  std::move(request_handler)
+      .Run({}, {}, client_receiver.BindNewPipeAndPassRemote());
+
+  run_loop.Run();
+}
+
 }  // namespace
 
 TEST_F(PdfURLLoaderRequestInterceptorUnseasonedDisabledTest,
@@ -78,7 +101,8 @@
 }
 
 TEST_F(PdfURLLoaderRequestInterceptorTest, MaybeCreateLoader) {
-  EXPECT_CALL(loader_callback_, Run(base::test::IsNotNullCallback()));
+  EXPECT_CALL(loader_callback_, Run(base::test::IsNotNullCallback()))
+      .WillOnce(RunRequestHandler);
 
   auto interceptor = CreateInterceptor();
   interceptor->MaybeCreateLoader(resource_request_, browser_context(),
diff --git a/components/pdf/browser/plugin_response_writer.cc b/components/pdf/browser/plugin_response_writer.cc
index 073258f..fb72c4f 100644
--- a/components/pdf/browser/plugin_response_writer.cc
+++ b/components/pdf/browser/plugin_response_writer.cc
@@ -10,7 +10,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/strings/strcat.h"
+#include "base/strings/string_util.h"
 #include "mojo/public/c/system/types.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/system/data_pipe.h"
@@ -27,11 +27,38 @@
 namespace {
 
 std::string GenerateResponse(const GURL& source_url, const GURL& original_url) {
-  return base::StrCat({R"(<!DOCTYPE html>
-<html style="height:100%; width:100%">
-<embed type="application/x-google-chrome-pdf" width="100%" height="100%")",
-                       " src=\"", source_url.spec(), "\" original-url=\"",
-                       original_url.spec(), "\">"});
+  // TODO(crbug.com/1228987): This script in this response is never executed
+  // when JavaScript is blocked throughout the browser (set in
+  // chrome://settings/content/javascript). A permanent solution would likely
+  // have to hook into postMessage() natively.
+  static constexpr char kResponseTemplate[] = R"(<!DOCTYPE html>
+<style>
+body,
+embed,
+html {
+  height: 100%;
+  margin: 0;
+  width: 100%;
+}
+</style>
+<embed type="application/x-google-chrome-pdf" src="$1" original-url="$2">
+<script>
+const channel = new MessageChannel();
+const plugin = document.querySelector('embed');
+
+plugin.addEventListener('message', e => channel.port1.postMessage(e.data));
+channel.port1.onmessage = e => plugin.postMessage(e.data);
+
+window.parent.postMessage(
+    {type: 'connect', token: plugin.getAttribute('src')}, '$3',
+    [channel.port2]);
+</script>
+)";
+
+  return base::ReplaceStringPlaceholders(
+      kResponseTemplate,
+      {source_url.spec(), original_url.spec(), source_url.GetOrigin().spec()},
+      /*offsets=*/nullptr);
 }
 
 }  // namespace
diff --git a/components/pdf/browser/plugin_response_writer_unittest.cc b/components/pdf/browser/plugin_response_writer_unittest.cc
index 04fdf27..efb23d6 100644
--- a/components/pdf/browser/plugin_response_writer_unittest.cc
+++ b/components/pdf/browser/plugin_response_writer_unittest.cc
@@ -143,6 +143,7 @@
               HasSubstr("src=\"chrome-extension://id/stream-url\""));
   EXPECT_THAT(body_drainer_->content(),
               HasSubstr("original-url=\"https://example.test/fake.pdf\""));
+  EXPECT_THAT(body_drainer_->content(), HasSubstr("'chrome-extension://id/'"));
 }
 
 TEST_F(PluginResponseWriterTest, StartWithUnescapedUrls) {
@@ -166,6 +167,31 @@
               HasSubstr("src=\"chrome-extension://id/stream-url%22\""));
   EXPECT_THAT(body_drainer_->content(),
               HasSubstr("original-url=\"https://example.test/%22fake.pdf\""));
+  EXPECT_THAT(body_drainer_->content(), HasSubstr("'chrome-extension://id/'"));
+}
+
+TEST_F(PluginResponseWriterTest, StartForPrintPreview) {
+  auto response_writer =
+      NewPluginResponseWriter(GURL("chrome://print/1/0/print.pdf"),
+                              GURL("chrome://print/1/0/print.pdf"));
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(mock_client_, OnComplete).WillOnce([&run_loop]() {
+    run_loop.Quit();
+  });
+  response_writer->Start(base::DoNothing());
+  run_loop.Run();
+
+  // Waiting for `URLLoaderClient::OnComplete()` ensures `body_drainer_` is set,
+  // but the data pipe may still have unread data.
+  ASSERT_TRUE(body_drainer_);
+  body_drainer_->WaitComplete();
+
+  EXPECT_THAT(body_drainer_->content(),
+              HasSubstr("src=\"chrome://print/1/0/print.pdf\""));
+  EXPECT_THAT(body_drainer_->content(),
+              HasSubstr("original-url=\"chrome://print/1/0/print.pdf\""));
+  EXPECT_THAT(body_drainer_->content(), HasSubstr("'chrome://print/'"));
 }
 
 }  // namespace pdf
diff --git a/components/performance_manager/mechanisms/tab_loading_frame_navigation_scheduler_browsertest.cc b/components/performance_manager/mechanisms/tab_loading_frame_navigation_scheduler_browsertest.cc
index bd25fcb6..7649e9db 100644
--- a/components/performance_manager/mechanisms/tab_loading_frame_navigation_scheduler_browsertest.cc
+++ b/components/performance_manager/mechanisms/tab_loading_frame_navigation_scheduler_browsertest.cc
@@ -125,9 +125,8 @@
 
 }  // namespace
 
-// TODO(crbug.com/1121748): Test is flaky.
 IN_PROC_BROWSER_TEST_F(TabLoadingFrameNavigationSchedulerTest,
-                       DISABLED_ThrottlingDisabled) {
+                       ThrottlingDisabled) {
   GURL url(embedded_test_server()->GetURL("a.com", "/a.html"));
   auto* contents = shell()->web_contents();
 
@@ -217,9 +216,8 @@
   WaitForLoad(contents2);
 }
 
-// TODO(crbug.com/1121748): Test is flaky.
 IN_PROC_BROWSER_TEST_F(TabLoadingFrameNavigationSchedulerTest,
-                       DISABLED_ChildFrameThrottled) {
+                       ChildFrameThrottled) {
   GURL url(embedded_test_server()->GetURL("a.com", "/a_embeds_b.html"));
   auto* contents = shell()->web_contents();
 
@@ -325,9 +323,8 @@
   WaitForLoad(contents);
 }
 
-// TODO(crbug.com/1121748): Test is flaky.
 IN_PROC_BROWSER_TEST_F(TabLoadingFrameNavigationSchedulerTest,
-                       DISABLED_NavigationInterruptsThrottling) {
+                       NavigationInterruptsThrottling) {
   GURL url(embedded_test_server()->GetURL("a.com", "/a_embeds_b.html"));
   auto* contents = shell()->web_contents();
 
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc
index bec58c7..3548f75 100644
--- a/components/permissions/permission_manager.cc
+++ b/components/permissions/permission_manager.cc
@@ -393,6 +393,28 @@
   }
 }
 
+void PermissionManager::RequestPermissionFromCurrentDocument(
+    ContentSettingsType content_settings_type,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(ContentSetting)> callback) {
+  RequestPermissionsFromCurrentDocument(
+      std::vector<ContentSettingsType>(1, content_settings_type),
+      render_frame_host, user_gesture,
+      base::BindOnce(&ContentSettingCallbackWrapper, std::move(callback)));
+}
+
+void PermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<ContentSettingsType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<ContentSetting>&)> callback) {
+  RequestPermissions(
+      permissions, render_frame_host,
+      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host),
+      user_gesture, std::move(callback));
+}
+
 PermissionResult PermissionManager::GetPermissionStatus(
     ContentSettingsType permission,
     const GURL& requesting_origin,
@@ -419,6 +441,14 @@
                                    requesting_origin, embedding_origin);
 }
 
+PermissionResult PermissionManager::GetPermissionStatusForCurrentDocument(
+    ContentSettingsType permission,
+    content::RenderFrameHost* render_frame_host) {
+  GURL origin = PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host);
+  return GetPermissionStatusHelper(permission, render_frame_host, origin,
+                                   origin);
+}
+
 void PermissionManager::RequestPermission(
     PermissionType permission,
     content::RenderFrameHost* render_frame_host,
diff --git a/components/permissions/permission_manager.h b/components/permissions/permission_manager.h
index 7c5db7c..6f0faad 100644
--- a/components/permissions/permission_manager.h
+++ b/components/permissions/permission_manager.h
@@ -61,18 +61,32 @@
   // ContentSettingsType enum. The methods which take PermissionType values
   // are for the content::PermissionControllerDelegate overrides and shouldn't
   // be used from chrome/.
-
+  // Deprecated. Use `RequestPermissionFromCurrentDocument` instead.
   void RequestPermission(ContentSettingsType permission,
                          content::RenderFrameHost* render_frame_host,
                          const GURL& requesting_origin,
                          bool user_gesture,
                          base::OnceCallback<void(ContentSetting)> callback);
+  // Deprecated. Use `RequestPermissionsFromCurrentDocument` instead.
   void RequestPermissions(
       const std::vector<ContentSettingsType>& permissions,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       bool user_gesture,
       base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
+  void RequestPermissionFromCurrentDocument(
+      ContentSettingsType permission,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<void(ContentSetting)> callback);
+  // Requests the given `permission` on behalf of the last committed document in
+  // `render_frame_host`, also performing additional checks such as Permission
+  // Policy.
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<ContentSettingsType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
 
   PermissionResult GetPermissionStatus(ContentSettingsType permission,
                                        const GURL& requesting_origin,
@@ -84,11 +98,19 @@
   // TODO(raymes): Currently we still pass the |requesting_origin| as a separate
   // parameter because we can't yet guarantee that it matches the last committed
   // origin of the RenderFrameHost. See crbug.com/698985.
+  // Deprecated. Use `GetPermissionStatusForCurrentDocument` instead.
   PermissionResult GetPermissionStatusForFrame(
       ContentSettingsType permission,
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin);
 
+  // Returns the status for the given `permission` on behalf of the last
+  // committed document in `render_frame_host`, also performing additional
+  // checks such as Permission Policy.
+  PermissionResult GetPermissionStatusForCurrentDocument(
+      ContentSettingsType permission,
+      content::RenderFrameHost* render_frame_host);
+
   // content::PermissionControllerDelegate implementation.
   void RequestPermission(
       content::PermissionType permission,
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc
index eabe1fa..4e48b0f 100644
--- a/components/permissions/permission_util.cc
+++ b/components/permissions/permission_util.cc
@@ -252,13 +252,19 @@
 GURL PermissionUtil::GetLastCommittedOriginAsURL(
     content::WebContents* web_contents) {
   DCHECK(web_contents);
+  return GetLastCommittedOriginAsURL(web_contents->GetMainFrame());
+}
+
+GURL PermissionUtil::GetLastCommittedOriginAsURL(
+    content::RenderFrameHost* render_frame_host) {
+  DCHECK(render_frame_host);
   if (base::FeatureList::IsEnabled(features::kRevisedOriginHandling)) {
-    if (web_contents->GetLastCommittedURL().IsAboutBlank()) {
-      return web_contents->GetMainFrame()->GetLastCommittedOrigin().GetURL();
+    if (render_frame_host->GetLastCommittedURL().IsAboutBlank()) {
+      return render_frame_host->GetLastCommittedOrigin().GetURL();
     }
   }
 
-  return web_contents->GetLastCommittedURL().GetOrigin();
+  return render_frame_host->GetLastCommittedURL().GetOrigin();
 }
 
 }  // namespace permissions
diff --git a/components/permissions/permission_util.h b/components/permissions/permission_util.h
index e107fd8..5e2603e 100644
--- a/components/permissions/permission_util.h
+++ b/components/permissions/permission_util.h
@@ -16,6 +16,7 @@
 namespace content {
 enum class PermissionType;
 class WebContents;
+class RenderFrameHost;
 }  // namespace content
 
 class GURL;
@@ -72,6 +73,8 @@
   // ultimately all call sites should be migrated to determine the authoritative
   // security origin based on the requesting RenderFrameHost.
   static GURL GetLastCommittedOriginAsURL(content::WebContents* web_contents);
+  static GURL GetLastCommittedOriginAsURL(
+      content::RenderFrameHost* render_frame_host);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionUtil);
diff --git a/components/policy/core/browser/android/policy_cache_updater_android_unittest.cc b/components/policy/core/browser/android/policy_cache_updater_android_unittest.cc
index 83d86c0c..851b097 100644
--- a/components/policy/core/browser/android/policy_cache_updater_android_unittest.cc
+++ b/components/policy/core/browser/android/policy_cache_updater_android_unittest.cc
@@ -62,10 +62,9 @@
 class PolicyCacheUpdaterAndroidTest : public ::testing::Test {
  public:
   PolicyCacheUpdaterAndroidTest() {
-    ON_CALL(policy_provider_, IsInitializationComplete(_))
-        .WillByDefault(Return(true));
-    ON_CALL(policy_provider_, IsFirstPolicyLoadComplete(_))
-        .WillByDefault(Return(true));
+    policy_provider_.SetDefaultReturns(
+        true /* is_initialization_complete_return */,
+        true /* is_first_policy_load_complete_return */);
     j_support_ = Java_PolicyCacheUpdaterTestSupporter_Constructor(env_);
     policy_service_ = std::make_unique<policy::PolicyServiceImpl>(
         std::vector<ConfigurationPolicyProvider*>({&policy_provider_}));
@@ -107,7 +106,7 @@
   JNIEnv* env_ = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> j_support_;
   PolicyMap policy_map_;
-  MockConfigurationPolicyProvider policy_provider_;
+  testing::NiceMock<MockConfigurationPolicyProvider> policy_provider_;
   std::unique_ptr<PolicyService> policy_service_;
   std::unique_ptr<ConfigurationPolicyHandlerList> policy_handler_list_;
   base::test::SingleThreadTaskEnvironment task_environment_;
diff --git a/components/policy/core/browser/configuration_policy_pref_store_test.cc b/components/policy/core/browser/configuration_policy_pref_store_test.cc
index 4d51266..340d117 100644
--- a/components/policy/core/browser/configuration_policy_pref_store_test.cc
+++ b/components/policy/core/browser/configuration_policy_pref_store_test.cc
@@ -27,10 +27,10 @@
                                         base::Unretained(this)),
                     GetChromePolicyDetailsCallback(),
                     /* allow_all_future_policies*/ true) {
+  provider_.SetDefaultReturns(false /* is_initialization_complete_return */,
+                              false /* is_first_policy_load_complete_return */);
   EXPECT_CALL(provider_, IsInitializationComplete(_))
       .WillRepeatedly(Return(false));
-  ON_CALL(provider_, IsFirstPolicyLoadComplete(_)).WillByDefault(Return(false));
-
   provider_.Init();
   providers_.push_back(&provider_);
   policy_service_ = std::make_unique<PolicyServiceImpl>(providers_);
diff --git a/components/policy/core/common/cloud/cloud_policy_store.cc b/components/policy/core/common/cloud/cloud_policy_store.cc
index f06b8df..e7a260f9 100644
--- a/components/policy/core/common/cloud/cloud_policy_store.cc
+++ b/components/policy/core/common/cloud/cloud_policy_store.cc
@@ -83,13 +83,6 @@
     external_data_manager_->OnPolicyStoreLoaded();
 }
 
-void CloudPolicyStore::SetPolicyMapForTesting(const PolicyMap& policy_map) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  policy_map_ = policy_map.Clone();
-  NotifyStoreLoaded();
-}
-
 void CloudPolicyStore::SetFirstPoliciesLoaded(bool loaded) {
   first_policies_loaded_ = loaded;
 }
diff --git a/components/policy/core/common/cloud/cloud_policy_store.h b/components/policy/core/common/cloud/cloud_policy_store.h
index 25b1e1e..8d85d9f 100644
--- a/components/policy/core/common/cloud/cloud_policy_store.h
+++ b/components/policy/core/common/cloud/cloud_policy_store.h
@@ -150,14 +150,6 @@
   void SetExternalDataManager(
       base::WeakPtr<CloudExternalDataManager> external_data_manager);
 
-  // Replaces |policy_map_| and calls the registered observers, simulating a
-  // successful load of |policy_map| from persistent storage.
-  // TODO(bartfab): This override is only needed because there are no policies
-  // that reference external data and therefore, no ExternalDataFetchers in the
-  // |policy_map_|. Once the first such policy is added, use that policy in
-  // tests and remove the override.
-  void SetPolicyMapForTesting(const PolicyMap& policy_map);
-
   // Sets whether or not the first policies for this policy store were loaded.
   void SetFirstPoliciesLoaded(bool loaded);
 
diff --git a/components/policy/core/common/management/platform_management_service.cc b/components/policy/core/common/management/platform_management_service.cc
index 13f2c009..c060226 100644
--- a/components/policy/core/common/management/platform_management_service.cc
+++ b/components/policy/core/common/management/platform_management_service.cc
@@ -4,7 +4,9 @@
 
 #include "components/policy/core/common/management/platform_management_service.h"
 
+#include "base/no_destructor.h"
 #include "build/build_config.h"
+
 #if defined(OS_WIN)
 #include "components/policy/core/common/management/platform_management_status_provider_win.h"
 #endif
diff --git a/components/policy/core/common/management/platform_management_service.h b/components/policy/core/common/management/platform_management_service.h
index c0a73d3..31f812d 100644
--- a/components/policy/core/common/management/platform_management_service.h
+++ b/components/policy/core/common/management/platform_management_service.h
@@ -5,7 +5,6 @@
 #ifndef COMPONENTS_POLICY_CORE_COMMON_MANAGEMENT_PLATFORM_MANAGEMENT_SERVICE_H_
 #define COMPONENTS_POLICY_CORE_COMMON_MANAGEMENT_PLATFORM_MANAGEMENT_SERVICE_H_
 
-#include "base/no_destructor.h"
 #include "components/policy/core/common/management/management_service.h"
 #include "components/policy/policy_export.h"
 
diff --git a/components/policy/core/common/mock_configuration_policy_provider.h b/components/policy/core/common/mock_configuration_policy_provider.h
index ebba2345..2f3af6c 100644
--- a/components/policy/core/common/mock_configuration_policy_provider.h
+++ b/components/policy/core/common/mock_configuration_policy_provider.h
@@ -50,6 +50,15 @@
     ConfigurationPolicyProvider::Init(&registry_);
   }
 
+  // Utility testing method used to set up boilerplate |ON_CALL| defaults.
+  void SetDefaultReturns(bool is_initialization_complete_return,
+                         bool is_first_policy_load_complete_return) {
+    ON_CALL(*this, IsInitializationComplete(testing::_))
+        .WillByDefault(testing::Return(is_initialization_complete_return));
+    ON_CALL(*this, IsFirstPolicyLoadComplete(testing::_))
+        .WillByDefault(testing::Return(is_first_policy_load_complete_return));
+  }
+
   // Convenience method that installs an expectation on RefreshPolicies that
   // just notifies the observers and serves the same policies.
   void SetAutoRefresh();
diff --git a/components/policy/core/common/policy_loader_win.cc b/components/policy/core/common/policy_loader_win.cc
index cbf9209..d895ae0 100644
--- a/components/policy/core/common/policy_loader_win.cc
+++ b/components/policy/core/common/policy_loader_win.cc
@@ -245,6 +245,13 @@
 }
 
 PolicyLoaderWin::~PolicyLoaderWin() {
+  // Mitigate the issues caused by loading DLLs or lazily resolving symbols on a
+  // background thread (http://crbug/973868) which can hold the process wide
+  // LoaderLock and cause contention on Foreground threads. This issue is solved
+  // on Windows version after Win7. This code can be removed when Win7 is no
+  // longer supported.
+  SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
   if (!user_policy_watcher_failed_) {
     ::UnregisterGPNotification(user_policy_changed_event_.handle());
     user_policy_watcher_.StopWatching();
diff --git a/components/power_scheduler/power_mode_arbiter.h b/components/power_scheduler/power_mode_arbiter.h
index 840c7ff4..132bef3 100644
--- a/components/power_scheduler/power_mode_arbiter.h
+++ b/components/power_scheduler/power_mode_arbiter.h
@@ -11,7 +11,6 @@
 #include "base/component_export.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/no_destructor.h"
 #include "base/observer_list_threadsafe.h"
 #include "base/synchronization/lock.h"
 #include "base/task_runner.h"
diff --git a/components/reporting/util/shared_queue.h b/components/reporting/util/shared_queue.h
index 923b2e7..1c6a369 100644
--- a/components/reporting/util/shared_queue.h
+++ b/components/reporting/util/shared_queue.h
@@ -22,9 +22,9 @@
 template <typename QueueType>
 class SharedQueue : public base::RefCountedThreadSafe<SharedQueue<QueueType>> {
  public:
-  static scoped_refptr<SharedQueue<QueueType>> Create() {
-    scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner{
-        base::ThreadPool::CreateSequencedTaskRunner({})};
+  static scoped_refptr<SharedQueue<QueueType>> Create(
+      scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
+          base::ThreadPool::CreateSequencedTaskRunner({})) {
     return base::WrapRefCounted(
         new SharedQueue<QueueType>(sequenced_task_runner));
   }
diff --git a/components/sync/driver/glue/sync_transport_data_prefs.cc b/components/sync/driver/glue/sync_transport_data_prefs.cc
index 9aa9032..6f26da3 100644
--- a/components/sync/driver/glue/sync_transport_data_prefs.cc
+++ b/components/sync/driver/glue/sync_transport_data_prefs.cc
@@ -54,9 +54,9 @@
   registry->RegisterStringPref(kSyncCacheGuid, std::string());
   registry->RegisterStringPref(kSyncBirthday, std::string());
   registry->RegisterStringPref(kSyncBagOfChips, std::string());
-  registry->RegisterInt64Pref(kSyncLastSyncedTime, 0);
-  registry->RegisterInt64Pref(kSyncLastPollTime, 0);
-  registry->RegisterInt64Pref(kSyncPollIntervalSeconds, 0);
+  registry->RegisterTimePref(kSyncLastSyncedTime, base::Time());
+  registry->RegisterTimePref(kSyncLastPollTime, base::Time());
+  registry->RegisterTimeDeltaPref(kSyncPollIntervalSeconds, base::TimeDelta());
   registry->RegisterStringPref(kSyncKeystoreEncryptionBootstrapToken,
                                std::string());
   registry->RegisterDictionaryPref(kSyncInvalidationVersions);
@@ -78,39 +78,32 @@
 
 base::Time SyncTransportDataPrefs::GetLastSyncedTime() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return base::Time::FromDeltaSinceWindowsEpoch(
-      base::TimeDelta::FromMicroseconds(
-          pref_service_->GetInt64(kSyncLastSyncedTime)));
+  return pref_service_->GetTime(kSyncLastSyncedTime);
 }
 
 void SyncTransportDataPrefs::SetLastSyncedTime(base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  pref_service_->SetInt64(kSyncLastSyncedTime,
-                          time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+  pref_service_->SetTime(kSyncLastSyncedTime, time);
 }
 
 base::Time SyncTransportDataPrefs::GetLastPollTime() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return base::Time::FromDeltaSinceWindowsEpoch(
-      base::TimeDelta::FromMicroseconds(
-          pref_service_->GetInt64(kSyncLastPollTime)));
+  return pref_service_->GetTime(kSyncLastPollTime);
 }
 
 void SyncTransportDataPrefs::SetLastPollTime(base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  pref_service_->SetInt64(kSyncLastPollTime,
-                          time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+  pref_service_->SetTime(kSyncLastPollTime, time);
 }
 
 base::TimeDelta SyncTransportDataPrefs::GetPollInterval() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return base::TimeDelta::FromSeconds(
-      pref_service_->GetInt64(kSyncPollIntervalSeconds));
+  return pref_service_->GetTimeDelta(kSyncPollIntervalSeconds);
 }
 
 void SyncTransportDataPrefs::SetPollInterval(base::TimeDelta interval) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  pref_service_->SetInt64(kSyncPollIntervalSeconds, interval.InSeconds());
+  pref_service_->SetTimeDelta(kSyncPollIntervalSeconds, interval);
 }
 
 std::string SyncTransportDataPrefs::GetKeystoreEncryptionBootstrapToken()
diff --git a/components/sync/trusted_vault/download_keys_response_handler.cc b/components/sync/trusted_vault/download_keys_response_handler.cc
index 186976e..55121f6 100644
--- a/components/sync/trusted_vault/download_keys_response_handler.cc
+++ b/components/sync/trusted_vault/download_keys_response_handler.cc
@@ -160,7 +160,7 @@
       return ProcessedResponse(
           /*status=*/TrustedVaultDownloadKeysStatus::
               kMemberNotFoundOrCorrupted);
-    case TrustedVaultRequest::HttpStatus::kFailedPrecondition:
+    case TrustedVaultRequest::HttpStatus::kBadRequest:
     case TrustedVaultRequest::HttpStatus::kOtherError:
       return ProcessedResponse(
           /*status=*/TrustedVaultDownloadKeysStatus::kOtherError);
diff --git a/components/sync/trusted_vault/download_keys_response_handler_unittest.cc b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
index ede07dd..102e7da 100644
--- a/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
+++ b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
@@ -108,13 +108,13 @@
               /*response_body=*/std::string())
           .status,
       Eq(TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted));
-  EXPECT_THAT(handler()
-                  .ProcessResponse(
-                      /*http_status=*/TrustedVaultRequest::HttpStatus::
-                          kFailedPrecondition,
-                      /*response_body=*/std::string())
-                  .status,
-              Eq(TrustedVaultDownloadKeysStatus::kOtherError));
+  EXPECT_THAT(
+      handler()
+          .ProcessResponse(
+              /*http_status=*/TrustedVaultRequest::HttpStatus::kBadRequest,
+              /*response_body=*/std::string())
+          .status,
+      Eq(TrustedVaultDownloadKeysStatus::kOtherError));
   EXPECT_THAT(
       handler()
           .ProcessResponse(
diff --git a/components/sync/trusted_vault/fake_security_domains_server.cc b/components/sync/trusted_vault/fake_security_domains_server.cc
index 0e0fab9..b11a6f9 100644
--- a/components/sync/trusted_vault/fake_security_domains_server.cc
+++ b/components/sync/trusted_vault/fake_security_domains_server.cc
@@ -305,7 +305,7 @@
   if (state_.public_key_to_shared_keys.count(member.public_key()) != 0) {
     // Member already exists.
     auto response = std::make_unique<net::test_server::BasicHttpResponse>();
-    response->set_code(net::HTTP_PRECONDITION_FAILED);
+    response->set_code(net::HTTP_BAD_REQUEST);
     return response;
   }
 
@@ -314,7 +314,7 @@
   if (last_shared_key.epoch() != 0 &&
       last_shared_key.epoch() != state_.current_epoch) {
     auto response = std::make_unique<net::test_server::BasicHttpResponse>();
-    response->set_code(net::HTTP_PRECONDITION_FAILED);
+    response->set_code(net::HTTP_BAD_REQUEST);
     return response;
   }
 
@@ -338,7 +338,7 @@
     // Either constant key is not allowed, or request uses the real key without
     // populating the epoch.
     auto response = std::make_unique<net::test_server::BasicHttpResponse>();
-    response->set_code(net::HTTP_PRECONDITION_FAILED);
+    response->set_code(net::HTTP_BAD_REQUEST);
     return response;
   }
 
diff --git a/components/sync/trusted_vault/trusted_vault_connection_impl.cc b/components/sync/trusted_vault/trusted_vault_connection_impl.cc
index 1b91852..630cbd5 100644
--- a/components/sync/trusted_vault/trusted_vault_connection_impl.cc
+++ b/components/sync/trusted_vault/trusted_vault_connection_impl.cc
@@ -131,7 +131,7 @@
                               /*last_key_version=*/0);
       return;
     case TrustedVaultRequest::HttpStatus::kNotFound:
-    case TrustedVaultRequest::HttpStatus::kFailedPrecondition:
+    case TrustedVaultRequest::HttpStatus::kBadRequest:
       // Local trusted vault keys are outdated.
       std::move(callback).Run(
           TrustedVaultRegistrationStatus::kLocalDataObsolete,
@@ -180,7 +180,7 @@
       break;
     case TrustedVaultRequest::HttpStatus::kOtherError:
     case TrustedVaultRequest::HttpStatus::kNotFound:
-    case TrustedVaultRequest::HttpStatus::kFailedPrecondition:
+    case TrustedVaultRequest::HttpStatus::kBadRequest:
       std::move(callback).Run(TrustedVaultRecoverabilityStatus::kError);
       return;
   }
diff --git a/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc b/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc
index 4612bb5..0179ff4 100644
--- a/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc
+++ b/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc
@@ -479,9 +479,8 @@
                                           /*response_content=*/std::string()));
 }
 
-TEST_F(
-    TrustedVaultConnectionImplTest,
-    ShouldHandleFailedJoinSecurityDomainsRequestWithPreconditionFailedStatus) {
+TEST_F(TrustedVaultConnectionImplTest,
+       ShouldHandleFailedJoinSecurityDomainsRequestWithBadRequestStatus) {
   std::unique_ptr<SecureBoxKeyPair> key_pair = MakeTestKeyPair();
   ASSERT_THAT(key_pair, NotNull());
 
@@ -497,13 +496,13 @@
           /*authentication_factor_type_hint=*/absl::nullopt, callback.Get());
   ASSERT_THAT(request, NotNull());
 
-  // In particular, HTTP_PRECONDITION_FAILED indicates that
+  // In particular, HTTP_BAD_REQUEST indicates that
   // |last_trusted_vault_key_and_version| is not actually the last on the server
   // side.
   EXPECT_CALL(callback,
               Run(Eq(TrustedVaultRegistrationStatus::kLocalDataObsolete)));
   EXPECT_TRUE(
-      RespondToJoinSecurityDomainsRequest(net::HTTP_PRECONDITION_FAILED,
+      RespondToJoinSecurityDomainsRequest(net::HTTP_BAD_REQUEST,
                                           /*response_content=*/std::string()));
 }
 
diff --git a/components/sync/trusted_vault/trusted_vault_request.cc b/components/sync/trusted_vault/trusted_vault_request.cc
index 5a47cfa..ce34efe0 100644
--- a/components/sync/trusted_vault/trusted_vault_request.cc
+++ b/components/sync/trusted_vault/trusted_vault_request.cc
@@ -132,16 +132,17 @@
       "Sync.TrustedVaultURLFetchResponse",
       http_response_code == 0 ? net_error : http_response_code);
 
+  if (http_response_code == net::HTTP_BAD_REQUEST) {
+    RunCompletionCallbackAndMaybeDestroySelf(HttpStatus::kBadRequest,
+                                             std::string());
+    return;
+  }
   if (http_response_code == net::HTTP_NOT_FOUND) {
     RunCompletionCallbackAndMaybeDestroySelf(HttpStatus::kNotFound,
                                              std::string());
     return;
   }
-  if (http_response_code == net::HTTP_PRECONDITION_FAILED) {
-    RunCompletionCallbackAndMaybeDestroySelf(HttpStatus::kFailedPrecondition,
-                                             std::string());
-    return;
-  }
+
   if (http_response_code != net::HTTP_OK &&
       http_response_code != net::HTTP_NO_CONTENT) {
     RunCompletionCallbackAndMaybeDestroySelf(HttpStatus::kOtherError,
diff --git a/components/sync/trusted_vault/trusted_vault_request.h b/components/sync/trusted_vault/trusted_vault_request.h
index f533a512..fcc6fe0f 100644
--- a/components/sync/trusted_vault/trusted_vault_request.h
+++ b/components/sync/trusted_vault/trusted_vault_request.h
@@ -35,12 +35,12 @@
   enum class HttpStatus {
     // Reported when server returns http status code 200 or 204.
     kSuccess,
+    // Reported when server returns http status code 400 (bad request).
+    kBadRequest,
     // Reported when server returns http status code 404 (not found).
     kNotFound,
-    // Reported when server returns http status code 412 (precondition failed).
-    kFailedPrecondition,
     // Reported when other error occurs: unable to fetch access token, network
-    // and http errors (except 404 and 412).
+    // and http errors (except 400 and 404).
     kOtherError
   };
 
diff --git a/components/sync/trusted_vault/trusted_vault_request_unittest.cc b/components/sync/trusted_vault/trusted_vault_request_unittest.cc
index 8f6e3a2..761e9d7 100644
--- a/components/sync/trusted_vault/trusted_vault_request_unittest.cc
+++ b/components/sync/trusted_vault/trusted_vault_request_unittest.cc
@@ -228,6 +228,20 @@
                                    /*response_body=*/""));
 }
 
+TEST_F(TrustedVaultRequestTest, ShouldHandleBadRequestStatus) {
+  base::MockCallback<TrustedVaultRequest::CompletionCallback>
+      completion_callback;
+  std::unique_ptr<TrustedVaultRequest> request = StartNewRequestWithAccessToken(
+      kAccessToken, TrustedVaultRequest::HttpMethod::kGet,
+      /*request_body=*/absl::nullopt, completion_callback.Get());
+
+  // |completion_callback| should be called after receiving response.
+  EXPECT_CALL(completion_callback,
+              Run(TrustedVaultRequest::HttpStatus::kBadRequest, _));
+  EXPECT_TRUE(RespondToHttpRequest(net::OK, net::HTTP_BAD_REQUEST,
+                                   /*response_body=*/""));
+}
+
 TEST_F(TrustedVaultRequestTest, ShouldHandleNotFoundStatus) {
   base::MockCallback<TrustedVaultRequest::CompletionCallback>
       completion_callback;
@@ -242,20 +256,6 @@
                                    /*response_body=*/""));
 }
 
-TEST_F(TrustedVaultRequestTest, ShouldHandlePreconditionFailedStatus) {
-  base::MockCallback<TrustedVaultRequest::CompletionCallback>
-      completion_callback;
-  std::unique_ptr<TrustedVaultRequest> request = StartNewRequestWithAccessToken(
-      kAccessToken, TrustedVaultRequest::HttpMethod::kGet,
-      /*request_body=*/absl::nullopt, completion_callback.Get());
-
-  // |completion_callback| should be called after receiving response.
-  EXPECT_CALL(completion_callback,
-              Run(TrustedVaultRequest::HttpStatus::kFailedPrecondition, _));
-  EXPECT_TRUE(RespondToHttpRequest(net::OK, net::HTTP_PRECONDITION_FAILED,
-                                   /*response_body=*/""));
-}
-
 TEST_F(TrustedVaultRequestTest, ShouldHandleAccessTokenFetchingFailures) {
   base::MockCallback<TrustedVaultRequest::CompletionCallback>
       completion_callback;
diff --git a/components/test/data/payments/secure_payment_confirmation.js b/components/test/data/payments/secure_payment_confirmation.js
index ae5bcd9c..d26b805 100644
--- a/components/test/data/payments/secure_payment_confirmation.js
+++ b/components/test/data/payments/secure_payment_confirmation.js
@@ -110,6 +110,16 @@
 }
 
 /**
+ * Creates a secure payment confirmation credential and returns its type.
+ * @param {string} icon - The URL of the icon for the credential.
+ * @return {string} - Either "PaymentCredential" or "PublicKeyCredential".
+ */
+async function createCredentialAndReturnItsType(icon) { // eslint-disable-line no-unused-vars, max-len
+  const credential = await createAndReturnPaymentCredential(icon);
+  return credential.constructor.name;
+}
+
+/**
  * Creates and returns a secure payment confirmation credential.
  * @param {string} icon - The URL of the icon for the credential.
  * @return {PaymentCredential} - The new credential.
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index d0009e91..5120b482 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -354,8 +354,8 @@
   return true;
 }
 
-void TranslateManager::InitiateManualTranslation(bool auto_translate,
-                                                 bool triggered_from_menu) {
+void TranslateManager::ShowTranslateUI(bool auto_translate,
+                                       bool triggered_from_menu) {
   // If a translation is in progress, do nothing.
   if (language_state_.translation_pending()) {
     return;
diff --git a/components/translate/core/browser/translate_manager.h b/components/translate/core/browser/translate_manager.h
index 1e9a796..319750a 100644
--- a/components/translate/core/browser/translate_manager.h
+++ b/components/translate/core/browser/translate_manager.h
@@ -133,11 +133,10 @@
   // Maybe initiates translation when Autofill Assistant has finished.
   void OnAutofillAssistantFinished();
 
-  // Initiate a manually triggered translation process for the current page.
-  // Collect source and target languages, and show translation UI. If
-  // |auto_translate| is true the page gets translated to the target language.
-  void InitiateManualTranslation(bool auto_translate = false,
-                                 bool triggered_from_menu = false);
+  // Show the translation UI. If |auto_translate| is true the page gets
+  // translated to the target language.
+  void ShowTranslateUI(bool auto_translate = false,
+                       bool triggered_from_menu = false);
 
   // Returns true iff the current page could be manually translated.
   // Logging should only be performed when this method is called to show the
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index 568a08a..200e56a 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -1236,7 +1236,7 @@
                   Bucket(metrics::INITIATION_STATUS_SHOW_ICON, 1)));
 }
 
-TEST_F(TranslateManagerTest, InitiateManualTranslation) {
+TEST_F(TranslateManagerTest, ShowTranslateUI) {
   manager_->set_application_locale("en");
   mock_language_model_.details = {
       MockLanguageModel::LanguageDetails("de", 1.0),
@@ -1256,9 +1256,10 @@
   translate_manager_->GetLanguageState()->LanguageDetermined("de", true);
   network_notifier_.SimulateOnline();
 
-  translate_manager_->InitiateManualTranslation();
+  translate_manager_->ShowTranslateUI();
 
-  // InitiateManualTranslation should only ShowTranslateUI (not do translation).
+  // TranslateManager::ShowTranslateUI should only call
+  // TranslateClient::ShowTranslateUI (not do translation).
   histogram_tester.ExpectTotalCount(kInitiationStatusName, 0);
 }
 
diff --git a/components/variations/variations_ids_provider.h b/components/variations/variations_ids_provider.h
index afe774e..17ee4a5f 100644
--- a/components/variations/variations_ids_provider.h
+++ b/components/variations/variations_ids_provider.h
@@ -15,7 +15,6 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
-#include "base/no_destructor.h"
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
 #include "components/variations/proto/study.pb.h"
diff --git a/components/variations/variations_test_utils.cc b/components/variations/variations_test_utils.cc
index 577f2ef..8f453a2 100644
--- a/components/variations/variations_test_utils.cc
+++ b/components/variations/variations_test_utils.cc
@@ -15,15 +15,20 @@
 namespace variations {
 
 const char kUncompressedBase64TestSeedData[] =
-    "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p"
-    "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB"
-    "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0"
-    "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf"
-    "MDgQAUoMCghncm91cF8wORAB";
+    "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5pZm"
+    "9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBABSgwK"
+    "CGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0EAFKDA"
+    "oIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBfMDgQAUoM"
+    "Cghncm91cF8wORAB";
+
+const char kCompressedBase64TestSeedData[] =
+    "H4sIAAAAAAAAAOPSMEwxsjQxM0lLMk4xt0hLMzQ1NUs1TTI1NUw2MzExT05KNjdJNU1LMRDay8"
+    "glH+rrqBual5mWX5SbWVKpG1KUmZija2igG5BalJyaVyLRMGfSUlYLRif2lNS0xNKcEi9uLhhT"
+    "gNGLh4sjvSi/tCDewBCFZ4TCM0bhmaDwTFF4Zig8cxSeBQrPUoARAEVeJPrqAAAA";
 
 const char kBase64TestSeedSignature[] =
-    "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
-    "96JkMYgzTkHPwbv7K/CmgA==";
+    "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy96"
+    "JkMYgzTkHPwbv7K/CmgA==";
 
 const char kTestSeedStudyName[] = "UMA-Uniformity-Trial-10-Percent";
 
diff --git a/components/variations/variations_test_utils.h b/components/variations/variations_test_utils.h
index 3dc343f..91a1849 100644
--- a/components/variations/variations_test_utils.h
+++ b/components/variations/variations_test_utils.h
@@ -14,12 +14,14 @@
 
 namespace variations {
 
-// The below seed and signature pair were generated using the server's private
-// key.
+// The test seed data is associated with a VariationsSeed with one study,
+// "UMA-Uniformity-Trial-10-Percent", and ten equally weighted groups: "default"
+// and "group_01" through "group_09". The study is not associated with channels,
+// platforms, or features.
 //
-// The seed contains one study, "UMA-Uniformity-Trial-10-Percent", and ten
-// equally weighted groups: "default" and "group_01" through "group_09".
+// The seed and signature pair were generated using the server's private key.
 extern const char kUncompressedBase64TestSeedData[];
+extern const char kCompressedBase64TestSeedData[];
 extern const char kBase64TestSeedSignature[];
 extern const char kTestSeedStudyName[];
 
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
index dbdc8f5..34e5e9d 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -36,7 +36,8 @@
 // Normalizes value to a float in [0, 1]. Use to convert a fuzzed
 // uint32 into a percentage.
 float Normalize(uint32_t x) {
-  return static_cast<float>(x) / std::numeric_limits<uint32_t>::max();
+  return static_cast<float>(x) /
+         static_cast<float>(std::numeric_limits<uint32_t>::max());
 }
 
 gfx::Size GetSizeFromProtobuf(const proto::Size& proto_size) {
diff --git a/components/viz/service/display/delegated_ink_point_renderer_skia.cc b/components/viz/service/display/delegated_ink_point_renderer_skia.cc
index e248daa..e3bc5f5 100644
--- a/components/viz/service/display/delegated_ink_point_renderer_skia.cc
+++ b/components/viz/service/display/delegated_ink_point_renderer_skia.cc
@@ -30,7 +30,6 @@
     paint.setAntiAlias(true);
     paint.setBlendMode(SkBlendMode::kSrcOver);
     paint.setColor(metadata_->color());
-    paint.setFilterQuality(kNone_SkFilterQuality);
     paint.setStrokeCap(SkPaint::kRound_Cap);
     paint.setStrokeJoin(SkPaint::kRound_Join);
     paint.setStrokeWidth(SkScalar(metadata_->diameter()));
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 3e6553d2..1407be2a 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -1065,13 +1065,13 @@
     DLOG(ERROR) << "Received unexpected PresentationFeedback";
     return;
   }
-  ++last_presented_trace_id_;
-  TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
-      "viz,benchmark", "Graphics.Pipeline.DrawAndSwap",
-      last_presented_trace_id_, feedback.timestamp);
   auto& presentation_group_timing = pending_presentation_group_timings_.front();
   auto copy_feedback = SanitizePresentationFeedback(
       feedback, presentation_group_timing.draw_start_timestamp());
+  ++last_presented_trace_id_;
+  TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
+      "viz,benchmark", "Graphics.Pipeline.DrawAndSwap",
+      last_presented_trace_id_, copy_feedback.timestamp);
   TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
       "benchmark,viz", "Display::FrameDisplayed", TRACE_EVENT_SCOPE_THREAD,
       copy_feedback.timestamp);
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index ef87dbb..ba17de03 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -1317,8 +1317,8 @@
   // Applying the scissor explicitly means avoiding a clipRect() call and
   // allows more quads to be batched together in a DrawEdgeAAImageSet call
   if (scissor_rect) {
-    if (CanExplicitlyScissor(quad, draw_region,
-                             params.content_device_transform)) {
+    if (CanExplicitlyScissor(quad, draw_region, params.content_device_transform,
+                             *scissor_rect)) {
       ApplyExplicitScissor(quad, *scissor_rect, params.content_device_transform,
                            &params.aa_flags, &params.visible_rect);
       params.vis_tex_coords = params.visible_rect;
@@ -1358,7 +1358,8 @@
 bool SkiaRenderer::CanExplicitlyScissor(
     const DrawQuad* quad,
     const gfx::QuadF* draw_region,
-    const gfx::Transform& contents_device_transform) const {
+    const gfx::Transform& contents_device_transform,
+    const gfx::Rect& scissor_rect) const {
   // PICTURE_CONTENT is not like the others, since it is executing a list of
   // draw calls into the canvas.
   if (quad->material == DrawQuad::Material::kPictureContent)
@@ -1371,11 +1372,14 @@
   // This is slightly different than
   // gfx::Transform::IsPositiveScaleAndTranslation in that it also allows zero
   // scales. This is because in the common orthographic case the z scale is 0.
-  if (!contents_device_transform.IsScaleOrTranslation())
+  if (!contents_device_transform.IsScaleOrTranslation() ||
+      contents_device_transform.matrix().get(0, 0) < 0.0f ||
+      contents_device_transform.matrix().get(1, 1) < 0.0f ||
+      contents_device_transform.matrix().get(2, 2) < 0.0f) {
     return false;
+  }
 
-  // Sanity check: we should not have a Compositor CompositorRenderPassDrawQuad
-  // here.
+  // State check: should not have a CompositorRenderPassDrawQuad if we got here.
   DCHECK_NE(quad->material, DrawQuad::Material::kCompositorRenderPass);
   if (quad->material == DrawQuad::Material::kAggregatedRenderPass) {
     // If the renderpass has filters, the filters may modify the effective
@@ -1386,9 +1390,18 @@
       return false;
   }
 
-  return contents_device_transform.matrix().get(0, 0) >= 0.0 &&
-         contents_device_transform.matrix().get(1, 1) >= 0.0 &&
-         contents_device_transform.matrix().get(2, 2) >= 0.0;
+  // If the intersection of the scissor and the quad's visible_rect results in
+  // subpixel device-space geometry, do not drop the scissor. Otherwise Skia
+  // sees an unclipped anti-aliased hairline and uses different AA methods that
+  // would cause the rasterized result to extend beyond the scissor.
+  gfx::RectF device_bounds(quad->visible_rect);
+  contents_device_transform.TransformRect(&device_bounds);
+  device_bounds.Intersect(gfx::RectF(scissor_rect));
+  if (device_bounds.width() < 1.0f || device_bounds.height() < 1.0f) {
+    return false;
+  }
+
+  return true;
 }
 
 const DrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index 0cf2a14..b94ffe0b 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -158,10 +158,10 @@
       DrawQuadParams* params) const;
   // True or false if the DrawQuad can have the scissor rect applied by
   // modifying the quad's visible_rect instead of as a separate clip operation.
-  bool CanExplicitlyScissor(
-      const DrawQuad* quad,
-      const gfx::QuadF* draw_region,
-      const gfx::Transform& contents_device_transform) const;
+  bool CanExplicitlyScissor(const DrawQuad* quad,
+                            const gfx::QuadF* draw_region,
+                            const gfx::Transform& contents_device_transform,
+                            const gfx::Rect& scissor_rect) const;
 
   bool MustFlushBatchedQuads(const DrawQuad* new_quad,
                              const DrawRPDQParams* rpdq_params,
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index ac91841..64c2f6b 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -287,7 +287,7 @@
     if (settings_->allow_antialiasing &&
         (settings_->force_antialiasing || all_four_edges_are_exterior))
       current_paint_.setAntiAlias(true);
-    current_paint_.setFilterQuality(kLow_SkFilterQuality);
+    current_sampling_ = SkSamplingOptions(SkFilterMode::kLinear);
   }
 
   if (quad->ShouldDrawWithBlending() ||
@@ -549,12 +549,10 @@
   SkMatrix content_mat = SkMatrix::RectToRect(content_rect, dest_rect);
 
   sk_sp<SkShader> shader;
-  SkSamplingOptions sampling(cc::PaintFlags::FilterQualityToSkSamplingOptions(
-      current_paint_.getFilterQuality()));
   if (!filter_image) {
-    shader = source_bitmap.makeShader(sampling, content_mat);
+    shader = source_bitmap.makeShader(current_sampling_, content_mat);
   } else {
-    shader = filter_image->makeShader(sampling, content_mat);
+    shader = filter_image->makeShader(current_sampling_, content_mat);
   }
 
   if (quad->mask_resource_id()) {
@@ -571,7 +569,7 @@
     SkMatrix mask_mat = SkMatrix::RectToRect(mask_rect, dest_rect);
 
     current_paint_.setMaskFilter(SkShaderMaskFilter::Make(
-        mask_lock.sk_image()->makeShader(sampling, mask_mat)));
+        mask_lock.sk_image()->makeShader(current_sampling_, mask_mat)));
   }
 
   // If we have a backdrop filter shader, render its results first.
diff --git a/components/viz/service/display/software_renderer.h b/components/viz/service/display/software_renderer.h
index 1777984..2cb8940 100644
--- a/components/viz/service/display/software_renderer.h
+++ b/components/viz/service/display/software_renderer.h
@@ -124,6 +124,7 @@
   SkCanvas* root_canvas_ = nullptr;
   SkCanvas* current_canvas_ = nullptr;
   SkPaint current_paint_;
+  SkSamplingOptions current_sampling_;
   std::unique_ptr<SkCanvas> current_framebuffer_canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(SoftwareRenderer);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 6413855..16c8595a 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1163,49 +1163,54 @@
   if (context_is_lost_)
     return;
 
-  // GL is used on MacOS and GL doesn't need semaphores.
-  promise_image_access_helper_.BeginAccess(std::move(image_contexts),
-                                           /*begin_semaphores=*/nullptr,
-                                           /*end_semaphores=*/nullptr);
-  using ScopedWriteAccess =
-      std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>;
-  std::vector<ScopedWriteAccess> scoped_write_accesses;
-  for (auto& overlay : overlays) {
-    if (!overlay.ddl)
-      continue;
-    const auto& characterization = overlay.ddl->characterization();
-    auto backing = GetOrCreateRenderPassOverlayBacking(characterization);
-    if (!backing)
-      break;
-    DCHECK(overlay.mailbox.IsZero());
-    overlay.mailbox = backing->mailbox();
-    auto scoped_access = backing->BeginScopedWriteAccess(
-        /*final_msaa_count=*/0, characterization.surfaceProps(),
-        /*begin_semaphores=*/nullptr,
-        /*end_semaphores=*/nullptr,
-        gpu::SharedImageRepresentation::AllowUnclearedAccess::kYes);
-    bool result = scoped_access->surface()->draw(overlay.ddl);
-    DCHECK(result);
-    scoped_write_accesses.push_back(std::move(scoped_access));
-    backing->SetCleared();
-    in_flight_render_pass_overlay_backings_.insert(std::move(backing));
-  }
+  if (!image_contexts.empty()) {
+    DCHECK(context_state_->GrContextIsGL());
 
-  if (!scoped_write_accesses.empty()) {
-    absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
-    if (dependency_->GetGrShaderCache()) {
-      cache_use.emplace(dependency_->GetGrShaderCache(),
-                        gpu::kDisplayCompositorClientId);
+    // GL doesn't use semaphores.
+    promise_image_access_helper_.BeginAccess(std::move(image_contexts),
+                                             /*begin_semaphores=*/nullptr,
+                                             /*end_semaphores=*/nullptr);
+    using ScopedWriteAccess =
+        std::unique_ptr<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>;
+    std::vector<ScopedWriteAccess> scoped_write_accesses;
+    for (auto& overlay : overlays) {
+      if (!overlay.ddl)
+        continue;
+      const auto& characterization = overlay.ddl->characterization();
+      auto backing = GetOrCreateRenderPassOverlayBacking(characterization);
+      if (!backing)
+        break;
+      DCHECK(overlay.mailbox.IsZero());
+      overlay.mailbox = backing->mailbox();
+      auto scoped_access = backing->BeginScopedWriteAccess(
+          /*final_msaa_count=*/0, characterization.surfaceProps(),
+          /*begin_semaphores=*/nullptr,
+          /*end_semaphores=*/nullptr,
+          gpu::SharedImageRepresentation::AllowUnclearedAccess::kYes);
+      bool result = scoped_access->surface()->draw(overlay.ddl);
+      DCHECK(result);
+      scoped_write_accesses.push_back(std::move(scoped_access));
+      backing->SetCleared();
+      in_flight_render_pass_overlay_backings_.insert(std::move(backing));
     }
 
-    GrFlushInfo flush_info = {};
-    if (on_finished)
-      gpu::AddCleanupTaskForSkiaFlush(std::move(on_finished), &flush_info);
-    context_state_->gr_context()->flush(flush_info);
-    context_state_->gr_context()->submit();
-    scoped_write_accesses.clear();
+    if (!scoped_write_accesses.empty()) {
+      absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+      if (dependency_->GetGrShaderCache()) {
+        cache_use.emplace(dependency_->GetGrShaderCache(),
+                          gpu::kDisplayCompositorClientId);
+      }
+
+      GrFlushInfo flush_info = {};
+      if (on_finished)
+        gpu::AddCleanupTaskForSkiaFlush(std::move(on_finished), &flush_info);
+      context_state_->gr_context()->flush(flush_info);
+      context_state_->gr_context()->submit();
+      scoped_write_accesses.clear();
+    }
+    promise_image_access_helper_.EndAccess();
   }
-  promise_image_access_helper_.EndAccess();
+
   output_device_->ScheduleOverlays(std::move(overlays));
 #else
   DCHECK(image_contexts.empty());
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java
index b241ed7..2858aca 100644
--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java
+++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/AuthenticatorImpl.java
@@ -81,6 +81,7 @@
         }
 
         mMakeCredentialCallback = callback;
+        mIsOperationPending = true;
         Context context = ContextUtils.getApplicationContext();
         if (PackageUtils.getPackageVersion(context, GMSCORE_PACKAGE_NAME)
                 < Fido2ApiHandler.GMSCORE_MIN_VERSION) {
@@ -88,7 +89,6 @@
             return;
         }
 
-        mIsOperationPending = true;
         Fido2ApiHandler.getInstance().makeCredential(options, mRenderFrameHost, mOrigin,
                 (status, response)
                         -> onRegisterResponse(status, response),
@@ -104,6 +104,7 @@
         }
 
         mGetAssertionCallback = callback;
+        mIsOperationPending = true;
         Context context = ContextUtils.getApplicationContext();
 
         if (PackageUtils.getPackageVersion(context, GMSCORE_PACKAGE_NAME)
@@ -112,7 +113,6 @@
             return;
         }
 
-        mIsOperationPending = true;
         Fido2ApiHandler.getInstance().getAssertion(options, mRenderFrameHost, mOrigin,
                 (status, response) -> onSignResponse(status, response), status -> onError(status));
     }
@@ -155,12 +155,18 @@
      * Callbacks for receiving responses from the internal handlers.
      */
     public void onRegisterResponse(Integer status, MakeCredentialAuthenticatorResponse response) {
+        // In case mojo pipe is closed due to the page begin destroyed while waiting for response.
+        if (!mIsOperationPending) return;
+
         assert mMakeCredentialCallback != null;
         mMakeCredentialCallback.call(status, response);
         close();
     }
 
     public void onSignResponse(Integer status, GetAssertionAuthenticatorResponse response) {
+        // In case mojo pipe is closed due to the page begin destroyed while waiting for response.
+        if (!mIsOperationPending) return;
+
         assert mGetAssertionCallback != null;
         mGetAssertionCallback.call(status, response);
         close();
@@ -172,6 +178,9 @@
     }
 
     public void onError(Integer status) {
+        // In case mojo pipe is closed due to the page begin destroyed while waiting for response.
+        if (!mIsOperationPending) return;
+
         assert ((mMakeCredentialCallback != null && mGetAssertionCallback == null)
                 || (mMakeCredentialCallback == null && mGetAssertionCallback != null));
         if (mMakeCredentialCallback != null) {
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.h b/content/browser/accessibility/accessibility_tree_formatter_mac.h
index e122ac1..523740e 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.h
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.h
@@ -25,6 +25,12 @@
 
   base::Value BuildNode(ui::AXPlatformNodeDelegate* node) const override;
 
+  std::string EvaluateScript(
+      ui::AXPlatformNodeDelegate* root,
+      const std::vector<ui::AXScriptInstruction>& instructions,
+      size_t start_index,
+      size_t end_index) const override;
+
  protected:
   void AddDefaultFilters(
       std::vector<ui::AXPropertyFilter>* property_filters) override;
@@ -35,10 +41,6 @@
 
   base::Value BuildNode(const id node) const;
 
-  // Runs all scripts defined by given property filters.
-  void EvaluateScripts(const a11y::LineIndexer* line_indexer,
-                       base::Value* dict) const;
-
   void RecursiveBuildTree(const id node,
                           const NSRect& root_rect,
                           const a11y::LineIndexer* line_indexer,
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index e3470fdb..c50d742e 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -18,6 +18,7 @@
 #include "content/public/browser/ax_inspect_factory.h"
 #include "ui/accessibility/platform/inspect/ax_inspect_utils.h"
 #include "ui/accessibility/platform/inspect/ax_property_node.h"
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
 
 // This file uses the deprecated NSObject accessibility interface.
 // TODO(crbug.com/948844): Migrate to the new NSAccessibility interface.
@@ -116,30 +117,45 @@
   NSSize size = SizeOf(root);
   NSRect rect = NSMakeRect(position.x, position.y, size.width, size.height);
 
-  EvaluateScripts(&line_indexer, &dict);
   RecursiveBuildTree(root, rect, &line_indexer, &dict);
 
   return dict;
 }
 
-void AccessibilityTreeFormatterMac::EvaluateScripts(
-    const LineIndexer* line_indexer,
-    base::Value* dict) const {
-  std::map<std::string, id> storage;
+std::string AccessibilityTreeFormatterMac::EvaluateScript(
+    ui::AXPlatformNodeDelegate* root,
+    const std::vector<ui::AXScriptInstruction>& instructions,
+    size_t start_index,
+    size_t end_index) const {
+  BrowserAccessibilityCocoa* platform_root = ToBrowserAccessibilityCocoa(
+      BrowserAccessibility::FromAXPlatformNodeDelegate(root));
+
   base::Value scripts(base::Value::Type::LIST);
-  AttributeInvoker invoker(line_indexer, &storage);
-  for (const AXPropertyNode& property_node : ScriptPropertyNodes()) {
+  LineIndexer line_indexer(platform_root);
+  std::map<std::string, id> storage;
+  AttributeInvoker invoker(&line_indexer, &storage);
+  for (size_t index = start_index; index < end_index; index++) {
+    DCHECK(instructions[index].IsScript());
+    const AXPropertyNode& property_node = instructions[index].AsScript();
     OptionalNSObject value = invoker.Invoke(property_node);
     if (value.IsNotApplicable()) {
       continue;
     }
 
-    base::Value result = value.IsError() ? base::Value(kFailedToParseError)
-                                         : PopulateObject(*value, line_indexer);
+    base::Value result = value.IsError()
+                             ? base::Value(kFailedToParseError)
+                             : PopulateObject(*value, &line_indexer);
 
     scripts.Append(property_node.ToString() + "=" + AXFormatValue(result));
   }
-  dict->SetPath(kScriptsDictAttr, std::move(scripts));
+
+  std::string contents;
+  for (const base::Value& script : scripts.GetList()) {
+    std::string line;
+    WriteAttribute(true, script.GetString(), &line);
+    contents += line + "\n";
+  }
+  return contents;
 }
 
 base::Value AccessibilityTreeFormatterMac::BuildNode(
@@ -160,7 +176,6 @@
   NSSize size = SizeOf(node);
   NSRect rect = NSMakeRect(position.x, position.y, size.width, size.height);
 
-  EvaluateScripts(&line_indexer, &dict);
   AddProperties(node, rect, &line_indexer, &dict);
   return dict;
 }
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm b/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
index c4919c5..3f5fc85 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
@@ -16,6 +16,7 @@
 #include "net/base/data_url.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -24,7 +25,6 @@
 
 const ui::AXPropertyFilter::Type ALLOW_EMPTY =
     ui::AXPropertyFilter::ALLOW_EMPTY;
-const ui::AXPropertyFilter::Type SCRIPT = ui::AXPropertyFilter::SCRIPT;
 
 class AccessibilityTreeFormatterMacBrowserTest : public ContentBrowserTest {
  public:
@@ -32,14 +32,18 @@
   ~AccessibilityTreeFormatterMacBrowserTest() override {}
 
   // Checks the formatted accessible tree for the given data URL.
-  void TestAndCheck(const char* url,
-                    const std::vector<ui::AXPropertyFilter>& property_filters,
-                    const std::vector<ui::AXNodeFilter>& node_filters,
-                    const char* expected) const;
+  void TestFormat(const char* url,
+                  const std::vector<ui::AXPropertyFilter>& property_filters,
+                  const std::vector<ui::AXNodeFilter>& node_filters,
+                  const char* expected) const;
 
-  void TestAndCheck(const char* url,
-                    const std::vector<const char*>& filters,
-                    const char* expected) const;
+  void TestFormat(const char* url,
+                  const std::vector<const char*>& filters,
+                  const char* expected) const;
+
+  void TestScript(const char* url,
+                  const std::vector<const char*>& scripts,
+                  const char* expected) const;
 
   // Tests wrong parameters for an attribute in a single run
   void TestWrongParameters(const char* url,
@@ -55,7 +59,7 @@
   }
 };
 
-void AccessibilityTreeFormatterMacBrowserTest::TestAndCheck(
+void AccessibilityTreeFormatterMacBrowserTest::TestFormat(
     const char* url,
     const std::vector<ui::AXPropertyFilter>& property_filters,
     const std::vector<ui::AXNodeFilter>& node_filters,
@@ -82,7 +86,7 @@
   EXPECT_EQ(actual, expected);
 }
 
-void AccessibilityTreeFormatterMacBrowserTest::TestAndCheck(
+void AccessibilityTreeFormatterMacBrowserTest::TestFormat(
     const char* url,
     const std::vector<const char*>& filters,
     const char* expected) const {
@@ -90,7 +94,35 @@
   for (const char* filter : filters) {
     property_filters.emplace_back(filter, ALLOW_EMPTY);
   }
-  TestAndCheck(url, property_filters, {}, expected);
+  TestFormat(url, property_filters, {}, expected);
+}
+
+void AccessibilityTreeFormatterMacBrowserTest::TestScript(
+    const char* url,
+    const std::vector<const char*>& scripts,
+    const char* expected) const {
+  ASSERT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
+
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kLoadComplete);
+  ASSERT_TRUE(NavigateToURL(shell(), GURL(url)));
+  waiter.WaitForNotification();
+
+  std::unique_ptr<ui::AXTreeFormatter> formatter =
+      AXInspectFactory::CreatePlatformFormatter();
+
+  BrowserAccessibility* root = GetManager()->GetRoot();
+  ASSERT_NE(nullptr, root);
+
+  std::vector<ui::AXScriptInstruction> instructions;
+  for (const char* script : scripts) {
+    instructions.emplace_back(script);
+  }
+
+  std::string actual =
+      formatter->EvaluateScript(root, instructions, 0, instructions.size());
+  EXPECT_EQ(actual, expected);
 }
 
 void AccessibilityTreeFormatterMacBrowserTest::TestWrongParameters(
@@ -112,7 +144,7 @@
     std::string filter(filter_pattern);
     filter.replace(filter_pos, placeholder.length(), parameter);
 
-    TestAndCheck(url, {filter.c_str()}, expected.c_str());
+    TestFormat(url, {filter.c_str()}, expected.c_str());
   }
 }
 
@@ -120,10 +152,10 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        DefaultAttributes) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <input aria-label='input'>)~~",
-               {},
-               R"~~(AXWebArea
+             {},
+             R"~~(AXWebArea
 ++AXGroup
 ++++AXTextField AXDescription='input'
 )~~");
@@ -131,10 +163,10 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Filters_NoWildcardProperty) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <input class='classolasso'>)~~",
-               {"AXDOMClassList"},
-               R"~~(AXWebArea AXDOMClassList=[]
+             {"AXDOMClassList"},
+             R"~~(AXWebArea AXDOMClassList=[]
 ++AXGroup AXDOMClassList=[]
 ++++AXTextField AXDOMClassList=['classolasso']
 )~~");
@@ -142,11 +174,11 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Filters_LineIndex) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <input class='input_at_3rd_line'>
                     <input class='input_at_4th_line'>
                     <input class='input_at_5th_line'>)~~",
-               {":3,:5;AXDOMClassList=*"}, R"~~(AXWebArea
+             {":3,:5;AXDOMClassList=*"}, R"~~(AXWebArea
 ++AXGroup
 ++++AXTextField AXDOMClassList=['input_at_3rd_line']
 ++++AXTextField
@@ -156,9 +188,9 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Serialize_AXTextMarker) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p>Paragraph</p>)~~",
-               {":3;AXStartTextMarker=*"}, R"~~(AXWebArea
+             {":3;AXStartTextMarker=*"}, R"~~(AXWebArea
 ++AXGroup
 ++++AXStaticText AXStartTextMarker={:1, 0, down} AXValue='Paragraph'
 )~~");
@@ -166,12 +198,12 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Serialize_AXTextMarkerRange) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>
                     <script>
                       window.getSelection().selectAllChildren(document.getElementById('p'));
                     </script>)~~",
-               {":3;AXSelectedTextMarkerRange=*"}, R"~~(AXWebArea
+             {":3;AXSelectedTextMarkerRange=*"}, R"~~(AXWebArea
 ++AXGroup
 ++++AXStaticText AXSelectedTextMarkerRange={anchor: {:2, -1, down}, focus: {:3, 0, down}} AXValue='Paragraph'
 )~~");
@@ -179,9 +211,9 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_Int) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p contentEditable='true'>Text</p>)~~",
-               {":2;AXLineForIndex(0)=*"}, R"~~(AXWebArea
+             {":2;AXLineForIndex(0)=*"}, R"~~(AXWebArea
 ++AXTextArea AXLineForIndex(0)=0 AXValue='Text'
 ++++AXStaticText AXValue='Text'
 )~~");
@@ -200,9 +232,9 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_IntArray) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <table role="grid"><tr><td>CELL</td></tr></table>)~~",
-               {"AXCellForColumnAndRow([0, 0])=*"}, R"~~(AXWebArea
+             {"AXCellForColumnAndRow([0, 0])=*"}, R"~~(AXWebArea
 ++AXTable AXCellForColumnAndRow([0, 0])=:4
 ++++AXRow
 ++++++AXCell
@@ -216,9 +248,9 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_IntArray_NilValue) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <table role="grid"></table>)~~",
-               {"AXCellForColumnAndRow([0, 0])=*"}, R"~~(AXWebArea
+             {"AXCellForColumnAndRow([0, 0])=*"}, R"~~(AXWebArea
 ++AXTable AXCellForColumnAndRow([0, 0])=NULL
 ++++AXGroup
 )~~");
@@ -242,27 +274,25 @@
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
-                       ParameterizedAttributes_NSRange) {
-  TestAndCheck(R"~~(data:text/html,
-                    <p contentEditable='true'>Text</p>)~~",
-               {":2;AXStringForRange({loc: 1, len: 2})=*"}, R"~~(AXWebArea
-++AXTextArea AXStringForRange({loc: 1, len: 2})='ex' AXValue='Text'
-++++AXStaticText AXValue='Text'
+                       ParameterizedAttributes_TextMarkerArray) {
+  TestScript(
+      R"~~(data:text/html,
+                    <textbox id="textbox">Text</textbox>)~~",
+      {"text_range:= textbox.AXTextMarkerRangeForUIElement(textbox)",
+       "textbox.AXTextMarkerRangeForUnorderedTextMarkers([text_range."
+       "anchor, text_range.focus])"},
+      R"~~(text_range={anchor: {:3, 0, down}, focus: {:3, 4, down}}
+textbox.AXTextMarkerRangeForUnorderedTextMarkers([text_range.anchor, text_range.focus])={anchor: {:3, 0, down}, focus: {:3, 4, down}}
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
-                       ParameterizedAttributes_TextMarkerArray) {
-  TestAndCheck(
-      R"~~(data:text/html,
-                    <textbox id="textbox">Text</textbox>)~~",
-      {{"text_range:= textbox.AXTextMarkerRangeForUIElement(textbox)", SCRIPT},
-       {"textbox.AXTextMarkerRangeForUnorderedTextMarkers([text_range."
-        "anchor, text_range.focus])",
-        SCRIPT}},
-      {{"*", "*"}},
-      R"~~(text_range={anchor: {:3, 0, down}, focus: {:3, 4, down}}
-textbox.AXTextMarkerRangeForUnorderedTextMarkers([text_range.anchor, text_range.focus])={anchor: {:3, 0, down}, focus: {:3, 4, down}}
+                       ParameterizedAttributes_NSRange) {
+  TestFormat(R"~~(data:text/html,
+                    <p contentEditable='true'>Text</p>)~~",
+             {":2;AXStringForRange({loc: 1, len: 2})=*"}, R"~~(AXWebArea
+++AXTextArea AXStringForRange({loc: 1, len: 2})='ex' AXValue='Text'
+++++AXStaticText AXValue='Text'
 )~~");
 }
 
@@ -280,9 +310,9 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_UIElement) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p contentEditable='true'>Text</p>)~~",
-               {":2;AXIndexForChildUIElement(:3)=*"}, R"~~(AXWebArea
+             {":2;AXIndexForChildUIElement(:3)=*"}, R"~~(AXWebArea
 ++AXTextArea AXIndexForChildUIElement(:3)=0 AXValue='Text'
 ++++AXStaticText AXValue='Text'
 )~~");
@@ -302,10 +332,10 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_TextMarker) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p>Text</p>)~~",
-               {":1;AXIndexForTextMarker({:2, 1, down})=*"},
-               R"~~(AXWebArea AXIndexForTextMarker({:2, 1, down})=1
+             {":1;AXIndexForTextMarker({:2, 1, down})=*"},
+             R"~~(AXWebArea AXIndexForTextMarker({:2, 1, down})=1
 ++AXGroup
 ++++AXStaticText AXValue='Text'
 )~~");
@@ -326,11 +356,11 @@
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        ParameterizedAttributes_TextMarkerRange) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p>Text</p>)~~",
-               {":2;AXStringForTextMarkerRange({anchor: {:2, 1, down}, focus: "
-                "{:2, 3, down}})=*"},
-               R"~~(AXWebArea
+             {":2;AXStringForTextMarkerRange({anchor: {:2, 1, down}, focus: "
+              "{:2, 3, down}})=*"},
+             R"~~(AXWebArea
 ++AXGroup AXStringForTextMarkerRange({anchor: {:2, 1, down}, focus: {:2, 3, down}})='ex'
 ++++AXStaticText AXValue='Text'
 )~~");
@@ -352,114 +382,110 @@
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest, NestedCalls) {
-  TestAndCheck(R"~~(data:text/html,
+  TestFormat(R"~~(data:text/html,
                     <p>Text</p>)~~",
-               {":1;AXIndexForTextMarker(AXTextMarkerForIndex(0))"},
-               R"~~(AXWebArea AXIndexForTextMarker(AXTextMarkerForIndex(0))=0
+             {":1;AXIndexForTextMarker(AXTextMarkerForIndex(0))"},
+             R"~~(AXWebArea AXIndexForTextMarker(AXTextMarkerForIndex(0))=0
 ++AXGroup
 ++++AXStaticText AXValue='Text'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest, Script) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <input aria-label='input'>)~~",
-               {{":3.AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(:3.AXRole='AXTextField'
+             {":3.AXRole"},
+             R"~~(:3.AXRole='AXTextField'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_ByDOMId) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <input id='textbox' aria-label='input'>)~~",
-               {{"textbox.AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(textbox.AXRole='AXTextField'
+             {"textbox.AXRole"},
+             R"~~(textbox.AXRole='AXTextField'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_ByDOMId_WrongDOMId) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <input id='textbox' aria-label='input'>)~~",
-               {{"textbo.AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(textbo.AXRole=ERROR:FAILED_TO_PARSE
+             {"textbo.AXRole"},
+             R"~~(textbo.AXRole=ERROR:FAILED_TO_PARSE
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest, Script_Chain) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <input id='input' aria-label='input'>)~~",
-               {{"input.AXFocusableAncestor.AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(input.AXFocusableAncestor.AXRole='AXTextField'
+             {"input.AXFocusableAncestor.AXRole"},
+             R"~~(input.AXFocusableAncestor.AXRole='AXTextField'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_Chain_Array) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>)~~",
-               {{"p.AXChildren[0].AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(p.AXChildren[0].AXRole='AXStaticText'
+             {"p.AXChildren[0].AXRole"},
+             R"~~(p.AXChildren[0].AXRole='AXStaticText'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_Chain_Array_OutOfRange) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>)~~",
-               {{"p.AXChildren[9999].AXRole", SCRIPT}}, {{"*", "*"}},
-               R"~~(p.AXChildren[9999].AXRole=ERROR:FAILED_TO_PARSE
+             {"p.AXChildren[9999].AXRole"},
+             R"~~(p.AXChildren[9999].AXRole=ERROR:FAILED_TO_PARSE
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_Chain_TextRange_Anchor) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>)~~",
-               {{"p.AXTextMarkerRangeForUIElement(p).anchor", SCRIPT}},
-               {{"*", "*"}},
-               R"~~(p.AXTextMarkerRangeForUIElement(p).anchor={:2, 0, down}
+             {"p.AXTextMarkerRangeForUIElement(p).anchor"},
+             R"~~(p.AXTextMarkerRangeForUIElement(p).anchor={:2, 0, down}
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_Chain_TextRange_Focus) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>)~~",
-               {{"p.AXTextMarkerRangeForUIElement(p).focus", SCRIPT}},
-               {{"*", "*"}},
-               R"~~(p.AXTextMarkerRangeForUIElement(p).focus={:2, 9, down}
+             {"p.AXTextMarkerRangeForUIElement(p).focus"},
+             R"~~(p.AXTextMarkerRangeForUIElement(p).focus={:2, 9, down}
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_Variables_AXElement) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <p id='p'>Paragraph</p>)~~",
-               {{"text:= p.AXChildren[0]", SCRIPT}, {"text.AXRole", SCRIPT}},
-               {{"*", "*"}},
-               R"~~(text=:3
+             {"text:= p.AXChildren[0]", "text.AXRole"},
+             R"~~(text=:3
 text.AXRole='AXStaticText'
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_ActionNames) {
-  TestAndCheck(
+  TestScript(
       R"~~(data:text/html,
                     <button id='button'>Press me</button>)~~",
-      {{"button.AXActionNames", SCRIPT}}, {{"*", "*"}},
+      {"button.AXActionNames"},
       R"~~(button.AXActionNames=['AXPress', 'AXShowMenu', 'AXScrollToVisible']
 )~~");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
                        Script_PerformAction) {
-  TestAndCheck(R"~~(data:text/html,
+  TestScript(R"~~(data:text/html,
                     <button id='button'>Press me</button>)~~",
-               {{"button.AXPerformAction(AXPress)", SCRIPT}}, {{"*", "*"}},
-               R"~~()~~");
+             {"button.AXPerformAction(AXPress)"}, R"~~()~~");
 }
 
 }  // namespace content
diff --git a/content/browser/accessibility/ax_platform_node_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_win_browsertest.cc
index 5d54ce1..cf19204 100644
--- a/content/browser/accessibility/ax_platform_node_win_browsertest.cc
+++ b/content/browser/accessibility/ax_platform_node_win_browsertest.cc
@@ -465,7 +465,7 @@
   LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
       <!DOCTYPE html>
       <html>
-        </body>
+        <body>
           <div id="id"></div>
         </body>
       </html>
@@ -493,6 +493,50 @@
   EXPECT_EQ(0, expected_scoped_variant.Compare(scoped_variant));
 }
 
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinUIABrowserTest, UIAScrollIntoView) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div id="id" style="height: 20px; overflow: scroll;">
+            <ul>
+              <li>Item 1</li>
+              <li>Item 2</li>
+              <li>Item 3</li>
+              <li>Item 4</li>
+              <li>Item 5</li>
+              <li>Item 6</li>
+            </ul>
+          </div>
+        </body>
+      </html>
+  )HTML"));
+
+  BrowserAccessibility* root_browser_accessibility = GetRootAndAssertNonNull();
+  BrowserAccessibilityComWin* root_browser_accessibility_com_win =
+      ToBrowserAccessibilityWin(root_browser_accessibility)->GetCOM();
+  ASSERT_NE(nullptr, root_browser_accessibility_com_win);
+
+  BrowserAccessibility* browser_accessibility =
+      root_browser_accessibility->PlatformDeepestLastChild();
+  ASSERT_NE(nullptr, browser_accessibility);
+  ASSERT_EQ(ax::mojom::Role::kStaticText, browser_accessibility->GetRole());
+  BrowserAccessibilityComWin* browser_accessibility_com_win =
+      ToBrowserAccessibilityWin(browser_accessibility)->GetCOM();
+  ASSERT_NE(nullptr, browser_accessibility_com_win);
+
+  ui::AXPlatformNodeWin* platform_node = static_cast<ui::AXPlatformNodeWin*>(
+      ui::AXPlatformNode::FromNativeViewAccessible(
+          browser_accessibility->GetNativeViewAccessible()));
+  ASSERT_NE(nullptr, platform_node);
+
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kLocationChanged);
+  EXPECT_HRESULT_SUCCEEDED(platform_node->ScrollIntoView());
+  waiter.WaitForNotification();
+}
+
 IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinUIABrowserTest,
                        UIAGetPropertyValueCulture) {
   LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 9b6f48c..b99909e 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -419,7 +419,7 @@
   return node;
 }
 
-BrowserAccessibilityManager* DumpAccessibilityTestBase::GetManager() {
+BrowserAccessibilityManager* DumpAccessibilityTestBase::GetManager() const {
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(shell()->web_contents());
   return web_contents->GetRootBrowserAccessibilityManager();
@@ -430,6 +430,67 @@
   return AXInspectFactory::CreateFormatter(GetParam());
 }
 
+std::pair<base::Value, std::vector<std::string>>
+DumpAccessibilityTestBase::CaptureEvents(
+    InvokeAction invoke_action,
+    std::vector<std::string>& run_until) const {
+  // Create a new Event Recorder for the run.
+  std::unique_ptr<ui::AXEventRecorder> event_recorder =
+      AXInspectFactory::CreateRecorder(GetParam(), GetManager(),
+                                       base::GetCurrentProcId(), {});
+  event_recorder->SetOnlyWebEvents(true);
+
+  // Create a waiter that waits for any one accessibility event.
+  // This will ensure that after calling the go() function, we
+  // block until we've received an accessibility event generated as
+  // a result of this function.
+  std::unique_ptr<AccessibilityNotificationWaiter> waiter =
+      std::make_unique<AccessibilityNotificationWaiter>(
+          shell()->web_contents(), ui::kAXModeComplete,
+          ax::mojom::Event::kNone);
+
+  // It's possible for platform events to be received after all blink or
+  // generated events have been fired. Unblock the |waiter| when this happens.
+  event_recorder->ListenToEvents(
+      base::BindRepeating(&DumpAccessibilityTestBase::OnEventRecorded,
+                          base::Unretained(this), waiter.get()));
+
+  base::Value action_result = std::move(invoke_action).Run();
+
+  for (;;) {
+    // Wait for at least one event. This may unblock either when |waiter|
+    // observes either an ax::mojom::Event or ui::AXEventGenerator::Event, or
+    // when |event_recorder| records a platform event.
+    waiter->WaitForNotification();
+    if (event_recorder->IsRunUntilEventSatisfied(run_until))
+      break;
+  }
+
+  event_recorder->StopListeningToEvents();
+
+  // More than one accessibility event could have been generated.
+  // To make sure we've received all accessibility events, add a
+  // sentinel by calling SignalEndOfTest and waiting for a kEndOfTest
+  // event in response.
+  waiter = std::make_unique<AccessibilityNotificationWaiter>(
+      shell()->web_contents(), ui::kAXModeComplete,
+      ax::mojom::Event::kEndOfTest);
+  GetManager()->SignalEndOfTest();
+  waiter->WaitForNotification();
+  event_recorder->WaitForDoneRecording();
+
+  // Dump the event logs, running them through any filters specified
+  // in the HTML file.
+  std::vector<std::string> event_logs = event_recorder->GetEventLogs();
+
+  // Sort the logs so that results are predictable. There are too many
+  // nondeterministic things that affect the exact order of events fired,
+  // so these tests shouldn't be used to make assertions about event order.
+  std::sort(event_logs.begin(), event_logs.end());
+
+  return std::make_pair(std::move(action_result), std::move(event_logs));
+}
+
 BrowserAccessibility* DumpAccessibilityTestBase::FindNodeInSubtree(
     BrowserAccessibility& node,
     const std::string& name) {
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.h b/content/browser/accessibility/dump_accessibility_browsertest_base.h
index 19914ff..1e83c727 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -11,6 +11,7 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "content/public/browser/ax_inspect_factory.h"
+#include "content/public/test/accessibility_notification_waiter.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/dump_accessibility_test_helper.h"
 #include "third_party/blink/public/common/features.h"
@@ -94,10 +95,16 @@
 
   // Retrieve the browser accessibility manager object for the current web
   // contents.
-  BrowserAccessibilityManager* GetManager();
+  BrowserAccessibilityManager* GetManager() const;
 
   std::unique_ptr<ui::AXTreeFormatter> CreateFormatter() const;
 
+  // Returns a list of captured events fired after the invoked action.
+  using InvokeAction = base::OnceCallback<base::Value()>;
+  std::pair<base::Value, std::vector<std::string>> CaptureEvents(
+      InvokeAction invoke_action,
+      std::vector<std::string>& run_until) const;
+
   // Test scenario loaded from the test file.
   ui::AXInspectScenario scenario_;
 
@@ -131,6 +138,11 @@
       const std::vector<std::string>& skip_urls);
 
   void WaitForAXTreeLoaded(WebContentsImpl* web_contents);
+
+  void OnEventRecorded(AccessibilityNotificationWaiter* waiter,
+                       const std::string& event) const {
+    waiter->Quit();
+  }
 };
 
 }  // namespace content
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 2a9415c..b4ed9bfd 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -25,7 +25,6 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/test/accessibility_notification_waiter.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -96,11 +95,6 @@
   void RunEventTest(const base::FilePath::CharType* file_path);
 
  private:
-  void OnEventRecorded(AccessibilityNotificationWaiter* waiter,
-                       const std::string& event) {
-    waiter->Quit();
-  }
-
   std::string initial_tree_;
   std::string final_tree_;
 };
@@ -109,78 +103,28 @@
     std::vector<std::string>& run_until) {
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(shell()->web_contents());
-  base::ProcessId pid = base::GetCurrentProcId();
 
   // Save a copy of the accessibility tree (as a text dump); we'll
   // log this for the user later if the test fails.
   initial_tree_ = DumpUnfilteredAccessibilityTreeAsString();
 
-  // Create a waiter that waits for any one accessibility event.
-  // This will ensure that after calling the go() function, we
-  // block until we've received an accessibility event generated as
-  // a result of this function.
-  std::unique_ptr<AccessibilityNotificationWaiter> waiter;
-
   final_tree_.clear();
   bool run_go_again = false;
   std::vector<std::string> result;
   do {
-    // Create a new Event Recorder for the run.
-    std::unique_ptr<ui::AXEventRecorder> event_recorder =
-        AXInspectFactory::CreateRecorder(
-            GetParam(), web_contents->GetRootBrowserAccessibilityManager(), pid,
-            {});
-    event_recorder->SetOnlyWebEvents(true);
-
-    waiter = std::make_unique<AccessibilityNotificationWaiter>(
-        shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kNone);
-
-    // It's possible for platform events to be received after all blink or
-    // generated events have been fired. Unblock the |waiter| when this happens.
-    event_recorder->ListenToEvents(
-        base::BindRepeating(&DumpAccessibilityEventsTest::OnEventRecorded,
-                            base::Unretained(this), waiter.get()));
-
-    base::Value go_results =
-        ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "go()");
-    run_go_again = go_results.is_bool() && go_results.GetBool();
-
-    for (;;) {
-      // Wait for at least one event. This may unblock either when |waiter|
-      // observes either an ax::mojom::Event or ui::AXEventGenerator::Event, or
-      // when |event_recorder| records a platform event.
-      waiter->WaitForNotification();
-      if (event_recorder->IsRunUntilEventSatisfied(run_until))
-        break;
-    }
-
-    event_recorder->StopListeningToEvents();
-
-    // More than one accessibility event could have been generated.
-    // To make sure we've received all accessibility events, add a
-    // sentinel by calling SignalEndOfTest and waiting for a kEndOfTest
-    // event in response.
-    waiter = std::make_unique<AccessibilityNotificationWaiter>(
-        shell()->web_contents(), ui::kAXModeComplete,
-        ax::mojom::Event::kEndOfTest);
-    BrowserAccessibilityManager* manager =
-        web_contents->GetRootBrowserAccessibilityManager();
-    manager->SignalEndOfTest();
-    waiter->WaitForNotification();
-    event_recorder->WaitForDoneRecording();
-
-    // Save a copy of the final accessibility tree (as a text dump); we'll
-    // log this for the user later if the test fails.
-    final_tree_.append(DumpUnfilteredAccessibilityTreeAsString());
+    base::Value go_results;
+    std::vector<std::string> event_logs;
 
     // Dump the event logs, running them through any filters specified
     // in the HTML file.
-    std::vector<std::string> event_logs = event_recorder->GetEventLogs();
-
-    // Sort the logs so that results are predictable. There are too many
-    // nondeterministic things that affect the exact order of events fired,
-    // so these tests shouldn't be used to make assertions about event order.
-    std::sort(event_logs.begin(), event_logs.end());
+    std::tie(go_results, event_logs) =
+        CaptureEvents(base::BindOnce(&ExecuteScriptAndGetValue,
+                                     web_contents->GetMainFrame(), "go()"),
+                      run_until);
+    run_go_again = go_results.is_bool() && go_results.GetBool();
+    // Save a copy of the final accessibility tree (as a text dump); we'll
+    // log this for the user later if the test fails.
+    final_tree_.append(DumpUnfilteredAccessibilityTreeAsString());
 
     for (auto& event_log : event_logs) {
       if (AXTreeFormatter::MatchesPropertyFilters(scenario_.property_filters,
diff --git a/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc b/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc
index bc572ea4..88cf749e 100644
--- a/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc
@@ -4,14 +4,17 @@
 
 #include "base/files/file_util.h"
 #include "build/build_config.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/dump_accessibility_browsertest_base.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
 
 namespace content {
 
 using ui::AXPropertyFilter;
+using ui::AXScriptInstruction;
 using ui::AXTreeFormatter;
 
 // See content/test/data/accessibility/readme.md for an overview.
@@ -35,20 +38,69 @@
     property_filters->push_back(AXPropertyFilter(filter, type));
   }
 
+  base::Value EvaluateScript(
+      AXTreeFormatter* formatter,
+      BrowserAccessibility* root,
+      const std::vector<AXScriptInstruction>& instructions,
+      size_t start_index,
+      size_t end_index) {
+    return base::Value(
+        formatter->EvaluateScript(root, instructions, start_index, end_index));
+  }
+
   std::vector<std::string> Dump(std::vector<std::string>& unused) override {
+    std::vector<std::string> dump;
     std::unique_ptr<AXTreeFormatter> formatter(CreateFormatter());
+    BrowserAccessibility* root = GetManager()->GetRoot();
 
-    // Set test provided property filters.
-    formatter->SetPropertyFilters(scenario_.property_filters,
-                                  AXTreeFormatter::kFiltersDefaultSet);
+    size_t start_index = 0;
+    size_t length = scenario_.script_instructions.size();
+    while (start_index < length) {
+      std::string wait_for;
+      size_t index = start_index;
+      for (; index < length; index++) {
+        if (scenario_.script_instructions[index].IsEvent()) {
+          wait_for = scenario_.script_instructions[index].AsEvent();
+          break;
+        }
+      }
 
-    // No accessible tree nodes, just run scripts.
-    formatter->SetNodeFilters({{"*", "*"}});
+      std::string actual_contents;
+      if (wait_for.empty()) {
+        actual_contents = formatter->EvaluateScript(
+            root, scenario_.script_instructions, start_index, index);
+      } else {
+        std::vector<std::string> run_until{wait_for};
+        auto pair = CaptureEvents(
+            base::BindOnce(&DumpAccessibilityScriptTest::EvaluateScript,
+                           base::Unretained(this), formatter.get(), root,
+                           scenario_.script_instructions, start_index, index),
+            run_until);
+        actual_contents = pair.first.GetString();
+        for (auto event : pair.second) {
+          actual_contents += event + '\n';
+        }
+      }
 
-    std::string actual_contents =
-        formatter->Format(GetRootAccessibilityNode(shell()->web_contents()));
-    return base::SplitString(actual_contents, "\n", base::KEEP_WHITESPACE,
-                             base::SPLIT_WANT_NONEMPTY);
+      auto chunk =
+          base::SplitString(actual_contents, "\n", base::KEEP_WHITESPACE,
+                            base::SPLIT_WANT_NONEMPTY);
+      dump.insert(dump.end(), chunk.begin(), chunk.end());
+
+      start_index = index + 1;
+    }
+    return dump;
+  }
+
+  void RunMacActionTest(const base::FilePath::CharType* file_path) {
+    base::FilePath test_path = GetTestFilePath("accessibility", "mac/action");
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
+    }
+    base::FilePath html_file = test_path.Append(base::FilePath(file_path));
+
+    RunTest(html_file, "accessibility/mac/action");
   }
 
   void RunMacTextMarkerTest(const base::FilePath::CharType* file_path) {
@@ -88,6 +140,10 @@
                          ::testing::Values(AXInspectFactory::kMac),
                          TestPassToString());
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest, AXPressButton) {
+  RunMacActionTest(FILE_PATH_LITERAL("ax-press-button.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest,
                        AXNextWordEndTextMarkerForTextMarker) {
   RunMacTextMarkerTest(
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 0940758..81c58bd 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1176,6 +1176,11 @@
   RunAriaTest(FILE_PATH_LITERAL("aria-radiogroup.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityAriaRadioInShadowRoot) {
+  RunAriaTest(FILE_PATH_LITERAL("aria-radio-in-shadow-root.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaReadonly) {
   RunAriaTest(FILE_PATH_LITERAL("aria-readonly.html"));
 }
diff --git a/content/browser/conversions/conversion_manager_impl.cc b/content/browser/conversions/conversion_manager_impl.cc
index 77ce3843a..f706085 100644
--- a/content/browser/conversions/conversion_manager_impl.cc
+++ b/content/browser/conversions/conversion_manager_impl.cc
@@ -87,7 +87,7 @@
 }
 
 ConversionManagerImpl::ConversionManagerImpl(
-    StoragePartition* storage_partition,
+    StoragePartitionImpl* storage_partition,
     const base::FilePath& user_data_directory,
     scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy)
     : ConversionManagerImpl(
diff --git a/content/browser/conversions/conversion_manager_impl.h b/content/browser/conversions/conversion_manager_impl.h
index 4138cf5..1fb7c4b 100644
--- a/content/browser/conversions/conversion_manager_impl.h
+++ b/content/browser/conversions/conversion_manager_impl.h
@@ -38,7 +38,7 @@
 extern CONTENT_EXPORT const base::TimeDelta
     kConversionManagerQueueReportsInterval;
 
-class StoragePartition;
+class StoragePartitionImpl;
 
 // Provides access to the manager owned by the default StoragePartition.
 class ConversionManagerProviderImpl : public ConversionManager::Provider {
@@ -87,7 +87,7 @@
       size_t max_sent_reports_to_store) WARN_UNUSED_RESULT;
 
   ConversionManagerImpl(
-      StoragePartition* storage_partition,
+      StoragePartitionImpl* storage_partition,
       const base::FilePath& user_data_directory,
       scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
   ConversionManagerImpl(const ConversionManagerImpl& other) = delete;
diff --git a/content/browser/conversions/conversion_reporter_impl.cc b/content/browser/conversions/conversion_reporter_impl.cc
index da325ad..455ee4a 100644
--- a/content/browser/conversions/conversion_reporter_impl.cc
+++ b/content/browser/conversions/conversion_reporter_impl.cc
@@ -17,12 +17,15 @@
 namespace content {
 
 ConversionReporterImpl::ConversionReporterImpl(
-    StoragePartition* storage_partition,
+    StoragePartitionImpl* storage_partition,
     const base::Clock* clock)
     : clock_(clock),
-      partition_(static_cast<StoragePartitionImpl*>(storage_partition)),
+      partition_(storage_partition),
       network_sender_(
-          std::make_unique<ConversionNetworkSenderImpl>(storage_partition)) {}
+          std::make_unique<ConversionNetworkSenderImpl>(storage_partition)) {
+  DCHECK(clock_);
+  DCHECK(partition_);
+}
 
 ConversionReporterImpl::~ConversionReporterImpl() = default;
 
diff --git a/content/browser/conversions/conversion_reporter_impl.h b/content/browser/conversions/conversion_reporter_impl.h
index 9aad6b7..9d9e3c9 100644
--- a/content/browser/conversions/conversion_reporter_impl.h
+++ b/content/browser/conversions/conversion_reporter_impl.h
@@ -25,7 +25,6 @@
 
 namespace content {
 
-class StoragePartition;
 class StoragePartitionImpl;
 
 // This class is responsible for managing the dispatch of conversion reports to
@@ -51,7 +50,7 @@
                             ReportSentCallback sent_callback) = 0;
   };
 
-  ConversionReporterImpl(StoragePartition* storage_partition,
+  ConversionReporterImpl(StoragePartitionImpl* storage_partition,
                          const base::Clock* clock);
   ConversionReporterImpl(const ConversionReporterImpl&) = delete;
   ConversionReporterImpl& operator=(const ConversionReporterImpl&) = delete;
diff --git a/content/browser/conversions/conversion_reporter_impl_unittest.cc b/content/browser/conversions/conversion_reporter_impl_unittest.cc
index 7703b00a..953be29 100644
--- a/content/browser/conversions/conversion_reporter_impl_unittest.cc
+++ b/content/browser/conversions/conversion_reporter_impl_unittest.cc
@@ -16,8 +16,8 @@
 #include "content/browser/conversions/conversion_manager.h"
 #include "content/browser/conversions/conversion_test_utils.h"
 #include "content/browser/conversions/sent_report_info.h"
+#include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_browser_context.h"
@@ -73,7 +73,8 @@
       : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
         browser_context_(std::make_unique<TestBrowserContext>()),
         reporter_(std::make_unique<ConversionReporterImpl>(
-            browser_context_->GetDefaultStoragePartition(),
+            static_cast<StoragePartitionImpl*>(
+                browser_context_->GetDefaultStoragePartition()),
             task_environment_.GetMockClock())) {
     auto network_sender = std::make_unique<MockNetworkSender>();
     sender_ = network_sender.get();
diff --git a/content/browser/indexed_db/indexed_db_feature_observer_browsertest.cc b/content/browser/indexed_db/indexed_db_feature_observer_browsertest.cc
index 9c6af62a..67c3335 100644
--- a/content/browser/indexed_db/indexed_db_feature_observer_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_feature_observer_browsertest.cc
@@ -8,6 +8,7 @@
 #include "build/chromeos_buildflags.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "content/browser/feature_observer.h"
+#include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/feature_observer_client.h"
 #include "content/public/browser/render_process_host.h"
@@ -253,9 +254,16 @@
 
 // Verify that content::FeatureObserver is notified when a frame with active
 // IndexedDB connections is navigated away.
-// https://crbug.com/1218731 fails when BackforwardCache is enabled.
-IN_PROC_BROWSER_TEST_F(IndexedDBFeatureObserverBrowserTest,
-                       DISABLED_ObserverNavigate) {
+IN_PROC_BROWSER_TEST_F(IndexedDBFeatureObserverBrowserTest, ObserverNavigate) {
+  // The test expects the OnStopUsing() method to be called, which won't happen
+  // if the BackForwardCache is enabled.
+  // TODO(https://crbug.com/1228693): Figure out why this is happening.
+  shell()
+      ->web_contents()
+      ->GetController()
+      .GetBackForwardCache()
+      .DisableForTesting(content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   if (!CheckShouldRunTestAndNavigate())
     return;
 
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index 685fa61..2509b3c 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -2128,15 +2128,10 @@
 // Ensure portal activations respect navigation precedence. If there is an
 // ongoing browser initiated navigation, then a portal activation without user
 // activation cannot proceed.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_NavigationPrecedence DISABLED_NavigationPrecedence
-#else
-#define MAYBE_NavigationPrecedence NavigationPrecedence
-#endif
-IN_PROC_BROWSER_TEST_F(PortalBrowserTest, MAYBE_NavigationPrecedence) {
+IN_PROC_BROWSER_TEST_F(PortalBrowserTest, NavigationPrecedence) {
   GURL main_url1(embedded_test_server()->GetURL("portal.test", "/title1.html"));
   GURL main_url2(embedded_test_server()->GetURL("portal.test", "/title2.html"));
+  GURL main_url3(embedded_test_server()->GetURL("portal.test", "/title3.html"));
   ASSERT_TRUE(NavigateToURL(shell(), main_url1));
   ASSERT_TRUE(NavigateToURL(shell(), main_url2));
   WebContentsImpl* web_contents_impl =
@@ -2146,18 +2141,17 @@
   GURL portal_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
   CreatePortalToUrl(web_contents_impl, portal_url);
 
-  TestNavigationManager pending_back_navigation(web_contents_impl, main_url1);
-  ASSERT_TRUE(web_contents_impl->GetController().CanGoBack());
-  web_contents_impl->GetController().GoBack();
-  EXPECT_TRUE(pending_back_navigation.WaitForRequestStart());
+  TestNavigationManager pending_navigation(web_contents_impl, main_url3);
+  shell()->LoadURL(main_url3);
+  EXPECT_TRUE(pending_navigation.WaitForRequestStart());
 
   EXPECT_EQ("reject", EvalJs(main_frame,
                              "document.querySelector('portal').activate().then("
                              "    () => 'resolve', () => 'reject');",
                              EXECUTE_SCRIPT_NO_USER_GESTURE));
 
-  pending_back_navigation.WaitForNavigationFinished();
-  EXPECT_TRUE(pending_back_navigation.was_successful());
+  pending_navigation.WaitForNavigationFinished();
+  EXPECT_TRUE(pending_navigation.was_successful());
 }
 
 IN_PROC_BROWSER_TEST_F(PortalBrowserTest, RejectActivationOfErrorPages) {
diff --git a/content/browser/prerender/prerender_host.h b/content/browser/prerender/prerender_host.h
index efc7cfb..e23d8def 100644
--- a/content/browser/prerender/prerender_host.h
+++ b/content/browser/prerender/prerender_host.h
@@ -72,7 +72,8 @@
     kClientCertRequested = 19,
     kNavigationRequestNetworkError = 20,
     kMaxNumOfRunningPrerendersExceeded = 21,
-    kMaxValue = kMaxNumOfRunningPrerendersExceeded
+    kCancelAllHostsForTesting = 22,
+    kMaxValue = kCancelAllHostsForTesting
   };
 
   PrerenderHost(blink::mojom::PrerenderAttributesPtr attributes,
diff --git a/content/browser/prerender/prerender_host_registry.cc b/content/browser/prerender/prerender_host_registry.cc
index 33ad2dd..1546d29 100644
--- a/content/browser/prerender/prerender_host_registry.cc
+++ b/content/browser/prerender/prerender_host_registry.cc
@@ -277,6 +277,21 @@
   return nullptr;
 }
 
+void PrerenderHostRegistry::CancelAllHostsForTesting() {
+  DCHECK(reserved_prerender_host_by_frame_tree_node_id_.empty())
+      << "It is not possible to cancel reserved hosts, so they must not exist "
+         "when trying to cancel all hosts";
+
+  for (auto& iter : prerender_host_by_frame_tree_node_id_) {
+    // Asynchronously delete the prerender host.
+    ScheduleToDeleteAbandonedHost(
+        std::move(iter.second),
+        PrerenderHost::FinalStatus::kCancelAllHostsForTesting);
+  }
+  // After we're done scheduling deletion, clear the map.
+  prerender_host_by_frame_tree_node_id_.clear();
+}
+
 base::WeakPtr<PrerenderHostRegistry> PrerenderHostRegistry::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
diff --git a/content/browser/prerender/prerender_host_registry.h b/content/browser/prerender/prerender_host_registry.h
index e4ec9755..b68b097 100644
--- a/content/browser/prerender/prerender_host_registry.h
+++ b/content/browser/prerender/prerender_host_registry.h
@@ -138,6 +138,11 @@
   // the URL doesn't match any non-reserved host.
   PrerenderHost* FindHostByUrlForTesting(const GURL& prerendering_url);
 
+  // Cancels all hosts. Since reserved hosts can't be canceled, this will
+  // DCHECK when `reserved_prerender_host_by_frame_tree_node_id_` is not empty.
+  // This will cancel all hosts in `prerender_host_by_frame_tree_node_id_`.
+  void CancelAllHostsForTesting();
+
   base::WeakPtr<PrerenderHostRegistry> GetWeakPtr();
 
  private:
diff --git a/content/browser/renderer_host/back_forward_cache_metrics_browsertest.cc b/content/browser/renderer_host/back_forward_cache_metrics_browsertest.cc
index d82151b3..03d5aaa 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics_browsertest.cc
+++ b/content/browser/renderer_host/back_forward_cache_metrics_browsertest.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -61,12 +62,13 @@
 using UkmMetrics = ukm::TestUkmRecorder::HumanReadableUkmMetrics;
 using UkmEntry = ukm::TestUkmRecorder::HumanReadableUkmEntry;
 
+enum BackForwardCacheStatus { kDisabled = 0, kEnabled = 1 };
 }  // namespace
 
-class BackForwardCacheMetricsBrowserTest : public ContentBrowserTest,
-                                           public WebContentsObserver {
+class BackForwardCacheMetricsBrowserTestBase : public ContentBrowserTest,
+                                               public WebContentsObserver {
  public:
-  BackForwardCacheMetricsBrowserTest() {
+  BackForwardCacheMetricsBrowserTestBase() {
     geolocation_override_ =
         std::make_unique<device::ScopedGeolocationOverrider>(1.0, 1.0);
   }
@@ -105,18 +107,40 @@
   std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_override_;
 };
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_UKM DISABLED_UKM
-#else
-#define MAYBE_UKM UKM
-#endif
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, MAYBE_UKM) {
+class BackForwardCacheMetricsBrowserTest
+    : public BackForwardCacheMetricsBrowserTestBase,
+      public testing::WithParamInterface<BackForwardCacheStatus> {
+ public:
+  BackForwardCacheMetricsBrowserTest() {
+    if (GetParam() == BackForwardCacheStatus::kEnabled) {
+      // Enable BackForwardCache.
+      feature_list_.InitWithFeaturesAndParameters(
+          {{features::kBackForwardCache, {{"enable_same_site", "true"}}},
+           {kBackForwardCacheNoTimeEviction, {}}},
+          // Allow BackForwardCache for all devices regardless of their memory.
+          {features::kBackForwardCacheMemoryControls});
+      DCHECK(IsSameSiteBackForwardCacheEnabled());
+    } else {
+      feature_list_.InitAndDisableFeature(features::kBackForwardCache);
+      DCHECK(!IsBackForwardCacheEnabled());
+    }
+  }
+
+  static std::string DescribeParams(
+      const testing::TestParamInfo<ParamType>& info) {
+    return info.param ? "BFCacheEnabled" : "BFCacheDisabled";
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, UKM) {
   ukm::TestAutoSetUkmRecorder recorder;
 
-  const GURL url1(
-      embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
-  const GURL url2(embedded_test_server()->GetURL("/title1.html"));
+  const GURL url1(embedded_test_server()->GetURL(
+      "a.com", "/frame_tree/page_with_one_frame.html"));
+  const GURL url2(embedded_test_server()->GetURL("b.com", "/title1.html"));
   const char kChildFrameId[] = "child0";
 
   EXPECT_TRUE(NavigateToURL(shell(), url2));
@@ -138,7 +162,11 @@
 
   {
     // We are waiting for two navigations here: main frame and subframe.
-    TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+    // However, when back/forward cache is enabled, back navigation to a page
+    // with subframes will not trigger a subframe navigation (since the
+    // subframe is cached with the page).
+    TestNavigationObserver navigation_observer(
+        shell()->web_contents(), 1 + (IsBackForwardCacheEnabled() ? 0 : 1));
     shell()->GoBackOrForward(-1);
     navigation_observer.WaitForNavigationFinished();
   }
@@ -161,10 +189,13 @@
   // The navigation entries are:
   // [*url2, url1(subframe), url1(url2), url2].
 
-  // There are five new navigations and four back navigations.
+  // There are five new navigations and four back navigations (3 if
+  // back/forward cache is enabled, as the first subframe back navigation won't
+  // happen).
   // Navigations 1, 2, 5 are main frame. Navigation 3 is an initial navigation
   // in the subframe, navigation 4 is a subframe navigation.
-  ASSERT_EQ(navigation_ids_.size(), static_cast<size_t>(9));
+  ASSERT_EQ(navigation_ids_.size(),
+            static_cast<size_t>(8 + (IsBackForwardCacheEnabled() ? 0 : 1)));
   ukm::SourceId id1 = ToSourceId(navigation_ids_[0]);
   ukm::SourceId id2 = ToSourceId(navigation_ids_[1]);
   // ukm::SourceId id3 = ToSourceId(navigation_ids_[2]);
@@ -173,23 +204,25 @@
   ukm::SourceId id6 = ToSourceId(navigation_ids_[5]);
   // ukm::SourceId id7 = ToSourceId(navigation_ids_[6]);
   // ukm::SourceId id8 = ToSourceId(navigation_ids_[7]);
-  ukm::SourceId id9 = ToSourceId(navigation_ids_[8]);
+  ukm::SourceId id_last =
+      ToSourceId(navigation_ids_[navigation_ids_.size() - 1]);
 
   std::string last_navigation_id =
       "LastCommittedCrossDocumentNavigationSourceIdForTheSameDocument";
 
-  // First back-forward navigation (#6) navigates back to navigation #3, but it
+  // First back/forward navigation (#6) navigates back to navigation #3, but it
   // is the subframe navigation, so the corresponding main frame navigation is
   // #2. Navigation #7 loads the subframe for navigation #6.
-  // Second back-forward navigation (#8) navigates back to navigation #2,
-  // but it is subframe navigation and not reflected here. Third back-forward
+  // Second back/forward navigation (#8) navigates back to navigation #2,
+  // but it is subframe navigation and not reflected here. Third back/forward
   // navigation (#9) navigates back to navigation #1.
-  EXPECT_THAT(recorder.GetEntries("HistoryNavigation", {last_navigation_id}),
-              testing::ElementsAre(UkmEntry{id6, {{last_navigation_id, id2}}},
-                                   UkmEntry{id9, {{last_navigation_id, id1}}}));
+  EXPECT_THAT(
+      recorder.GetEntries("HistoryNavigation", {last_navigation_id}),
+      testing::ElementsAre(UkmEntry{id6, {{last_navigation_id, id2}}},
+                           UkmEntry{id_last, {{last_navigation_id, id1}}}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, CloneAndGoBack) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, CloneAndGoBack) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url1(embedded_test_server()->GetURL("/title1.html"));
@@ -249,7 +282,7 @@
 }
 
 // Confirms that UKMs are not recorded on reloading.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, Reload) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, Reload) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html"));
@@ -285,7 +318,7 @@
                                    UkmEntry{id6, {{last_navigation_id, id4}}}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        SameDocumentNavigationAndGoBackImmediately) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -308,7 +341,7 @@
               testing::ElementsAre());
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        GoBackToSameDocumentNavigationEntry) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -337,14 +370,14 @@
   // the first navigation. The third navigation is a regular navigation. The
   // fourth navigation goes back.
   //
-  // The back-forward navigation (#4) goes back to the navigation entry created
+  // The back/forward navigation (#4) goes back to the navigation entry created
   // by the same-document navigation (#2), so we expect the id corresponding to
   // the previous non-same-document navigation (#1).
   EXPECT_THAT(recorder.GetEntries("HistoryNavigation", {last_navigation_id}),
               testing::ElementsAre(UkmEntry{id4, {{last_navigation_id, id1}}}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        GoBackToSameDocumentNavigationEntry2) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -373,7 +406,7 @@
   // the first navigation. The third navigation is a regular navigation. The
   // fourth navigation goes back.
   //
-  // The back-forward navigation (#4) goes back to navigation #1, skipping a
+  // The back/forward navigation (#4) goes back to navigation #1, skipping a
   // navigation entry generated by same-document navigation (#2). Ensure that
   // the recorded id belongs to the navigation #1, not #2.
   EXPECT_THAT(recorder.GetEntries("HistoryNavigation", {last_navigation_id}),
@@ -430,7 +463,7 @@
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, Features_MainFrame) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, Features_MainFrame) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url1(embedded_test_server()->GetURL(
@@ -455,7 +488,7 @@
               testing::ElementsAre(FeatureUsage{id3, 0, 0, 0}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        Features_MainFrame_CrossOriginNavigation) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -481,30 +514,30 @@
               testing::ElementsAre(FeatureUsage{id3, 0, 0, 0}));
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_Features_SameOriginSubframes DISABLED_Features_SameOriginSubframes
-#else
-#define MAYBE_Features_SameOriginSubframes Features_SameOriginSubframes
-#endif
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
-                       MAYBE_Features_SameOriginSubframes) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
+                       Features_SameOriginSubframes) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url1(embedded_test_server()->GetURL(
       "/back_forward_cache/page_with_same_origin_subframe_with_pageshow.html"));
-  const GURL url2(embedded_test_server()->GetURL("/title1.html"));
+  const GURL url2(embedded_test_server()->GetURL("b.com", "/title1.html"));
 
   EXPECT_TRUE(NavigateToURL(shell(), url1));
   EXPECT_TRUE(NavigateToURL(shell(), url2));
 
   {
-    TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+    // We are waiting for two navigations here: main frame and subframe.
+    // However, when back/forward cache is enabled, back navigation to a page
+    // with subframes will not trigger a subframe navigation (since the
+    // subframe is cached with the page).
+    TestNavigationObserver navigation_observer(
+        shell()->web_contents(), 1 + (IsBackForwardCacheEnabled() ? 0 : 1));
     shell()->GoBackOrForward(-1);
     navigation_observer.WaitForNavigationFinished();
   }
 
-  ASSERT_EQ(navigation_ids_.size(), static_cast<size_t>(5));
+  ASSERT_EQ(navigation_ids_.size(),
+            static_cast<size_t>(4 + (IsBackForwardCacheEnabled() ? 0 : 1)));
   // ukm::SourceId id1 = ToSourceId(navigation_ids_[0]);
   // ukm::SourceId id2 = ToSourceId(navigation_ids_[1]);
   // ukm::SourceId id3 = ToSourceId(navigation_ids_[2]);
@@ -514,7 +547,7 @@
               testing::ElementsAre(FeatureUsage{id4, 0, 0, 0}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        Features_SameOriginSubframes_CrossOriginNavigation) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -528,7 +561,7 @@
   web_contents()->GetController().GoBack();
   EXPECT_TRUE(WaitForLoadStop(web_contents()));
 
-  // When the page is restored from back-forward cache, there is one navigation
+  // When the page is restored from back/forward cache, there is one navigation
   // corresponding to the bfcache restore. Whereas, when the page is reloaded,
   // there are two navigations i.e., one loading the main frame and one loading
   // the subframe.
@@ -542,32 +575,31 @@
               testing::ElementsAre(FeatureUsage{id4, 0, 0, 0}));
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_Features_CrossOriginSubframes \
-  DISABLED_Features_CrossOriginSubframes
-#else
-#define MAYBE_Features_CrossOriginSubframes Features_CrossOriginSubframes
-#endif
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest,
-                       MAYBE_Features_CrossOriginSubframes) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
+                       Features_CrossOriginSubframes) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url1(embedded_test_server()->GetURL(
       "/back_forward_cache/"
       "page_with_cross_origin_subframe_with_pageshow.html"));
-  const GURL url2(embedded_test_server()->GetURL("/title1.html"));
+  const GURL url2(embedded_test_server()->GetURL("b.com", "/title1.html"));
 
   EXPECT_TRUE(NavigateToURL(shell(), url1));
   EXPECT_TRUE(NavigateToURL(shell(), url2));
 
   {
-    TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+    // We are waiting for two navigations here: main frame and subframe.
+    // However, when back/forward cache is enabled, back navigation to a page
+    // with subframes will not trigger a subframe navigation (since the
+    // subframe is cached with the page).
+    TestNavigationObserver navigation_observer(
+        shell()->web_contents(), 1 + (IsBackForwardCacheEnabled() ? 0 : 1));
     shell()->GoBackOrForward(-1);
     navigation_observer.WaitForNavigationFinished();
   }
 
-  ASSERT_EQ(navigation_ids_.size(), static_cast<size_t>(5));
+  ASSERT_EQ(navigation_ids_.size(),
+            static_cast<size_t>(4 + (IsBackForwardCacheEnabled() ? 0 : 1)));
   // ukm::SourceId id1 = ToSourceId(navigation_ids_[0]);
   // ukm::SourceId id2 = ToSourceId(navigation_ids_[1]);
   // ukm::SourceId id3 = ToSourceId(navigation_ids_[2]);
@@ -577,7 +609,7 @@
               testing::ElementsAre(FeatureUsage{id4, 0, 0, 0}));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, DedicatedWorker) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, DedicatedWorker) {
   ukm::TestAutoSetUkmRecorder recorder;
 
   const GURL url(embedded_test_server()->GetURL(
@@ -601,7 +633,7 @@
 #else
 #define MAYBE_SharedWorker SharedWorker
 #endif
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, MAYBE_SharedWorker) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, MAYBE_SharedWorker) {
   const GURL url(embedded_test_server()->GetURL(
       "/back_forward_cache/page_with_shared_worker.html"));
 
@@ -616,7 +648,7 @@
                 blink::scheduler::WebSchedulerTrackedFeature::kSharedWorker));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsBrowserTest, Geolocation) {
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest, Geolocation) {
   const GURL url1(embedded_test_server()->GetURL("/title1.html"));
   EXPECT_TRUE(NavigateToURL(shell(), url1));
 
@@ -632,7 +664,7 @@
 }
 
 class RecordBackForwardCacheMetricsWithoutEnabling
-    : public BackForwardCacheMetricsBrowserTest {
+    : public BackForwardCacheMetricsBrowserTestBase {
  public:
   RecordBackForwardCacheMetricsWithoutEnabling() {
     // Sets the allowed websites for testing.
@@ -707,7 +739,7 @@
               1)));
 
   // BackForwardCache is disabled here, the navigation is not served from
-  // back-forward cache.
+  // back/forward cache.
   EXPECT_THAT(
       histogram_tester.GetAllSamples(kReloadsAfterHistoryNavigationHistogram),
       ElementsAre(Bucket(
@@ -744,28 +776,10 @@
           1)));
 }
 
-class BackForwardCacheEnabledMetricsBrowserTest
-    : public BackForwardCacheMetricsBrowserTest {
- protected:
-  BackForwardCacheEnabledMetricsBrowserTest() {
-    scoped_feature_list_.InitWithFeaturesAndParameters(
-        {{features::kBackForwardCache,
-          {// Set a very long TTL before expiration (longer than the test
-           // timeout) so tests that are expecting deletion don't pass when
-           // they shouldn't.
-           {"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}},
-        // Allow BackForwardCache for all devices regardless of their memory.
-        {features::kBackForwardCacheMemoryControls});
-  }
-
-  ~BackForwardCacheEnabledMetricsBrowserTest() override = default;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_F(BackForwardCacheEnabledMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        RecordReloadsAfterHistoryNavigation) {
+  if (!IsBackForwardCacheEnabled())
+    return;
   base::HistogramTester histogram_tester;
   using ReloadsAfterHistoryNavigation =
       BackForwardCacheMetrics::ReloadsAfterHistoryNavigation;
@@ -828,7 +842,7 @@
       web_contents()->GetFrameTree()->root()->current_frame_host();
 
   // Make url1 ineligible for caching so that when we navigate back it doesn't
-  // fetch the RenderFrameHost from the back-forward cache.
+  // fetch the RenderFrameHost from the back/forward cache.
   DisableForRenderFrameHostForTesting(rfh_url1);
   EXPECT_TRUE(NavigateToURL(shell(), url3));
 
@@ -853,8 +867,10 @@
               2)));
 }
 
-IN_PROC_BROWSER_TEST_F(BackForwardCacheEnabledMetricsBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsBrowserTest,
                        RestoreNavigationToNextPaint) {
+  if (!IsBackForwardCacheEnabled())
+    return;
   base::HistogramTester histogram_tester;
   const char kRestoreNavigationToNextPaintTimeHistogram[] =
       "BackForwardCache.Restore.NavigationToFirstPaint";
@@ -911,7 +927,7 @@
 
 // Tests that activating a prerender works correctly when navigated
 // back.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheMetricsPrerenderingBrowserTest,
+IN_PROC_BROWSER_TEST_P(BackForwardCacheMetricsPrerenderingBrowserTest,
                        MainFrameNavigation) {
   ukm::TestAutoSetUkmRecorder recorder;
 
@@ -958,4 +974,15 @@
               testing::ElementsAre(FeatureUsage{id5, 0, 0, 0}));
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         BackForwardCacheMetricsBrowserTest,
+                         testing::ValuesIn({BackForwardCacheStatus::kDisabled,
+                                            BackForwardCacheStatus::kEnabled}),
+                         BackForwardCacheMetricsBrowserTest::DescribeParams);
+INSTANTIATE_TEST_SUITE_P(All,
+                         BackForwardCacheMetricsPrerenderingBrowserTest,
+                         testing::ValuesIn({BackForwardCacheStatus::kDisabled,
+                                            BackForwardCacheStatus::kEnabled}),
+                         BackForwardCacheMetricsBrowserTest::DescribeParams);
+
 }  // namespace content
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index 7412cf2..7592dd9 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -5779,10 +5779,10 @@
   entry2->root_node()->children[0]->frame_entry->set_frame_unique_name("wrong");
 
   // With BackForwardCache page is restored from cache instead of getting
-  // recreated on history navigation, disable back-forward cache to force a
+  // recreated on history navigation, disable back/forward cache to force a
   // reload and a URL fetch.
-  DisableBackForwardCacheForTesting(
-      contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // 4. Go back, recreating the iframe. The subframe entry won't be found, and
   // we should fall back to the default URL.
@@ -5876,10 +5876,10 @@
   EXPECT_EQ(0U, entry2->root_node()->children.size());
 
   // With BackForwardCache page is restored from cache instead of getting
-  // recreated on history navigation, disable back-forward cache to force a
+  // recreated on history navigation, disable back/forward cache to force a
   // reload and a URL fetch.
-  DisableBackForwardCacheForTesting(
-      contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // 3. Go back, recreating the iframe.  The subframe will have a new name this
   // time, so we won't find a history item for it.  We should let the new data
@@ -5984,6 +5984,12 @@
 // forms injected into about:blank pages.  See https://crbug.com/657896.
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        FrameNavigationEntry_RecreatedInjectedBlankSubframe) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   // 1. Start on a page that injects a nested iframe into an injected
   // about:blank iframe.
   GURL main_url(embedded_test_server()->GetURL(
@@ -6081,6 +6087,11 @@
 // https://crbug.com/657896#c9).
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        FrameNavigationEntry_RecreatedInjectedSrcdocSubframe) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   // 1. Start on a page that injects a nested iframe srcdoc which contains a
   // nested iframe.
   GURL main_url(embedded_test_server()->GetURL(
@@ -6304,6 +6315,12 @@
 // - Main frame redirect, clearing the children (step 8).
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        FrameNavigationEntry_BackWithRedirect) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   // 1. Start on a page with two frames.
   GURL initial_url(
       embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
@@ -6478,6 +6495,12 @@
 // (This wasn't working initially).
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        FrameNavigationEntry_SameOriginBackWithRedirect) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   // 1. Start on a page with an iframe.
   GURL initial_url(embedded_test_server()->GetURL(
       "/navigation_controller/page_with_data_iframe.html"));
@@ -7151,6 +7174,12 @@
 IN_PROC_BROWSER_TEST_P(
     NavigationControllerBrowserTest,
     ReplacedNavigationEntryData_BackAfterReplaceStateWithRedirect) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
                             ->root();
@@ -9349,6 +9378,10 @@
                        BackFromPageWithReplaceStateInBeforeUnload) {
   NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
       shell()->web_contents()->GetController());
+  // With BackForwardCache, old frame doesn't fire beforeunload handlers as the
+  // page is stored in BackForwardCache on navigation.
+  controller.GetBackForwardCache().DisableForTesting(
+      content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
 
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
@@ -10295,6 +10328,11 @@
 // navigation in the main frame.  See https://crbug.com/597322.
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        ForwardInSubframeWithPendingForward) {
+  // The test expects history navigations to be not instant, so that it can
+  // start another forward navigation while another forward navigation has
+  // already started.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   // Navigate to a page with an iframe.
   GURL url_a(embedded_test_server()->GetURL(
       "/navigation_controller/page_with_data_iframe.html"));
@@ -10396,11 +10434,8 @@
   EXPECT_TRUE(delayer.WaitForRequestStart());
 
   NavigationController& controller = shell()->web_contents()->GetController();
-
-  TestNavigationManager back_manager(
-      shell()->web_contents(), embedded_test_server()->GetURL("/title1.html"));
   controller.GoBack();
-  back_manager.WaitForNavigationFinished();
+  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
 
   EXPECT_TRUE(controller.CanGoForward());
   EXPECT_EQ(0, controller.GetCurrentEntryIndex());
@@ -12461,6 +12496,11 @@
 // See https://crbug.com/765291.
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        BackSameDocumentAfterBlockedSubframe) {
+  // The test assumes the previous iframe gets deleted after navigation and
+  // later recreated on history navigations. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
       shell()->web_contents()->GetController());
 
@@ -12570,6 +12610,12 @@
 // main frame instead (and does a 404 instead of XFO error).
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        BackSameDocumentAfter404MainFrame) {
+  // This test expects going back to trigger a new page load and fetch a URL
+  // (which would fail with a 404 error). Disable back/forward cache to ensure
+  // that it doesn't happen.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
       shell()->web_contents()->GetController());
   // 1) Navigate to |start_url|.
@@ -13047,10 +13093,10 @@
   prev_spare = curr_spare;
 
   // With BackForwardCache the old process won't get deleted on navigation as it
-  // is still in use by the bfcached document, disable back-forward cache to
+  // is still in use by the bfcached document, disable back/forward cache to
   // ensure that the process gets deleted.
-  DisableBackForwardCacheForTesting(
-      contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   RenderProcessHostWatcher prev_host_watcher(
       prev_host, RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
@@ -13932,10 +13978,10 @@
 
   // This test expects using different SiteInstance/URL when navigating back.
   // This won't happen with BackForwardCache as document is restored directly
-  // instead of redirecting, disable back-forward cache to ensure that redirect
+  // instead of redirecting, disable back/forward cache to ensure that redirect
   // happens on history navigation.
-  DisableBackForwardCacheForTesting(
-      contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // Back, which should redirect to |url3|.
   FrameNavigateParamsCapturer capturer(root);
@@ -14352,10 +14398,10 @@
              };)"));
 
   // With BackForwardCache, old RenderFrameHost won't enter pending deletion
-  // on navigation as it is stored in bfcache, disable back-forward cache to
+  // on navigation as it is stored in bfcache, disable back/forward cache to
   // ensure that the RFH will enter pending deletion state.
-  DisableBackForwardCacheForTesting(
-      contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // Navigate the main frame cross-process and wait for the unload event to
   // fire.
@@ -16387,7 +16433,12 @@
   // [url1(subframe), url1(url2), *url3]
 
   {
-    TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+    // We are waiting for two navigations here: main frame and subframe.
+    // However, when back/forward cache is enabled, back navigation to a page
+    // with subframes will not trigger a subframe navigation (since the
+    // subframe is cached with the page).
+    TestNavigationObserver navigation_observer(
+        shell()->web_contents(), IsBackForwardCacheEnabled() ? 1 : 2);
     shell()->GoBackOrForward(-1);
     navigation_observer.WaitForNavigationFinished();
   }
@@ -16399,9 +16450,16 @@
   // first main document.
   // The second NavigateToURL navigates to a new main document.
   // The back navigation navigates back both main document and a child document
-  // and they are related to the first main document.
-  EXPECT_THAT(GetProcessedMainDocumentSequenceNumbers(),
-              ElementsAre(1, 1, 1, 2, 1, 1));
+  // and they are related to the first main document (except when same-site
+  // back/forward cache is enabled, where we only navigate the main frame, since
+  // the subframe is cached and doesn't need reconstruction/navigation).
+  if (!IsBackForwardCacheEnabled()) {
+    EXPECT_THAT(GetProcessedMainDocumentSequenceNumbers(),
+                ElementsAre(1, 1, 1, 2, 1, 1));
+  } else {
+    EXPECT_THAT(GetProcessedMainDocumentSequenceNumbers(),
+                ElementsAre(1, 1, 1, 2, 1));
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(
@@ -17583,6 +17641,12 @@
   EXPECT_EQ(3, controller.GetEntryCount());
   EXPECT_EQ(1, controller.GetCurrentEntryIndex());
 
+  // The test assumes the current page and its iframes gets deleted after
+  // navigation and later recreated on the back navigation. Disable back/forward
+  // cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
   // Navigate main frame to another url.
   EXPECT_TRUE(NavigateToURL(
       shell(), embedded_test_server()->GetURL("a.com", "/title2.html")));
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
index 2587268..105bfa9 100644
--- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -40,6 +40,7 @@
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/page_type.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/scoped_web_ui_controller_factory_registration.h"
@@ -979,6 +980,10 @@
 // current page fires history.back().
 TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
   NavigationControllerImpl& controller = controller_impl();
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back/forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(RenderViewHostTestHarness::web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // First make some history.
   const GURL kExistingURL1("http://foo/eh");
@@ -1522,6 +1527,10 @@
 // Tests what happens when a back navigation produces a new page.
 TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
   NavigationControllerImpl& controller = controller_impl();
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back/forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(RenderViewHostTestHarness::web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   const GURL url1("http://foo/1");
   const GURL url2("http://foo/2");
@@ -3804,11 +3813,17 @@
   EXPECT_TRUE(controller.GetPendingEntry());
   EXPECT_EQ(2, controller.GetEntryCount());
 
-  testing::NiceMock<MockPageBroadcast> mock_page_broadcast;
-  contents()->GetRenderViewHost()->BindPageBroadcast(
-      mock_page_broadcast.GetRemote());
-  EXPECT_CALL(mock_page_broadcast, SetHistoryOffsetAndLength(0, 1));
-  controller.PruneAllButLastCommitted();
+  {
+    // Ensure that the PruneAllButLastCommitted() call will result in a
+    // SetHistoryOffsetAndLength() call. We put this into its own scope so that
+    // other PageBroadcast calls (e.g. SetPageLifecycleState()) won't go through
+    // the mock.
+    testing::NiceMock<MockPageBroadcast> mock_page_broadcast;
+    contents()->GetRenderViewHost()->BindPageBroadcast(
+        mock_page_broadcast.GetRemote());
+    EXPECT_CALL(mock_page_broadcast, SetHistoryOffsetAndLength(0, 1));
+    controller.PruneAllButLastCommitted();
+  }
 
   // We should only have the last committed and pending entries at this point,
   // and the pending entry should still not be in the entry list.
@@ -4048,6 +4063,12 @@
 // resurrected.
 TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
   NavigationControllerImpl& controller = controller_impl();
+  // When back/forward cache is enabled, the ReadyToCommit() call for the
+  // forward navigation to B will commit the navigation immediately, making the
+  // navigation to page C not prune the entry to B. Disable back/forward cache
+  // to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(RenderViewHostTestHarness::web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // Start on page A.
   const GURL url_a("http://foo.com/a");
diff --git a/content/browser/renderer_host/navigation_entry_impl_unittest.cc b/content/browser/renderer_host/navigation_entry_impl_unittest.cc
index 27d0760b..a1513a93 100644
--- a/content/browser/renderer_host/navigation_entry_impl_unittest.cc
+++ b/content/browser/renderer_host/navigation_entry_impl_unittest.cc
@@ -329,6 +329,31 @@
             entry1_->root_node()->children[0]->frame_entry.get());
 }
 
+TEST_F(NavigationEntryTest, SetPageStateWithDefaultSequenceNumbers) {
+  blink::PageState page_state1 =
+      blink::PageState::CreateFromURL(GURL("http://foo.com"));
+  blink::PageState page_state2 =
+      blink::PageState::CreateFromURL(GURL("http://bar.com"));
+
+  std::unique_ptr<NavigationEntryRestoreContextImpl> context =
+      std::make_unique<NavigationEntryRestoreContextImpl>();
+  entry1_->SetPageState(page_state1, context.get());
+  entry2_->SetPageState(page_state2, context.get());
+
+  // Because no sequence numbers were set on the PageState objects, they will
+  // default to 0.
+  EXPECT_EQ(entry1_->root_node()->frame_entry->item_sequence_number(), 0);
+  EXPECT_EQ(entry2_->root_node()->frame_entry->item_sequence_number(), 0);
+  EXPECT_EQ(entry1_->root_node()->frame_entry->document_sequence_number(), 0);
+  EXPECT_EQ(entry2_->root_node()->frame_entry->document_sequence_number(), 0);
+
+  // However, because the item sequence number was the "default" value,
+  // NavigationEntryRestoreContext should not have de-duplicated the root
+  // FrameNavigationEntries, even though they "match".
+  EXPECT_NE(entry1_->root_node()->frame_entry.get(),
+            entry2_->root_node()->frame_entry.get());
+}
+
 #if defined(OS_ANDROID)
 // Failing test, see crbug/1050906.
 // Test that content URIs correctly show the file display name as the title.
diff --git a/content/browser/renderer_host/navigation_entry_restore_context_impl.cc b/content/browser/renderer_host/navigation_entry_restore_context_impl.cc
index 407c822..b0d62ac 100644
--- a/content/browser/renderer_host/navigation_entry_restore_context_impl.cc
+++ b/content/browser/renderer_host/navigation_entry_restore_context_impl.cc
@@ -21,6 +21,10 @@
 
 void NavigationEntryRestoreContextImpl::AddFrameNavigationEntry(
     FrameNavigationEntry* entry) {
+  // Do not track FrameNavigationEntries for the default ISN of 0, since this
+  // value can be used for any arbitrary document.
+  if (entry->item_sequence_number() == 0)
+    return;
   Key key(entry->item_sequence_number(), entry->frame_unique_name());
   DCHECK(entries_.find(key) == entries_.end());
   entries_.emplace(key, entry);
@@ -30,6 +34,8 @@
 NavigationEntryRestoreContextImpl::GetFrameNavigationEntryForItemSequenceNumber(
     int64_t item_sequence_number,
     const std::string& unique_name) {
+  if (item_sequence_number == 0)
+    return nullptr;
   auto it = entries_.find(Key(item_sequence_number, unique_name));
   return it == entries_.end() ? nullptr : it->second;
 }
diff --git a/content/browser/renderer_host/navigation_entry_restore_context_impl.h b/content/browser/renderer_host/navigation_entry_restore_context_impl.h
index 542a44d..a28207b 100644
--- a/content/browser/renderer_host/navigation_entry_restore_context_impl.h
+++ b/content/browser/renderer_host/navigation_entry_restore_context_impl.h
@@ -38,6 +38,12 @@
   // As an added precaution, we key based on both item sequence number and
   // the unique name of the frame, just in case a sequence number somehow
   // appears in multiple frames.
+  //
+  // We also ensure that entries with an item sequence number of 0 (the default
+  // value) cannot be stored or retrieved, since they may not represent the same
+  // document. This may happen for entries restored without all available state,
+  // and we can skip FrameNavigationEntry sharing for them because they are not
+  // considered same-document anyway.
   struct Key {
     Key(int64_t isn, const std::string& name)
         : item_sequence_number(isn), unique_name(name) {}
diff --git a/content/browser/renderer_host/navigation_request_browsertest.cc b/content/browser/renderer_host/navigation_request_browsertest.cc
index 3dbca36..9b40f0e 100644
--- a/content/browser/renderer_host/navigation_request_browsertest.cc
+++ b/content/browser/renderer_host/navigation_request_browsertest.cc
@@ -30,6 +30,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -2976,21 +2977,13 @@
   EXPECT_THAT(offsets_, testing::ElementsAre(1, 0, 1, 1, -1, -1, 1));
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_NavigationEntryOffsetsForSubframes \
-  DISABLED_NavigationEntryOffsetsForSubframes
-#else
-#define MAYBE_NavigationEntryOffsetsForSubframes \
-  NavigationEntryOffsetsForSubframes
-#endif
 IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
-                       MAYBE_NavigationEntryOffsetsForSubframes) {
+                       NavigationEntryOffsetsForSubframes) {
   const GURL url1(embedded_test_server()->GetURL("/title1.html"));
   const GURL url1_fragment1(
       embedded_test_server()->GetURL("/title1.html#id_1"));
-  const GURL url2(
-      embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
+  const GURL url2(embedded_test_server()->GetURL(
+      "b.com", "/frame_tree/page_with_one_frame.html"));
   const char kChildFrameId[] = "child0";
 
   EXPECT_TRUE(NavigateToURL(shell(), url1));
@@ -3016,7 +3009,11 @@
 
   {
     // We are waiting for two navigations here: main frame and subframe.
-    TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+    // However, when back/forward cache is enabled, back navigation to a page
+    // with subframes will not trigger a subframe navigation (since the
+    // subframe is cached with the page).
+    TestNavigationObserver navigation_observer(
+        shell()->web_contents(), IsBackForwardCacheEnabled() ? 1 : 2);
     shell()->GoBackOrForward(-1);
     navigation_observer.WaitForNavigationFinished();
   }
@@ -3059,8 +3056,16 @@
   // navigations have offset 3 as requested.
   // Note that all subframe navigations have offset 1 regardless of whether they
   // result in a new entry being generated or not.
-  EXPECT_THAT(offsets_,
-              testing::ElementsAre(1, 1, 1, 0, 1, 1, -1, 1, -1, -1, -1, 4));
+  if (IsBackForwardCacheEnabled()) {
+    // When back/forward cache is enabled, back navigation to a page with
+    // subframes will not trigger a subframe navigation (since the subframe is
+    // cached with the page and won't need to be reconstructed/navigated).
+    EXPECT_THAT(offsets_,
+                testing::ElementsAre(1, 1, 1, 0, 1, 1, -1, -1, -1, -1, 4));
+  } else {
+    EXPECT_THAT(offsets_,
+                testing::ElementsAre(1, 1, 1, 0, 1, 1, -1, 1, -1, -1, -1, 4));
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(NavigationRequestBackForwardBrowserTest,
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index 78c6cf6..8d14c49 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -397,7 +397,8 @@
   if (ui::PageTransitionIsMainFrame(params.transition)) {
     if (delegate_) {
       // Run tasks that must execute just before the commit.
-      delegate_->DidNavigateMainFramePreCommit(was_within_same_document);
+      delegate_->DidNavigateMainFramePreCommit(frame_tree_node,
+                                               was_within_same_document);
     }
   }
 
diff --git a/content/browser/renderer_host/navigator_delegate.h b/content/browser/renderer_host/navigator_delegate.h
index ba0b6b8..0dc1586 100644
--- a/content/browser/renderer_host/navigator_delegate.h
+++ b/content/browser/renderer_host/navigator_delegate.h
@@ -59,6 +59,7 @@
   // Handles post-navigation tasks in navigation BEFORE the entry has been
   // committed to the NavigationController.
   virtual void DidNavigateMainFramePreCommit(
+      FrameTreeNode* frame_tree_node,
       bool navigation_is_within_page) = 0;
 
   // Handles post-navigation tasks in navigation AFTER the entry has been
diff --git a/content/browser/renderer_host/navigator_unittest.cc b/content/browser/renderer_host/navigator_unittest.cc
index ca894395..449f0b8d 100644
--- a/content/browser/renderer_host/navigator_unittest.cc
+++ b/content/browser/renderer_host/navigator_unittest.cc
@@ -24,6 +24,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_navigation_throttle_inserter.h"
@@ -52,6 +53,16 @@
          !site_instance->IsDefaultSiteInstance();
 }
 
+// Same as above but does not return true if back/forward cache is the only
+// trigger for SiteInstance change. This function is useful if, e.g. the test
+// intends to disable back/forward cache.
+bool ExpectSiteInstanceChangeWithoutBackForwardCache(
+    SiteInstanceImpl* site_instance) {
+  return AreAllSitesIsolatedForTesting() ||
+         IsProactivelySwapBrowsingInstanceEnabled() ||
+         !site_instance->IsDefaultSiteInstance();
+}
+
 }  // namespace
 
 class NavigatorTest : public RenderViewHostImplTestHarness {
@@ -270,8 +281,17 @@
 
   contents()->NavigateAndCommit(kUrl0);
   EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
-  if (!ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance()))
+
+  // The test expects cross-site navigations to change SiteInstances, but not
+  // same-site navigations. Return if SiteInstance change is not possible, and
+  // disable same-site back/forward cache to ensure SiteInstance won't change
+  // for same-site navigations.
+  DisableBackForwardCacheForTesting(
+      contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
+  if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
+          main_test_rfh()->GetSiteInstance())) {
     return;
+  }
 
   // Start a renderer-initiated navigation to about:blank.
   EXPECT_FALSE(main_test_rfh()->is_loading());
@@ -321,8 +341,17 @@
 
   contents()->NavigateAndCommit(kUrl0);
   EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
-  if (!ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance()))
+
+  // The test expects cross-site navigations to change SiteInstances, but not
+  // same-site navigations. Return if SiteInstance change is not possible, and
+  // disable same-site back/forward cache to ensure SiteInstance won't change
+  // for same-site navigations.
+  DisableBackForwardCacheForTesting(
+      contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
+  if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
+          main_test_rfh()->GetSiteInstance())) {
     return;
+  }
 
   // Start a renderer-initiated navigation to about:blank.
   EXPECT_FALSE(main_test_rfh()->is_loading());
diff --git a/content/browser/renderer_host/page_impl_browsertest.cc b/content/browser/renderer_host/page_impl_browsertest.cc
index bcd16bc..5504711f 100644
--- a/content/browser/renderer_host/page_impl_browsertest.cc
+++ b/content/browser/renderer_host/page_impl_browsertest.cc
@@ -394,40 +394,34 @@
 }
 
 // Test that a new Page object is created for a same-site same-RFH navigation.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_SameSiteSameRenderFrameHostNavigation \
-  DISABLED_SameSiteSameRenderFrameHostNavigation
-#else
-#define MAYBE_SameSiteSameRenderFrameHostNavigation \
-  SameSiteSameRenderFrameHostNavigation
-#endif
-IN_PROC_BROWSER_TEST_F(PageImplTest,
-                       MAYBE_SameSiteSameRenderFrameHostNavigation) {
+IN_PROC_BROWSER_TEST_F(PageImplTest, SameSiteSameRenderFrameHostNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a1(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL url_a2(embedded_test_server()->GetURL("a.com", "/title2.html"));
 
   // 1) Navigate to A1.
   EXPECT_TRUE(NavigateToURL(shell(), url_a1));
-  RenderFrameHostImpl* main_rfh_a1 = primary_main_frame_host();
+  RenderFrameHostImplWrapper main_rfh_a1(primary_main_frame_host());
   PageImpl& page_a1 = main_rfh_a1->GetPage();
   testing::NiceMock<MockWebContentsObserver> page_changed_observer(
       web_contents());
   base::WeakPtr<Data> data = CreateOrGetDataForPage(page_a1)->GetWeakPtr();
 
-  // 2) Navigate to A2, both A1 and A2 should reuse RenderFrameHost. This will
-  // result in invoking PrimaryPageChanged callback.
+  // 2) Navigate to A2. This will result in invoking PrimaryPageChanged
+  // callback.
   EXPECT_CALL(page_changed_observer, PrimaryPageChanged(testing::_)).Times(1);
   EXPECT_TRUE(NavigateToURL(shell(), url_a2));
-  RenderFrameHostImpl* main_rfh_a2 = primary_main_frame_host();
-  EXPECT_EQ(main_rfh_a1, main_rfh_a2);
-  PageImpl& page_a2 = main_rfh_a1->GetPage();
+  RenderFrameHostImplWrapper main_rfh_a2(primary_main_frame_host());
+  EXPECT_EQ(CanSameSiteMainFrameNavigationsChangeRenderFrameHosts(),
+            main_rfh_a1.get() != main_rfh_a2.get());
+  PageImpl& page_a2 = main_rfh_a2.get()->GetPage();
 
   // 3) New Page object should be created and the associated PageUserData object
-  // should be deleted for page_a1.
+  // should be deleted for page_a1 if it the page is not in the back-forward
+  // cache.
   EXPECT_NE(&page_a1, &page_a2);
-  EXPECT_FALSE(data);
+  if (!IsSameSiteBackForwardCacheEnabled())
+    EXPECT_FALSE(data);
 }
 
 // Test that a new Page object is created when RenderFrame is recreated after
diff --git a/content/browser/renderer_host/render_document_host_user_data_browsertest.cc b/content/browser/renderer_host/render_document_host_user_data_browsertest.cc
index e731ef9..27b963c 100644
--- a/content/browser/renderer_host/render_document_host_user_data_browsertest.cc
+++ b/content/browser/renderer_host/render_document_host_user_data_browsertest.cc
@@ -718,19 +718,14 @@
   EXPECT_FALSE(data);
 }
 
-// Tests that RenderDocumentHostUserData object is cleared on performing same
-// site navigation.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_SameSiteNavigation DISABLED_SameSiteNavigation
-#else
-#define MAYBE_SameSiteNavigation SameSiteNavigation
-#endif
-IN_PROC_BROWSER_TEST_F(RenderDocumentHostUserDataTest,
-                       MAYBE_SameSiteNavigation) {
+IN_PROC_BROWSER_TEST_F(RenderDocumentHostUserDataTest, SameSiteNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a1(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL url_a2(embedded_test_server()->GetURL("a.com", "/title2.html"));
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back-forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
 
   // 1) Navigate to A1.
   EXPECT_TRUE(NavigateToURL(shell(), url_a1));
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
index c788e7d..0c10f93 100644
--- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -3904,7 +3904,7 @@
   GURL url_b_with_frame(embedded_test_server()->GetURL(
       "b.com", "/navigation_controller/page_with_iframe.html"));
   EXPECT_TRUE(NavigateToURL(shell(), url_b_with_frame));
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled()) {
     // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument
     // is enabled, the navigation will result in a new RFH.
     EXPECT_NE(rfh_b, web_contents->GetMainFrame());
@@ -4382,9 +4382,14 @@
       shell()->web_contents()->GetSiteInstance());
 
   // Navigate to about:blank from address bar.  This stays in the foo.com
-  // SiteInstance.
+  // SiteInstance, unless we do a proactive BrowsingInstance swap due to
+  // back/forward cache.
   EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
-  EXPECT_EQ(site_instance, shell()->web_contents()->GetSiteInstance());
+  if (IsSameSiteBackForwardCacheEnabled()) {
+    site_instance = shell()->web_contents()->GetSiteInstance();
+  } else {
+    EXPECT_EQ(site_instance, shell()->web_contents()->GetSiteInstance());
+  }
 
   // Perform a browser-initiated navigation to foo.com.  This should also stay
   // in the original foo.com SiteInstance and BrowsingInstance.
diff --git a/content/browser/session_history_browsertest.cc b/content/browser/session_history_browsertest.cc
index 2a1abe3..5448f83e 100644
--- a/content/browser/session_history_browsertest.cc
+++ b/content/browser/session_history_browsertest.cc
@@ -10,12 +10,14 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_navigation_policy.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -305,46 +307,50 @@
   EXPECT_EQ(frames, GetTabURL());
 }
 
-// TODO(mpcomplete): enable this when Bug 734372 is fixed:
-// "Doing a session history navigation does not restore newly-created subframe
-// document state"
-// Test that back/forward preserves POST data and document state when navigating
-// across frames (ie, from frame -> nonframe).
-// Hangs, see http://crbug.com/45058.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_CrossFrameFormBackForward DISABLED_CrossFrameFormBackForward
-#else
-#define MAYBE_CrossFrameFormBackForward CrossFrameFormBackForward
-#endif
-IN_PROC_BROWSER_TEST_F(SessionHistoryTest, MAYBE_CrossFrameFormBackForward) {
+IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) {
   ASSERT_FALSE(CanGoBack());
 
   GURL frames(GetURL("frames.html"));
+  // Open a page with "ftop" and  "fbot" iframe.
+  // The title of the main frame follows the title of the "fbot" iframe.
   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
 
+  // Click link in the "fbot" iframe. This updates the title of the main frame
+  // to "form".
   ClickLink("aform");
   EXPECT_EQ("form", GetTabTitle());
   EXPECT_EQ(frames, GetTabURL());
 
+  // Submit form in the "fbot" iframe. This submits to /echotitle which sets the
+  // title to the submission content of the form.
   SubmitForm("isubmit");
   EXPECT_EQ("text=&select=a", GetTabTitle());
   EXPECT_EQ(frames, GetTabURL());
 
+  // Go back, navigating the "fbot"  iframe. This updates the title of the main
+  // frame back to "form".
   GoBack();
   EXPECT_EQ("form", GetTabTitle());
   EXPECT_EQ(frames, GetTabURL());
 
   // history is [blank, bot1, *form, post]
 
+  // Navigate the main frame.
   ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
 
   // history is [blank, bot1, form, *bot2]
 
+  // Navigate the main frame back. If back/forward cache is enabled, the page
+  // will be restored as it was before we navigated away from it, with the title
+  // set to "form". If not, the page will be reloaded from scratch, setting the
+  // title to "bot1" again.
   GoBack();
-  EXPECT_EQ("bot1", GetTabTitle());
+  EXPECT_EQ(IsSameSiteBackForwardCacheEnabled() ? "form" : "bot1",
+            GetTabTitle());
   EXPECT_EQ(frames, GetTabURL());
 
+  // Submit the form in the "fbot" iframe again . This submits to /echotitle
+  // which sets the title to the submission content of the form.
   SubmitForm("isubmit");
   EXPECT_EQ("text=&select=a", GetTabTitle());
   EXPECT_EQ(frames, GetTabURL());
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 69c9da9..0f6f289c 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -1534,6 +1534,10 @@
 
 // Ensure that OOPIFs are deleted after navigating to a new main frame.
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, CleanupCrossSiteIframe) {
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back-forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(
+      web_contents(), content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -13218,6 +13222,16 @@
 
   // Navigate away - this will trigger logging of the UMA.
   EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
+
+  // Wait until the page with the crashed frame gets unloaded (triggering its
+  // evicton if it got into the back/forward cache), so that the histogram will
+  // be recorded when the renderer process is gone.
+  // TODO(https://crbug.com/1193386): Ensure pages with crashed subframes won't
+  // get into back/forward cache.
+  InactiveRenderFrameHostDeletionObserver inactive_rfh_deletion_observer(
+      web_contents());
+  inactive_rfh_deletion_observer.Wait();
+
   histograms.ExpectUniqueSample("Stability.ChildFrameCrash.Visibility",
                                 CrashVisibility::kNeverVisibleAfterCrash, 10);
 }
diff --git a/content/browser/site_per_process_unload_browsertest.cc b/content/browser/site_per_process_unload_browsertest.cc
index a5e2c69..11c64ab 100644
--- a/content/browser/site_per_process_unload_browsertest.cc
+++ b/content/browser/site_per_process_unload_browsertest.cc
@@ -485,12 +485,12 @@
       web_contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
   rfh_b->DoNotDeleteForTesting();
 
-  // With BackForwardCache, old frame doesn't fire unload handlers as the page
-  // is stored in BackForwardCache on navigating.
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
   DisableBackForwardCacheForTesting(web_contents(),
                                     BackForwardCache::TEST_USES_UNLOAD_EVENT);
 
-  // 3) Navigate and check the old frame is deleted after some time.
+  // 3) Navigate and check the old document is deleted after some time.
   FrameTreeNode* root = web_contents()->GetFrameTree()->root();
   RenderFrameDeletedObserver deleted_observer(root->current_frame_host());
   EXPECT_TRUE(NavigateToURL(shell(), next_url));
@@ -500,6 +500,8 @@
 // Navigate from A(B(A(B)) to C. Check the unload handler are executed, executed
 // in the right order and the processes for A and B are removed.
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, Unload_ABAB) {
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
   web_contents()->GetController().GetBackForwardCache().DisableForTesting(
       content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
 
@@ -645,6 +647,8 @@
 // If B1's mojom::FrameHost::Detach is called before A2, it should not destroy
 // itself and its children, but rather wait for A2.
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, PartialUnloadHandler) {
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
   web_contents()->GetController().GetBackForwardCache().DisableForTesting(
       content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
 
@@ -754,6 +758,8 @@
 //          [6]            [14] |
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                        PendingDeletionCheckCompletedOnSubtree) {
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
   web_contents()->GetController().GetBackForwardCache().DisableForTesting(
       content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
 
@@ -1312,6 +1318,10 @@
 // 4. The browser must be resilient and detach B1 when A3 commits.
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                        SameProcessNavigationResilientToDetachDropped) {
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back-forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   GURL A1_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
   GURL A3_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
@@ -1417,6 +1427,10 @@
 // different frame hierarchy.
 IN_PROC_BROWSER_TEST_P(SitePerProcessSSLBrowserTest,
                        UnloadHandlersArePowerful) {
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
+  DisableBackForwardCacheForTesting(
+      web_contents(), content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
   // Navigate to a page hosting a cross-origin frame.
   GURL url =
       https_server()->GetURL("a.com", "/cross_site_iframe_factory.html?a(b)");
@@ -1508,6 +1522,10 @@
 // hierarchy.
 IN_PROC_BROWSER_TEST_P(SitePerProcessSSLBrowserTest,
                        UnloadHandlersArePowerfulGrandChild) {
+  // With BackForwardCache, old document doesn't fire unload handlers as the
+  // page is stored in BackForwardCache on navigation.
+  DisableBackForwardCacheForTesting(
+      web_contents(), content::BackForwardCache::TEST_USES_UNLOAD_EVENT);
   // Navigate to a page hosting a cross-origin frame.
   GURL url = https_server()->GetURL("a.com",
                                     "/cross_site_iframe_factory.html?a(b(c))");
diff --git a/content/browser/text_fragment_browsertest.cc b/content/browser/text_fragment_browsertest.cc
index f32d36da..b526e6c 100644
--- a/content/browser/text_fragment_browsertest.cc
+++ b/content/browser/text_fragment_browsertest.cc
@@ -266,16 +266,8 @@
   }
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_DisabledOnScriptHistoryNavigation \
-  DISABLED_DisabledOnScriptHistoryNavigation
-#else
-#define MAYBE_DisabledOnScriptHistoryNavigation \
-  DisabledOnScriptHistoryNavigation
-#endif
 IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
-                       MAYBE_DisabledOnScriptHistoryNavigation) {
+                       DisabledOnScriptHistoryNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL target_text_url(embedded_test_server()->GetURL(
       "/scrollable_page_with_content.html#:~:text=text"));
@@ -284,6 +276,12 @@
   EXPECT_TRUE(NavigateToURL(shell(), target_text_url));
 
   WebContents* main_contents = shell()->web_contents();
+  // The test assumes the previous page gets deleted after navigation and will
+  // be recreated with did_scroll == false. Disable back/forward cache to ensure
+  // that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(
+      main_contents, BackForwardCacheImpl::TEST_ASSUMES_NO_CACHING);
+
   {
     // The RenderFrameSubmissionObserver destructor expects the RenderFrameHost
     // stays the same until it gets destructed, so we need to scope this to make
@@ -355,25 +353,16 @@
   EXPECT_DID_SCROLL(true);
 }
 
-// Similar to the above test, we're checking that browser-initiated
-// same-document navigations invoke the text fragment. However, this time, the
-// initial landing on the page is via a non-user-activated script navigation.
-// This ensure we're not inappropriately blocking a text-fragment based on the
-// state of the initial document load.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_SameDocumentBrowserNavigationOnScriptNavigatedDocument \
-  DISABLED_SameDocumentBrowserNavigationOnScriptNavigatedDocument
-#else
-#define MAYBE_SameDocumentBrowserNavigationOnScriptNavigatedDocument \
-  SameDocumentBrowserNavigationOnScriptNavigatedDocument
-#endif
-IN_PROC_BROWSER_TEST_F(
-    TextFragmentAnchorBrowserTest,
-    MAYBE_SameDocumentBrowserNavigationOnScriptNavigatedDocument) {
+IN_PROC_BROWSER_TEST_F(TextFragmentAnchorBrowserTest,
+                       SameDocumentBrowserNavigationOnScriptNavigatedDocument) {
   ASSERT_TRUE(embedded_test_server()->Start());
   WebContents* main_contents = shell()->web_contents();
   RenderFrameSubmissionObserver frame_observer(main_contents);
+  // The test assumes the RenderWidgetHost stays the same after navigation,
+  // which won't happen if same-site back/forward-cache is enabled. Disable it
+  // so that we will keep RenderWidgetHost even after navigation.
+  DisableBackForwardCacheForTesting(
+      main_contents, BackForwardCacheImpl::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
 
   // Load an initial page
   {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 0cdaa350..08cc186 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -5545,10 +5545,19 @@
 }
 
 void WebContentsImpl::DidNavigateMainFramePreCommit(
+    FrameTreeNode* frame_tree_node,
     bool navigation_is_within_page) {
+  // The render_frame_host is always a main frame.
+  DCHECK(frame_tree_node->IsMainFrame());
   TRACE_EVENT1("content,navigation",
                "WebContentsImpl::DidNavigateMainFramePreCommit",
                "navigation_is_within_page", navigation_is_within_page);
+  bool is_primary_main_frame =
+      GetMainFrame() == frame_tree_node->render_manager()->current_frame_host();
+  // If running for a non-primary main frame, early out.
+  if (!is_primary_main_frame)
+    return;
+
   // Ensure fullscreen mode is exited before committing the navigation to a
   // different page.  The next page will not start out assuming it is in
   // fullscreen mode.
@@ -5556,6 +5565,7 @@
     // No page change?  Then, the renderer and browser can remain in fullscreen.
     return;
   }
+
   if (IsFullscreen())
     ExitFullscreen(false);
   DCHECK(!IsFullscreen());
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 9cc6945..74274cf 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -870,7 +870,8 @@
   void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
                             const GURL& url,
                             int error_code) override;
-  void DidNavigateMainFramePreCommit(bool navigation_is_within_page) override;
+  void DidNavigateMainFramePreCommit(FrameTreeNode* frame_tree_node,
+                                     bool navigation_is_within_page) override;
   void DidNavigateMainFramePostCommit(
       RenderFrameHostImpl* render_frame_host,
       const LoadCommittedDetails& details,
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 7a0a5b5..0eb432d9 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -52,6 +52,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/fake_local_frame.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/navigation_simulator.h"
@@ -1109,6 +1110,13 @@
 // TODO(avi,creis): Consider changing this behavior to better match the user's
 // intent.
 TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
+  // The test wants to cover the case where the old page gets deleted, so that
+  // back navigations can be stopped at ReadyToCommit timing. Disable
+  // back/forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  const bool will_change_site_instance =
+      IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled();
   // Start with a web ui page, which gets a new RVH with WebUI bindings.
   GURL url1(std::string(kChromeUIScheme) + "://" +
             std::string(kChromeUIGpuHost));
@@ -1145,14 +1153,14 @@
   SiteInstance* instance3 = contents()->GetSiteInstance();
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (will_change_site_instance) {
     // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument
     // is enabled, the RFH should change.
     EXPECT_NE(google_rfh, main_test_rfh());
   } else {
     EXPECT_EQ(google_rfh, main_test_rfh());
   }
-  if (CanSameSiteMainFrameNavigationsChangeSiteInstances()) {
+  if (will_change_site_instance) {
     // When ProactivelySwapBrowsingInstance is enabled on same-site navigations,
     // the SiteInstance will change.
     EXPECT_NE(instance2, instance3);
@@ -1171,7 +1179,7 @@
 
   auto* first_pending_rfh = contents()->GetSpeculativePrimaryMainFrame();
   GlobalRenderFrameHostId first_pending_rfh_id;
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (will_change_site_instance) {
     EXPECT_TRUE(contents()->CrossProcessNavigationPending());
     EXPECT_TRUE(first_pending_rfh);
     first_pending_rfh_id = first_pending_rfh->GetGlobalId();
@@ -1189,7 +1197,7 @@
   EXPECT_TRUE(contents()->CrossProcessNavigationPending());
   EXPECT_TRUE(contents()->GetSpeculativePrimaryMainFrame());
   EXPECT_EQ(entry1, controller().GetPendingEntry());
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (will_change_site_instance) {
     // When ProactivelySwapBrowsingInstance or RenderDocument is enabled on
     // same-site main frame navigation, the first back navigation will create a
     // speculative RFH even though it's a same-site navigation, and the
@@ -1213,7 +1221,7 @@
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_FALSE(controller().GetPendingEntry());
   EXPECT_EQ(google_rfh, main_test_rfh());
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (will_change_site_instance) {
     // We committed the second back navigation and landed on the first page.
     EXPECT_EQ(url1, controller().GetLastCommittedEntry()->GetURL());
   } else {
@@ -1234,9 +1242,15 @@
 // Tests that if we go back twice (same-site then cross-site), and the cross-
 // site RFH commits first, we ignore the now-swapped-out RFH's commit.
 TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) {
-  // This test assumes no interaction with the back-forward cache. Indeed, it
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back/forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
+  const bool will_change_site_instance =
+      IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled();
+  // This test assumes no interaction with the back/forward cache. Indeed, it
   // isn't possible to perform the second back navigation in between the
-  // ReadyToCommit and Commit of the first back-forward cache one. Both steps
+  // ReadyToCommit and Commit of the first back/forward cache one. Both steps
   // are combined with it, nothing can happen in between.
   contents()->GetController().GetBackForwardCache().DisableForTesting(
       BackForwardCache::TEST_ASSUMES_NO_CACHING);
@@ -1277,7 +1291,7 @@
   SiteInstance* instance3 = contents()->GetSiteInstance();
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
+  if (will_change_site_instance) {
     // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument
     // is enabled, the RFH should change.
     EXPECT_NE(google_rfh, main_test_rfh());
@@ -1285,7 +1299,7 @@
   } else {
     EXPECT_EQ(google_rfh, main_test_rfh());
   }
-  if (CanSameSiteMainFrameNavigationsChangeSiteInstances()) {
+  if (will_change_site_instance) {
     // When ProactivelySwapBrowsingInstance is enabled on same-site navigations,
     // the SiteInstance will change.
     EXPECT_NE(instance2, instance3);
@@ -1301,7 +1315,7 @@
   auto back_navigation1 =
       NavigationSimulator::CreateHistoryNavigation(-1, contents());
   back_navigation1->ReadyToCommit();
-  if (CanSameSiteMainFrameNavigationsChangeSiteInstances()) {
+  if (will_change_site_instance) {
     EXPECT_TRUE(contents()->CrossProcessNavigationPending());
   } else {
     EXPECT_FALSE(contents()->CrossProcessNavigationPending());
diff --git a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 9b65ed8..359a6311 100644
--- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "content/browser/loader/prefetch_url_loader_service.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -55,6 +56,7 @@
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_download_manager_delegate.h"
+#include "content/test/content_browser_test_utils_internal.h"
 #include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "net/base/features.h"
@@ -154,66 +156,6 @@
   std::string accept_langs_ = "en";
 };
 
-// Histograms: PrefetchedSignedExchangeCache.* are recorded when the current
-// document is replaced by a new one:
-// (a) If the new document is loaded in a new RenderFrameHost. The histogram is
-//     recorded in the old RenderFrameHost destructor.
-// (b) If the new document is loaded inside the same RenderFrameHost, it is
-//     recorded in RenderFrameHost::CommitNavigation().
-//
-// Note: The RenderDocument project will remove code path (b).
-//
-// In (a), since the deletion of a RenderFrameHost is asynchronous, it caused
-// several tests to be flaky. The tests weren't waiting for the RenderFrameHost
-// deletion before checking the histograms. See https://crbug.com/1016865
-//
-// Use this class for waiting any RenderFrameHost pending deletion or inside the
-// BackForwardCache to be deleted
-class InactiveRenderFrameHostDeletionObserver : public WebContentsObserver {
- public:
-  InactiveRenderFrameHostDeletionObserver(WebContents* content)
-      : WebContentsObserver(content) {
-    // |rfh_count_| starts at zero, because we expect to start counting when
-    // there are zero active RenderFrameHost.
-    EXPECT_EQ(1u, content->GetAllFrames().size());
-    EXPECT_FALSE(content->GetAllFrames()[0]->IsRenderFrameLive());
-  }
-  ~InactiveRenderFrameHostDeletionObserver() override = default;
-
-  void Wait() {
-    // Some RenderFrameHost may remain in the BackForwardCache. Request
-    // releasing them. This is asynchronous.
-    static_cast<WebContentsImpl*>(web_contents())
-        ->GetController()
-        .GetBackForwardCache()
-        .Flush();
-
-    loop_ = std::make_unique<base::RunLoop>();
-    target_rfh_count_ = web_contents()->GetAllFrames().size();
-    CheckCondition();
-    loop_->Run();
-  }
-
- private:
-  void RenderFrameCreated(RenderFrameHost*) override { rfh_count_++; }
-
-  void RenderFrameDeleted(RenderFrameHost*) override {
-    rfh_count_--;
-    CheckCondition();
-  }
-
-  void CheckCondition() {
-    if (loop_ && rfh_count_ == target_rfh_count_)
-      loop_->Quit();
-  }
-
-  std::unique_ptr<base::RunLoop> loop_;
-  int rfh_count_ = 0;
-  int target_rfh_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(InactiveRenderFrameHostDeletionObserver);
-};
-
 }  // namespace
 
 class SignedExchangeRequestHandlerBrowserTestBase
@@ -372,7 +314,8 @@
   DISALLOW_COPY_AND_ASSIGN(SignedExchangeRequestHandlerBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, Simple) {
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
+                       DISABLED_Simple) {
   InstallMockCert();
   InstallMockCertChainInterceptor();
 
@@ -423,6 +366,8 @@
           original_cert->cert_buffer());
   EXPECT_EQ(original_fingerprint, fingerprint);
 
+  // Wait for the previous page's RFH to be deleted (if it changed) so that the
+  // histograms will get updated.
   inactive_rfh_deletion_observer_->Wait();
   histogram_tester_.ExpectUniqueSample(
       kLoadResultHistogram, SignedExchangeLoadResult::kSuccess,
@@ -448,7 +393,8 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest, VariantMatch) {
+IN_PROC_BROWSER_TEST_P(SignedExchangeRequestHandlerBrowserTest,
+                       DISABLED_VariantMatch) {
   SetAcceptLangs("en-US,fr");
   InstallUrlInterceptor(
       GURL("https://cert.example.org/cert.msg"),
@@ -478,6 +424,8 @@
              base::StringPrintf("location.href = '%s';", url.spec().c_str())));
   EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
 
+  // Wait for the previous page's RFH to be deleted (if it changed) so that the
+  // histograms will get updated.
   inactive_rfh_deletion_observer_->Wait();
   histogram_tester_.ExpectUniqueSample(
       kLoadResultHistogram, SignedExchangeLoadResult::kSuccess,
diff --git a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
index 27d3cc9..b162d7f 100644
--- a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -46,6 +46,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/common/shell_switches.h"
+#include "content/test/content_browser_test_utils_internal.h"
 #include "net/base/features.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_cache.h"
@@ -236,6 +237,9 @@
 
   void SetUpOnMainThread() override {
     host_resolver()->AddRule("*", "127.0.0.1");
+    inactive_rfh_deletion_observer_ =
+        std::make_unique<InactiveRenderFrameHostDeletionObserver>(
+            shell()->web_contents());
     PrefetchBrowserTestBase::SetUpOnMainThread();
   }
 
@@ -247,6 +251,9 @@
   static constexpr uint64_t kTestBlobStorageMinFileSizeBytes = 10;
   static constexpr uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
 
+  std::unique_ptr<InactiveRenderFrameHostDeletionObserver>
+      inactive_rfh_deletion_observer_;
+
   static bool IsSignedExchangePrefetchCacheEnabled() {
     return base::FeatureList::IsEnabled(
                features::kSignedExchangePrefetchCacheForNavigations) ||
@@ -317,6 +324,9 @@
       // the target URL. The target content should still be read correctly.
       // The content is loaded from HTTPCache.
       NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+      // Wait for the previous page's RFH to be deleted (if it changed) so that
+      // the histograms will get updated.
+      inactive_rfh_deletion_observer_->Wait();
 
       EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
       histograms.ExpectTotalCount("PrefetchedSignedExchangeCache.Count", 0);
@@ -349,6 +359,9 @@
     // the target URL. The target content should still be read correctly.
     // The content is loaded from PrefetchedSignedExchangeCache.
     NavigateToURLAndWaitTitle(sxg_url, "Prefetch Target (SXG)");
+    // Wait for the previous page's RFH to be deleted (if it changed) so that
+    // the histograms will get updated.
+    inactive_rfh_deletion_observer_->Wait();
 
     EXPECT_EQ(1, sxg_request_counter->GetRequestCount());
     histograms.ExpectBucketCount("PrefetchedSignedExchangeCache.Count", 1, 1);
@@ -426,16 +439,8 @@
   DISALLOW_COPY_AND_ASSIGN(SignedExchangePrefetchBrowserTest);
 };
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_PrefetchMainResourceSXG_SameOrigin \
-  DISABLED_PrefetchMainResourceSXG_SameOrigin
-#else
-#define MAYBE_PrefetchMainResourceSXG_SameOrigin \
-  PrefetchMainResourceSXG_SameOrigin
-#endif
 IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
-                       MAYBE_PrefetchMainResourceSXG_SameOrigin) {
+                       PrefetchMainResourceSXG_SameOrigin) {
   RunPrefetchMainResourceSXGTest("example.com" /* prefetch_page_hostname */,
                                  "/prefetch.html" /* prefetch_page_path */,
                                  "example.com" /* sxg_hostname */,
@@ -444,16 +449,8 @@
                                  "/target.html" /* inner_url_path */);
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_PrefetchMainResourceSXG_CrossOrigin \
-  DISABLED_PrefetchMainResourceSXG_CrossOrigin
-#else
-#define MAYBE_PrefetchMainResourceSXG_CrossOrigin \
-  PrefetchMainResourceSXG_CrossOrigin
-#endif
 IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
-                       MAYBE_PrefetchMainResourceSXG_CrossOrigin) {
+                       PrefetchMainResourceSXG_CrossOrigin) {
   RunPrefetchMainResourceSXGTest(
       "aggregator.example.com" /* prefetch_page_hostname */,
       "/prefetch.html" /* prefetch_page_path */,
@@ -463,15 +460,8 @@
       "/target.html" /* inner_url_path */);
 }
 
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_PrefetchMainResourceSXG_SameURL \
-  DISABLED_PrefetchMainResourceSXG_SameURL
-#else
-#define MAYBE_PrefetchMainResourceSXG_SameURL PrefetchMainResourceSXG_SameURL
-#endif
 IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
-                       MAYBE_PrefetchMainResourceSXG_SameURL) {
+                       PrefetchMainResourceSXG_SameURL) {
   RunPrefetchMainResourceSXGTest("example.com" /* prefetch_page_hostname */,
                                  "/prefetch.html" /* prefetch_page_path */,
                                  "example.com" /* sxg_hostname */,
@@ -788,16 +778,8 @@
 // SignedExchangePrefetchCacheForNavigations when
 // |sxg_subresource_prefetch_enabled| is false to check the behavior of
 // SignedExchangePrefetchCacheForNavigations feature.
-// https://crbug.com/1219373 fails with BFCache field trial testing config.
-#if defined(OS_ANDROID)
-#define MAYBE_PrefetchAlternativeSubresourceSXG \
-  DISABLED_PrefetchAlternativeSubresourceSXG
-#else
-#define MAYBE_PrefetchAlternativeSubresourceSXG \
-  PrefetchAlternativeSubresourceSXG
-#endif
 IN_PROC_BROWSER_TEST_P(SignedExchangePrefetchBrowserTest,
-                       MAYBE_PrefetchAlternativeSubresourceSXG) {
+                       PrefetchAlternativeSubresourceSXG) {
   const char* prefetch_page_path = "/prefetch.html";
   const char* page_sxg_path = "/target.sxg";
   const char* page_inner_url_path = "/target.html";
@@ -942,6 +924,10 @@
     NavigateToURLAndWaitTitle(sxg_page_url, "from server");
   }
 
+  // Wait for the previous page's RFH to be deleted (if it changed) so that the
+  // histograms will get updated.
+  inactive_rfh_deletion_observer_->Wait();
+
   EXPECT_EQ(1, page_sxg_request_counter->GetRequestCount());
 
   if (IsSignedExchangePrefetchCacheEnabled()) {
diff --git a/content/browser/web_package/web_bundle_browsertest.cc b/content/browser/web_package/web_bundle_browsertest.cc
index cedd9bc..27734e4 100644
--- a/content/browser/web_package/web_bundle_browsertest.cc
+++ b/content/browser/web_package/web_bundle_browsertest.cc
@@ -29,6 +29,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -1206,6 +1207,11 @@
     const GURL& web_bundle_url,
     const GURL& url_origin,
     base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(web_contents,
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   NavigateAndWaitForTitle(
       web_contents, web_bundle_url,
       get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
@@ -1394,6 +1400,11 @@
     const GURL& web_bundle_url,
     const GURL& url_origin,
     base::RepeatingCallback<GURL(const GURL&)> get_url_for_bundle) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(web_contents,
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   NavigateAndWaitForTitle(
       web_contents, web_bundle_url,
       get_url_for_bundle.Run(url_origin.Resolve("/top-page/")), "Ready");
@@ -2711,15 +2722,13 @@
                 "/web_bundle/path_test/in_scope/page.html"));
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_HistoryNavigationError_UnexpectedContentType \
-  DISABLED_HistoryNavigationError_UnexpectedContentType
-#else
-#define MAYBE_HistoryNavigationError_UnexpectedContentType \
-  HistoryNavigationError_UnexpectedContentType
-#endif
 IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
-                       MAYBE_HistoryNavigationError_UnexpectedContentType) {
+                       HistoryNavigationError_UnexpectedContentType) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   const std::string wbn_path = "/web_bundle/test.wbn";
   const std::string primary_url_path = "/web_bundle/test.html";
   RegisterRequestHandler(wbn_path);
@@ -2747,15 +2756,13 @@
   HistoryBackAndWaitUntilConsoleError("Unexpected content type.");
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_HistoryNavigationError_MissingNosniff \
-  DISABLED_HistoryNavigationError_MissingNosniff
-#else
-#define MAYBE_HistoryNavigationError_MissingNosniff \
-  HistoryNavigationError_MissingNosniff
-#endif
 IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
-                       MAYBE_HistoryNavigationError_MissingNosniff) {
+                       HistoryNavigationError_MissingNosniff) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   const std::string wbn_path = "/web_bundle/test.wbn";
   const std::string primary_url_path = "/web_bundle/test.html";
   RegisterRequestHandler(wbn_path);
@@ -2784,15 +2791,13 @@
       "header.");
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_HistoryNavigationError_UnexpectedRedirect \
-  DISABLED_HistoryNavigationError_UnexpectedRedirect
-#else
-#define MAYBE_HistoryNavigationError_UnexpectedRedirect \
-  HistoryNavigationError_UnexpectedRedirect
-#endif
 IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
-                       MAYBE_HistoryNavigationError_UnexpectedRedirect) {
+                       HistoryNavigationError_UnexpectedRedirect) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   const std::string wbn_path = "/web_bundle/test.wbn";
   const std::string primary_url_path = "/web_bundle/test.html";
   RegisterRequestHandler(wbn_path);
@@ -2820,15 +2825,12 @@
   HistoryBackAndWaitUntilConsoleError("Unexpected redirect.");
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_HistoryNavigationError_ReadMetadataFailure \
-  DISABLED_HistoryNavigationError_ReadMetadataFailure
-#else
-#define MAYBE_HistoryNavigationError_ReadMetadataFailure \
-  HistoryNavigationError_ReadMetadataFailure
-#endif
 IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
-                       MAYBE_HistoryNavigationError_ReadMetadataFailure) {
+                       HistoryNavigationError_ReadMetadataFailure) {
+  // The test assumes the previous page gets deleted after navigation. Disable
+  // back/forward cache to ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   const std::string wbn_path = "/web_bundle/test.wbn";
   const std::string primary_url_path = "/web_bundle/test.html";
   RegisterRequestHandler(wbn_path);
@@ -2849,15 +2851,13 @@
       "Failed to read metadata of Web Bundle file: Wrong magic bytes.");
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_HistoryNavigationError_ExpectedUrlNotFound \
-  DISABLED_HistoryNavigationError_ExpectedUrlNotFound
-#else
-#define MAYBE_HistoryNavigationError_ExpectedUrlNotFound \
-  HistoryNavigationError_ExpectedUrlNotFound
-#endif
 IN_PROC_BROWSER_TEST_F(WebBundleNetworkBrowserTest,
-                       MAYBE_HistoryNavigationError_ExpectedUrlNotFound) {
+                       HistoryNavigationError_ExpectedUrlNotFound) {
+  // The test assumes the previous page gets deleted after navigation and doing
+  // back navigation will recreate the page. Disable back/forward cache to
+  // ensure that it doesn't get preserved in the cache.
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);
   const std::string wbn_path = "/web_bundle/test.wbn";
   const std::string primary_url_path = "/web_bundle/test.html";
   const std::string alt_primary_url_path = "/web_bundle/alt.html";
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 48e5096..c67c0bd 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3738,6 +3738,53 @@
   }
 }
 
+TEST_F(AuthenticatorImplTest, AlgorithmsOmitted) {
+  // Some CTAP 2.0 security keys shipped support for algorithms other than
+  // ECDSA P-256 but the algorithms field didn't exist then. makeCredential
+  // requests should get routed to them anyway.
+
+  device::VirtualCtap2Device::Config config;
+  // Remove the algorithms field from the getInfo.
+  config.advertised_algorithms.emplace(absl::nullopt);
+  virtual_device_factory_->SetCtap2Config(config);
+  NavigateAndCommit(GURL(kTestOrigin1));
+
+  // Test that an Ed25519 credential can still be created. (The virtual
+  // authenticator supports that algorithm.)
+  {
+    const int32_t algo =
+        static_cast<int32_t>(device::CoseAlgorithmIdentifier::kEdDSA);
+    PublicKeyCredentialCreationOptionsPtr options =
+        GetTestPublicKeyCredentialCreationOptions();
+    options->public_key_parameters = GetTestPublicKeyCredentialParameters(algo);
+    MakeCredentialResult result =
+        AuthenticatorMakeCredential(std::move(options));
+    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
+    const auto& response = result.response;
+    EXPECT_EQ(response->public_key_algo, algo);
+  }
+
+  // Test that requesting an unsupported algorithm still collects a touch.
+  {
+    bool touched = false;
+    virtual_device_factory_->mutable_state()->simulate_press_callback =
+        base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
+          touched = true;
+          return true;
+        });
+
+    const int32_t algo = static_cast<int32_t>(
+        device::CoseAlgorithmIdentifier::kInvalidForTesting);
+    PublicKeyCredentialCreationOptionsPtr options =
+        GetTestPublicKeyCredentialCreationOptions();
+    options->public_key_parameters = GetTestPublicKeyCredentialParameters(algo);
+    MakeCredentialResult result =
+        AuthenticatorMakeCredential(std::move(options));
+    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
+    EXPECT_TRUE(touched);
+  }
+}
+
 TEST_F(AuthenticatorImplTest, VirtualAuthenticatorPublicKeyAlgos) {
   // Exercise all the public key types in the virtual authenticator for create()
   // and get().
@@ -5769,6 +5816,152 @@
   EXPECT_EQ(5, virtual_device_factory_->mutable_state()->uv_retries);
 }
 
+class BlockingAuthenticatorRequestDelegate
+    : public AuthenticatorRequestClientDelegate {
+ public:
+  explicit BlockingAuthenticatorRequestDelegate(
+      base::OnceClosure* const callback)
+      : callback_(callback) {}
+
+  void RegisterActionCallbacks(
+      base::OnceClosure cancel_callback,
+      base::RepeatingClosure start_over_callback,
+      device::FidoRequestHandlerBase::RequestCallback request_callback,
+      base::RepeatingClosure bluetooth_adapter_power_on_callback) override {
+    cancel_callback_ = std::move(cancel_callback);
+  }
+
+  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
+    if (callback_ && *callback_) {
+      std::move(*callback_).Run();
+    }
+    return true;
+  }
+
+  void Cancel() { std::move(cancel_callback_).Run(); }
+
+ private:
+  base::OnceClosure* const callback_;
+  base::OnceClosure cancel_callback_;
+};
+
+class BlockingDelegateContentBrowserClient : public ContentBrowserClient {
+ public:
+  explicit BlockingDelegateContentBrowserClient(
+      base::OnceClosure* const callback)
+      : callback_(callback) {}
+
+  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
+    return &web_authentication_delegate_;
+  }
+
+  std::unique_ptr<AuthenticatorRequestClientDelegate>
+  GetWebAuthenticationRequestDelegate(
+      RenderFrameHost* render_frame_host) override {
+    auto ret =
+        std::make_unique<BlockingAuthenticatorRequestDelegate>(callback_);
+    delegate_ = ret.get();
+    return ret;
+  }
+
+  void Cancel() { delegate_->Cancel(); }
+
+ private:
+  TestWebAuthenticationDelegate web_authentication_delegate_;
+  base::OnceClosure* const callback_;
+  BlockingAuthenticatorRequestDelegate* delegate_ = nullptr;
+};
+
+class BlockingDelegateAuthenticatorImplTest : public AuthenticatorImplTest {
+ public:
+  BlockingDelegateAuthenticatorImplTest() = default;
+
+  BlockingDelegateAuthenticatorImplTest(
+      const BlockingDelegateAuthenticatorImplTest&) = delete;
+  BlockingDelegateAuthenticatorImplTest& operator=(
+      const BlockingDelegateAuthenticatorImplTest&) = delete;
+
+  void SetUp() override {
+    AuthenticatorImplTest::SetUp();
+    old_client_ = SetBrowserClientForTesting(&test_client_);
+    NavigateAndCommit(GURL(kTestOrigin1));
+  }
+
+  void TearDown() override {
+    SetBrowserClientForTesting(old_client_);
+    AuthenticatorImplTest::TearDown();
+  }
+
+ protected:
+  base::OnceClosure blocked_on_error_callback_;
+  BlockingDelegateContentBrowserClient test_client_{
+      &blocked_on_error_callback_};
+
+ private:
+  ContentBrowserClient* old_client_ = nullptr;
+};
+
+TEST_F(BlockingDelegateAuthenticatorImplTest, PostCancelMessage) {
+  // Create a fingerprint-reading device and a UP-only device. Advance the
+  // first till it's waiting for a fingerprint then simulate a touch on the
+  // UP device that claims that it failed due to an excluded credential.
+  // When the error is showing in the UI, have the fingerprint device resolve
+  // the UV with an error. Don't crash (crbug.com/1225899).
+
+  PublicKeyCredentialCreationOptionsPtr options =
+      GetTestPublicKeyCredentialCreationOptions();
+  options->exclude_credentials = GetTestCredentials();
+
+  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
+  scoped_refptr<VirtualFidoDevice::State> state_1 = device_1.state;
+  device_1.state->simulate_press_callback =
+      base::BindLambdaForTesting([&](VirtualFidoDevice* _) -> bool {
+        // Drop all makeCredential requests. The reply will be sent when
+        // the second authenticator is asked for a fingerprint.
+        return false;
+      });
+
+  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
+  scoped_refptr<VirtualFidoDevice::State> state_2 = device_2.state;
+  device_2.config.internal_uv_support = true;
+  device_2.config.pin_support = true;
+  device_2.config.pin_uv_auth_token_support = true;
+  device_2.config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
+  device_2.state->pin = kTestPIN;
+  device_2.state->fingerprints_enrolled = true;
+  device_2.state->uv_retries = 8;
+  device_2.state->simulate_press_callback =
+      base::BindLambdaForTesting([&](VirtualFidoDevice* _) -> bool {
+        // If asked for a fingerprint, fail the makeCredential request by
+        // simulating a matched excluded credential by the other authenticator.
+        base::SequencedTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE, base::BindOnce(std::move(state_1->transact_callback),
+                                      std::vector<uint8_t>{static_cast<uint8_t>(
+                                          device::CtapDeviceResponseCode::
+                                              kCtap2ErrCredentialExcluded)}));
+        return false;
+      });
+
+  auto discovery =
+      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
+  discovery->AddDevice(std::move(device_1));
+  discovery->AddDevice(std::move(device_2));
+  AuthenticatorEnvironmentImpl::GetInstance()
+      ->ReplaceDefaultDiscoveryFactoryForTesting(std::move(discovery));
+
+  blocked_on_error_callback_ = base::BindLambdaForTesting([&]() {
+    // When the UI should show an error, have the second authenticator reply
+    // to the fingerprint touch and cancel the transaction.
+    std::move(state_2->transact_callback)
+        .Run(std::vector<uint8_t>{static_cast<uint8_t>(
+            device::CtapDeviceResponseCode::kCtap2ErrOperationDenied)});
+    test_client_.Cancel();
+  });
+
+  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
+            AuthenticatorStatus::CREDENTIAL_EXCLUDED);
+}
+
 // ResidentKeyTestAuthenticatorRequestDelegate is a delegate that:
 //   a) always returns |kTestPIN| when asked for a PIN.
 //   b) sorts potential resident-key accounts by user ID, maps them to a string
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java
index 4e135344..2145217 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java
@@ -44,6 +44,13 @@
     }
 
     /**
+     * Helper method to signal the beginning of a given unit test.
+     */
+    public void signalReadyForTest() {
+        mTestComplete = false;
+    }
+
+    /**
      * Helper method to signal the end of a given unit test.
      */
     public void signalEndOfTest() {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java
index af4d157..f501d13 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java
@@ -7,6 +7,7 @@
 import static org.chromium.content.browser.accessibility.AccessibilityContentShellTestUtils.ANP_ERROR;
 import static org.chromium.content.browser.accessibility.AccessibilityContentShellTestUtils.END_OF_TEST_ERROR;
 import static org.chromium.content.browser.accessibility.AccessibilityContentShellTestUtils.NODE_TIMEOUT_ERROR;
+import static org.chromium.content.browser.accessibility.AccessibilityContentShellTestUtils.READY_FOR_TEST_ERROR;
 import static org.chromium.content.browser.accessibility.AccessibilityContentShellTestUtils.sContentShellDelegate;
 
 import android.annotation.SuppressLint;
@@ -204,6 +205,17 @@
     }
 
     /**
+     * Call through the WebContentsAccessibilityImpl to send a signal that we are ready to begin
+     * a test (using the kEndOfTest signal for simplicity). Poll until we receive the generated
+     * Blink event in response, then reset the tracker.
+     */
+    public void sendReadyForTestSignal() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> mWcax.signalEndOfTestForTesting());
+        CriteriaHelper.pollUiThread(() -> mTracker.testComplete(), READY_FOR_TEST_ERROR);
+        TestThreadUtils.runOnUiThreadBlocking(() -> mTracker.signalReadyForTest());
+    }
+
+    /**
      * Call through the WebContentsAccessibilityImpl to send a kEndOfTest event to signal that we
      * are done with a test. Poll until we receive the generated Blink event in response.
      */
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestData.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestData.java
index 82b4af4..5b39ca1 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestData.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestData.java
@@ -29,6 +29,8 @@
     public int typeWindowContentChangedCount;
     public boolean receivedEvent;
     public boolean receivedAccessibilityFocusEvent;
+    public boolean receivedTraversalEvent;
+    public boolean receivedSelectionEvent;
 
     private AccessibilityContentShellTestData() {
         traverseFromIndex = -1;
@@ -39,6 +41,8 @@
         typeWindowContentChangedCount = 0;
         receivedEvent = false;
         receivedAccessibilityFocusEvent = false;
+        receivedTraversalEvent = false;
+        receivedSelectionEvent = false;
     }
 
     public int getTraverseFromIndex() {
@@ -108,4 +112,20 @@
     public void setReceivedAccessibilityFocusEvent(boolean receivedAccessibilityFocusEvent) {
         this.receivedAccessibilityFocusEvent = receivedAccessibilityFocusEvent;
     }
+
+    public boolean hasReceivedTraversalEvent() {
+        return receivedTraversalEvent;
+    }
+
+    public void setReceivedTraversalEvent(boolean receivedTraversalEvent) {
+        this.receivedTraversalEvent = receivedTraversalEvent;
+    }
+
+    public boolean hasReceivedSelectionEvent() {
+        return receivedSelectionEvent;
+    }
+
+    public void setReceivedSelectionEvent(boolean receivedSelectionEvent) {
+        this.receivedSelectionEvent = receivedSelectionEvent;
+    }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestUtils.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestUtils.java
index 0865cb2..a7e2bc8 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestUtils.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellTestUtils.java
@@ -20,6 +20,8 @@
             "Could not find specified node before polling timeout.";
     public static final String END_OF_TEST_ERROR =
             "Did not receive kEndOfTest signal before polling timeout.";
+    public static final String READY_FOR_TEST_ERROR =
+            "Did not receive kReadyForTest signal before polling timeout.";
 
     /**
      * Basic interface to define a way to match |AccessibilityNodeInfo| objects based on the
@@ -101,11 +103,13 @@
                         case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
                             data.setSelectionFromIndex(event.getFromIndex());
                             data.setSelectionToIndex(event.getToIndex());
+                            data.setReceivedSelectionEvent(true);
                             break;
                         }
                         case AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
                             data.setTraverseFromIndex(event.getFromIndex());
                             data.setTraverseToIndex(event.getToIndex());
+                            data.setReceivedTraversalEvent(true);
                             break;
                         }
 
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
index e6c63372e..be8cee6 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -66,6 +66,7 @@
         mActivityTestRule.waitForActiveShellToBeDoneLoading();
         mActivityTestRule.setupTestFramework();
         mActivityTestRule.setAccessibilityDelegate();
+        mActivityTestRule.sendReadyForTestSignal();
     }
 
     /**
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
index 4428f37..a577815 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -98,6 +98,8 @@
             "AccessibilityNodeInfo object should have unclipped bounds in extras bundle";
     private static final String EVENT_TYPE_MASK_ERROR =
             "Conversion of event masks to event types not correct.";
+    private static final String TEXT_SELECTION_AND_TRAVERSAL_ERROR =
+            "Expected to receive both a traversal and selection text event";
 
     // Constant values for unit tests
     private static final int UNSUPPRESSED_EXPECTED_COUNT = 15;
@@ -125,6 +127,7 @@
         mActivityTestRule.setAccessibilityDelegate();
 
         mTestData = AccessibilityContentShellTestData.getInstance();
+        mActivityTestRule.sendReadyForTestSignal();
     }
 
     /* @Before */
@@ -135,6 +138,7 @@
         mActivityTestRule.setAccessibilityDelegate();
 
         mTestData = AccessibilityContentShellTestData.getInstance();
+        mActivityTestRule.sendReadyForTestSignal();
     }
 
     /**
@@ -170,6 +174,30 @@
     }
 
     /**
+     * Helper method for sending text related events and confirming that the associated text
+     * selection and traversal events have been dispatched before continuing with test.
+     *
+     * @param viewId            int virtualViewId of the text field
+     * @param action            int action to perform
+     * @param args              Bundle optional arguments
+     * @throws ExecutionException   Error
+     */
+    private void performTextActionOnUiThread(int viewId, int action, Bundle args)
+            throws ExecutionException {
+        // Reset values for traversal and selection events.
+        mTestData.setReceivedTraversalEvent(false);
+        mTestData.setReceivedSelectionEvent(false);
+
+        // Perform our text selection/traversal action.
+        mActivityTestRule.performActionOnUiThread(viewId, action, args);
+
+        // Poll until both events have been confirmed as received
+        CriteriaHelper.pollUiThread(() -> {
+            return mTestData.hasReceivedTraversalEvent() && mTestData.hasReceivedSelectionEvent();
+        }, TEXT_SELECTION_AND_TRAVERSAL_ERROR);
+    }
+
+    /**
      * Test <input type="range"> nodes and events for incrementing/decrementing value with actions.
      */
     @Test
@@ -344,6 +372,7 @@
      */
     @Test
     @SmallTest
+    @MinAndroidSdkLevel(Build.VERSION_CODES.M)
     public void testMaxContentChangedEventsFired_default() throws Throwable {
         // Build a simple web page with complex visibility change.
         setupTestFromFile("content/test/data/android/type_window_content_changed_events.html");
@@ -367,6 +396,7 @@
      */
     @Test
     @SmallTest
+    @MinAndroidSdkLevel(Build.VERSION_CODES.M)
     public void testMaxContentChangedEventsFired_largeLimit() throws Throwable {
         // Build a simple web page with complex visibility change.
         setupTestFromFile("content/test/data/android/type_window_content_changed_events.html");
@@ -506,7 +536,6 @@
      */
     @Test
     @SmallTest
-    @FlakyTest(message = "https://crbug.com/1223574")
     public void testEventIndices_SelectionOFF_CharacterGranularity() throws Throwable {
         // Build a simple web page with an input and the text "Testing"
         setupTestWithHTML("<input id=\"fn\" type=\"text\" value=\"Testing\">");
@@ -527,7 +556,7 @@
 
         // Simulate swiping left (backward)
         for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
@@ -538,7 +567,7 @@
 
         // Simulate swiping right (forward)
         for (int i = 0; i < 7; i++) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i, mTestData.getTraverseFromIndex());
@@ -554,7 +583,6 @@
      */
     @Test
     @LargeTest
-    @FlakyTest(message = "https://crbug.com/1223574")
     public void testEventIndices_SelectionON_CharacterGranularity() throws Throwable {
         // Build a simple web page with an input and the text "Testing"
         setupTestWithHTML("<input id=\"fn\" type=\"text\" value=\"Testing\">");
@@ -575,7 +603,7 @@
 
         // Simulate swiping left (backward) (adds to selections)
         for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
@@ -586,7 +614,7 @@
 
         // Simulate swiping right (forward) (removes from selection)
         for (int i = 0; i < 7; i++) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i, mTestData.getTraverseFromIndex());
@@ -598,7 +626,7 @@
         // Turn selection mode off and traverse to beginning so we can select forwards
         args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false);
         for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
         }
 
@@ -607,7 +635,7 @@
 
         // Simulate swiping right (forward) (adds to selection)
         for (int i = 0; i < 7; i++) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i, mTestData.getTraverseFromIndex());
@@ -618,7 +646,7 @@
 
         // Simulate swiping left (backward) (removes from selections)
         for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
@@ -634,7 +662,6 @@
      */
     @Test
     @SmallTest
-    @FlakyTest(message = "https://crbug.com/1223574")
     public void testEventIndices_SelectionOFF_WordGranularity() throws Throwable {
         // Build a simple web page with an input and the text "Testing this output is correct"
         setupTestWithHTML(
@@ -659,7 +686,7 @@
 
         // Simulate swiping left (backward) through all 5 words, check indices along the way
         for (int i = 4; i >= 0; --i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -670,7 +697,7 @@
 
         // Simulate swiping right (forward) through all 5 words, check indices along the way
         for (int i = 0; i < 5; ++i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -686,7 +713,6 @@
      */
     @Test
     @LargeTest
-    @FlakyTest(message = "https://crbug.com/1223574")
     public void testEventIndices_SelectionON_WordGranularity() throws Throwable {
         setupTestWithHTML(
                 "<input id=\"fn\" type=\"text\" value=\"Testing this output is correct\">");
@@ -710,7 +736,7 @@
 
         // Simulate swiping left (backward, adds to selection) through all 5 words, check indices
         for (int i = 4; i >= 0; --i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -721,7 +747,7 @@
 
         // Simulate swiping right (forward, removes selection) through all 5 words, check indices
         for (int i = 0; i < 5; ++i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -733,7 +759,7 @@
         // Turn selection mode off and traverse to beginning so we can select forwards
         args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false);
         for (int i = 4; i >= 0; i--) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
         }
 
@@ -742,7 +768,7 @@
 
         // Simulate swiping right (forward) (adds to selection)
         for (int i = 0; i < 5; ++i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -753,7 +779,7 @@
 
         // Simulate swiping left (backward) (removes from selections)
         for (int i = 4; i >= 0; --i) {
-            performActionOnUiThread(editTextVirtualViewId,
+            performTextActionOnUiThread(editTextVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(wordStarts[i], mTestData.getTraverseFromIndex());
@@ -769,7 +795,6 @@
      */
     @Test
     @LargeTest
-    @FlakyTest(message = "https://crbug.com/1223574")
     public void testEventIndices_contenteditable_SelectionON_CharacterGranularity()
             throws Throwable {
         setupTestWithHTML("<div contenteditable>Testing</div>");
@@ -782,14 +807,9 @@
 
         focusNode(contentEditableVirtualViewId);
 
-        // Move cursor to the end of the field for consistency.
-        Bundle moveArgs = new Bundle();
-        moveArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
-                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
-        for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(contentEditableVirtualViewId,
-                    AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, moveArgs);
-        }
+        // Send an end of test signal to ensure test page has fully started since some bots
+        // seem to flake when the page has not fully loaded before testing begins.
+        mActivityTestRule.sendEndOfTestSignal();
 
         // Set granularity to CHARACTER, with selection TRUE
         Bundle args = new Bundle();
@@ -797,41 +817,9 @@
                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
         args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
 
-        // Simulate swiping left (backward) (adds to selections)
-        for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(contentEditableVirtualViewId,
-                    AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
-
-            Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
-            Assert.assertEquals(i, mTestData.getTraverseToIndex());
-            Assert.assertEquals(7, mTestData.getSelectionFromIndex());
-            Assert.assertEquals(i - 1, mTestData.getSelectionToIndex());
-        }
-
-        // Simulate swiping right (forward) (removes from selection)
-        for (int i = 0; i < 7; i++) {
-            performActionOnUiThread(contentEditableVirtualViewId,
-                    AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
-
-            Assert.assertEquals(i, mTestData.getTraverseFromIndex());
-            Assert.assertEquals(i + 1, mTestData.getTraverseToIndex());
-            Assert.assertEquals(7, mTestData.getSelectionFromIndex());
-            Assert.assertEquals(i + 1, mTestData.getSelectionToIndex());
-        }
-
-        // Turn selection mode off and traverse to beginning so we can select forwards
-        args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false);
-        for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(contentEditableVirtualViewId,
-                    AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
-        }
-
-        // Turn selection mode on
-        args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
-
         // Simulate swiping right (forward) (adds to selection)
         for (int i = 0; i < 7; i++) {
-            performActionOnUiThread(contentEditableVirtualViewId,
+            performTextActionOnUiThread(contentEditableVirtualViewId,
                     AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i, mTestData.getTraverseFromIndex());
@@ -842,7 +830,7 @@
 
         // Simulate swiping left (backward) (removes from selections)
         for (int i = 7; i > 0; i--) {
-            performActionOnUiThread(contentEditableVirtualViewId,
+            performTextActionOnUiThread(contentEditableVirtualViewId,
                     AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
 
             Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
@@ -850,6 +838,38 @@
             Assert.assertEquals(0, mTestData.getSelectionFromIndex());
             Assert.assertEquals(i - 1, mTestData.getSelectionToIndex());
         }
+
+        // Turn selection mode off and traverse to end so we can select backwards
+        args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, false);
+        for (int i = 7; i > 0; i--) {
+            performTextActionOnUiThread(contentEditableVirtualViewId,
+                    AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
+        }
+
+        // Turn selection mode on
+        args.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
+
+        // Simulate swiping left (backward) (adds to selections)
+        for (int i = 7; i > 0; i--) {
+            performTextActionOnUiThread(contentEditableVirtualViewId,
+                    AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, args);
+
+            Assert.assertEquals(i - 1, mTestData.getTraverseFromIndex());
+            Assert.assertEquals(i, mTestData.getTraverseToIndex());
+            Assert.assertEquals(7, mTestData.getSelectionFromIndex());
+            Assert.assertEquals(i - 1, mTestData.getSelectionToIndex());
+        }
+
+        // Simulate swiping right (forward) (removes from selection)
+        for (int i = 0; i < 7; i++) {
+            performTextActionOnUiThread(contentEditableVirtualViewId,
+                    AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, args);
+
+            Assert.assertEquals(i, mTestData.getTraverseFromIndex());
+            Assert.assertEquals(i + 1, mTestData.getTraverseToIndex());
+            Assert.assertEquals(7, mTestData.getSelectionFromIndex());
+            Assert.assertEquals(i + 1, mTestData.getSelectionToIndex());
+        }
     }
 
     /**
diff --git a/content/public/browser/back_forward_cache.h b/content/public/browser/back_forward_cache.h
index 49802f76..32f7697 100644
--- a/content/public/browser/back_forward_cache.h
+++ b/content/public/browser/back_forward_cache.h
@@ -127,6 +127,14 @@
     // load a page that is ineligible for caching (e.g. due to an unsupported
     // feature).
     TEST_USES_UNLOAD_EVENT,
+
+    // This test expects that same-site navigations won't result in a
+    // RenderFrameHost / RenderFrame / RenderView / RenderWidget change.
+    // But when same-site BackForwardCache is enabled, the change usually does
+    // happen. Even so, there will still be valid navigations that don't result
+    // in those objects changing, so we should keep the test as is, just with
+    // BackForwardCache disabled.
+    TEST_ASSUMES_NO_RENDER_FRAME_CHANGE,
   };
 
   // Evict all entries from the BackForwardCache.
diff --git a/content/public/test/test_launcher.cc b/content/public/test/test_launcher.cc
index 06331475..3e1ea14 100644
--- a/content/public/test/test_launcher.cc
+++ b/content/public/test/test_launcher.cc
@@ -58,6 +58,9 @@
 #include "sandbox/policy/win/sandbox_win.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/sandbox_types.h"
+
+// To avoid conflicts with the macro from the Windows SDK...
+#undef GetCommandLine
 #elif defined(OS_MAC)
 #include "base/mac/scoped_nsautorelease_pool.h"
 #include "sandbox/mac/seatbelt_exec.h"
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index 03edfce..db400732 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -201,7 +201,7 @@
 
 // Disable platform crash handling and initialize the crash reporter, if
 // requested.
-// TODO(crbug.com/753619): Implement crash reporter integration for Fuchsia.
+// TODO(crbug.com/1226159): Implement crash reporter integration for Fuchsia.
 #if !defined(OS_FUCHSIA)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableCrashReporter)) {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index ea8b2e5..2cc8c3f 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -685,6 +685,10 @@
 if (is_fuchsia) {
   group("fuchsia_telemetry_gpu_integration_test") {
     testonly = true
+    data = [
+      "//content/test/gpu/fuchsia_util.py",
+      "//content/test/gpu/run_gpu_integration_test_fuchsia.py",
+    ]
     data_deps = [
       ":telemetry_gpu_integration_test_scripts_only",
       ":telemetry_gpu_integration_test_support",
@@ -694,11 +698,9 @@
   }
   group("performance_web_engine_test_suite") {
     testonly = true
-    data = [
-      "//content/test/gpu/run_telemetry_benchmark_fuchsia.py",
-      "//content/test/gpu/",
-    ]
+    data = [ "//content/test/gpu/run_telemetry_benchmark_fuchsia.py" ]
     data_deps = [
+      ":telemetry_gpu_integration_test_data",
       "//fuchsia/engine:web_engine_shell",
       "//fuchsia/engine:web_engine_with_webui",
       "//testing:run_perf_test",
@@ -713,19 +715,16 @@
     "//tools/perf/chrome_telemetry_build:telemetry_chrome_test_without_chrome",
   ]
 
-  data = [
-    "//content/test/gpu/",
-    "//testing/scripts/run_isolated_script_test.py",
+  data = [ "//testing/scripts/run_isolated_script_test.py" ]
+  data_deps = [
+    ":telemetry_gpu_integration_test_data",
+    "//testing:test_scripts_shared",
   ]
-  data_deps = [ "//testing:test_scripts_shared" ]
 }
 
 group("telemetry_gpu_integration_test_support") {
   testonly = true
   data = [
-    "//content/test/gpu/",
-    "//content/test/data/gpu/",
-
     # For the Maps performance test. Include the entire directory to
     # avoid having to update this BUILD.gn file if more files are
     # added in the future.
@@ -741,7 +740,6 @@
 
     # For webgl_conformance
     "//third_party/webgl/",
-    "//content/test/gpu/run_gpu_integration_test.py",
 
     # For pixel_test and trace_test
     "//media/test/data/four-colors.mp4",
@@ -762,20 +760,44 @@
     # For isolate contract.
     "//testing/scripts/gpu_integration_test_adapter.py",
     "//testing/scripts/run_gpu_integration_test_as_googletest.py",
-
-    # Not actually needed, but the way Telemetry looks for tests ends up looking
-    # in the unexpected_passes directory, which has a dependency on this.
-    # TODO(crbug.com/1227899): Remove this dependency once this target only
-    # includes the things it needs instead of all of //content/test/gpu/.
-    "//testing/unexpected_passes_common/",
   ]
 
   data_deps = [
+    ":telemetry_gpu_integration_test_data",
+
     # For anything using Skia Gold (pixel, maps).
     "//ui/base:goldctl",
   ]
 }
 
+group("telemetry_gpu_unittest_data") {
+  testonly = true
+  data = [
+    "//content/test/data/gpu/",
+    "//content/test/gpu/gpu_tests/",
+    "//content/test/gpu/unittest_data/",
+
+    "//content/test/gpu/gpu_project_config.py",
+    "//content/test/gpu/run_gpu_integration_test.py",
+    "//content/test/gpu/run_unittests.py",
+  ]
+}
+
+group("telemetry_gpu_integration_test_data") {
+  testonly = true
+  data = [
+    "//content/test/data/gpu/",
+    "//content/test/gpu/gold_inexact_matching/",
+    "//content/test/gpu/gpu_tests/",
+    "//content/test/gpu/power_measurement_results/",
+    "//content/test/gpu/unittest_data/",
+
+    "//content/test/gpu/gpu_project_config.py",
+    "//content/test/gpu/measure_power_intel.py",
+    "//content/test/gpu/run_gpu_integration_test.py",
+  ]
+}
+
 # browsertest_support can be used by targets that run content_shell based
 # browser tests.
 static_library("browsertest_support") {
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
index ad613c34..a1c6a66 100644
--- a/content/test/content_browser_test_utils_internal.cc
+++ b/content/test/content_browser_test_utils_internal.cc
@@ -22,6 +22,7 @@
 #include "base/test/bind.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/prerender/prerender_host_registry.h"
 #include "content/browser/renderer_host/delegated_frame_host.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/navigation_request.h"
@@ -862,4 +863,48 @@
   return get();
 }
 
+InactiveRenderFrameHostDeletionObserver::
+    InactiveRenderFrameHostDeletionObserver(WebContents* content)
+    : WebContentsObserver(content) {}
+
+InactiveRenderFrameHostDeletionObserver::
+    ~InactiveRenderFrameHostDeletionObserver() = default;
+
+void InactiveRenderFrameHostDeletionObserver::Wait() {
+  // Some RenderFrameHost may remain in the BackForwardCache and or as
+  // prerendered pages. Trigger deletion for them asynchronously.
+  static_cast<WebContentsImpl*>(web_contents())
+      ->GetController()
+      .GetBackForwardCache()
+      .Flush();
+  if (blink::features::IsPrerender2Enabled()) {
+    static_cast<WebContentsImpl*>(web_contents())
+        ->GetPrerenderHostRegistry()
+        ->CancelAllHostsForTesting();
+  }
+
+  for (RenderFrameHost* rfh : CollectAllRenderFrameHosts(web_contents())) {
+    // Keep track of all currently inactive RenderFrameHosts so that we can wait
+    // for all of them to be deleted.
+    if (!rfh->IsActive())
+      inactive_rfhs_.insert(rfh);
+  }
+  loop_ = std::make_unique<base::RunLoop>();
+  CheckCondition();
+  loop_->Run();
+}
+
+void InactiveRenderFrameHostDeletionObserver::RenderFrameDeleted(
+    RenderFrameHost* rfh) {
+  if (inactive_rfhs_.count(rfh) == 0)
+    return;
+  inactive_rfhs_.erase(rfh);
+  CheckCondition();
+}
+
+void InactiveRenderFrameHostDeletionObserver::CheckCondition() {
+  if (loop_ && inactive_rfhs_.empty())
+    loop_->Quit();
+}
+
 }  // namespace content
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h
index ed68e90..defd39f8 100644
--- a/content/test/content_browser_test_utils_internal.h
+++ b/content/test/content_browser_test_utils_internal.h
@@ -638,6 +638,26 @@
   RenderFrameHostImpl* operator->() const;
 };
 
+// Use this class to wait for all RenderFrameHosts in a WebContents that are
+// inactive (pending deletion, stored in BackForwardCache, prerendered, etc) to
+// be deleted. This will triggerBackForwardCache flushing and prerender
+// cancellations..
+class InactiveRenderFrameHostDeletionObserver : public WebContentsObserver {
+ public:
+  explicit InactiveRenderFrameHostDeletionObserver(WebContents* content);
+  ~InactiveRenderFrameHostDeletionObserver() override;
+
+  void Wait();
+
+ private:
+  void RenderFrameDeleted(RenderFrameHost*) override;
+
+  void CheckCondition();
+
+  std::unique_ptr<base::RunLoop> loop_;
+  std::set<RenderFrameHost*> inactive_rfhs_;
+};
+
 }  // namespace content
 
 #endif  // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
diff --git a/content/test/data/accessibility/aria/aria-radio-in-shadow-root-expected-blink.txt b/content/test/data/accessibility/aria/aria-radio-in-shadow-root-expected-blink.txt
new file mode 100644
index 0000000..56c3f8b
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-radio-in-shadow-root-expected-blink.txt
@@ -0,0 +1,62 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++radioGroup name='Group One' setSize=3
+++++++++heading name='Group One'
+++++++++++staticText name='Group One'
+++++++++++++inlineTextBox name='Group One'
+++++++++radioButton name='Red' setSize=3 posInSet=1 checkedState=true
+++++++++++staticText name='Red'
+++++++++++++inlineTextBox name='Red'
+++++++++radioButton name='Green' setSize=3 posInSet=2 checkedState=false
+++++++++++staticText name='Green'
+++++++++++++inlineTextBox name='Green'
+++++++++radioButton name='Blue' setSize=3 posInSet=3 checkedState=false
+++++++++++genericContainer ignored
+++++++++++++staticText name='Blue'
+++++++++++++++inlineTextBox name='Blue'
+++++++radioGroup name='Group Two' setSize=3
+++++++++genericContainer ignored
+++++++++++heading name='Group Two'
+++++++++++++staticText name='Group Two'
+++++++++++++++inlineTextBox name='Group Two'
+++++++++++radioButton name='Red' setSize=3 posInSet=1 checkedState=true
+++++++++++++staticText name='Red'
+++++++++++++++inlineTextBox name='Red'
+++++++++++radioButton name='Green' setSize=3 posInSet=2 checkedState=false
+++++++++++++staticText name='Green'
+++++++++++++++inlineTextBox name='Green'
+++++++++++radioButton name='Blue' setSize=3 posInSet=3 checkedState=false
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='Blue'
+++++++++++++++++inlineTextBox name='Blue'
+++++++radioGroup name='Group with aria-setsize and aria-posinset' setSize=8
+++++++++genericContainer ignored
+++++++++++heading name='Group with aria-setsize and aria-posinset'
+++++++++++++staticText name='Group with aria-setsize and aria-posinset'
+++++++++++++++inlineTextBox name='Group with aria-setsize and aria-posinset'
+++++++++++radioButton name='Red' setSize=8 posInSet=5 checkedState=true
+++++++++++++staticText name='Red'
+++++++++++++++inlineTextBox name='Red'
+++++++++++radioButton name='Green' setSize=8 posInSet=6 checkedState=false
+++++++++++++staticText name='Green'
+++++++++++++++inlineTextBox name='Green'
+++++++++++radioButton name='Blue' setSize=8 posInSet=7 checkedState=false
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='Blue'
+++++++++++++++++inlineTextBox name='Blue'
+++++++group name='Checkbox Group One' setSize=0
+++++++++genericContainer ignored
+++++++++++heading name='Checkbox Group One'
+++++++++++++staticText name='Checkbox Group One'
+++++++++++++++inlineTextBox name='Checkbox Group One'
+++++++++++checkBox name='Red' checkedState=true
+++++++++++++staticText name='Red'
+++++++++++++++inlineTextBox name='Red'
+++++++++++checkBox name='Green' checkedState=false
+++++++++++++staticText name='Green'
+++++++++++++++inlineTextBox name='Green'
+++++++++++checkBox name='Blue' checkedState=false
+++++++++++++genericContainer ignored
+++++++++++++++staticText name='Blue'
+++++++++++++++++inlineTextBox name='Blue'
diff --git a/content/test/data/accessibility/aria/aria-radio-in-shadow-root.html b/content/test/data/accessibility/aria/aria-radio-in-shadow-root.html
new file mode 100644
index 0000000..7e980fb
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-radio-in-shadow-root.html
@@ -0,0 +1,69 @@
+<!--
+@BLINK-ALLOW:setSize*
+@BLINK-ALLOW:posInSet*
+-->
+<div role="radiogroup" aria-labelledby="group-1">
+    <h1 id="group-1">Group One</h1>
+    <div id="radio-1a" role="radio" aria-checked="true" tabindex="0">
+        Red
+    </div>
+    <div id="radio-2a" role="radio" aria-checked="false" tabindex="0">
+        Green
+    </div>
+    <my-item id="radio-3a" role="radio" aria-checked="false" tabindex="0">
+        Blue
+    </my-item>
+</div>
+
+<new-el role="radiogroup" aria-labelledby="group-2">
+    <h1 id="group-2">Group Two</h1>
+    <div id="radio-1b" role="radio" aria-checked="true" tabindex="0">
+        Red
+    </div>
+    <div id="radio-2b" role="radio" aria-checked="false" tabindex="0">
+        Green
+    </div>
+    <my-item id="radio-3b" role="radio" aria-checked="false" tabindex="0">
+        Blue
+    </my-item>
+</new-el>
+
+<new-el role="radiogroup" aria-labelledby="group-2a">
+    <h1 id="group-2a">Group with aria-setsize and aria-posinset</h1>
+    <div id="radio-1b" role="radio" aria-checked="true" tabindex="0" aria-posinset="5" aria-setsize="8">
+        Red
+    </div>
+    <div id="radio-2b" role="radio" aria-checked="false" tabindex="0" aria-posinset="6" aria-setsize="8">
+        Green
+    </div>
+    <my-item id="radio-3b" role="radio" aria-checked="false" tabindex="0" aria-posinset="7" aria-setsize="8">
+        Blue
+    </my-item>
+</new-el>
+
+
+<new-el role="group" aria-labelledby="group-3">
+    <h1 id="group-3">Checkbox Group One</h1>
+    <div id="radio-1b" role="checkbox" aria-checked="true" tabindex="0">
+        Red
+    </div>
+    <div id="radio-2b" role="checkbox" aria-checked="false" tabindex="0">
+        Green
+    </div>
+    <my-item id="radio-3b" role="checkbox" aria-checked="false" tabindex="0">
+        Blue
+    </my-item>
+</new-el>
+
+<script>
+    class SlottedElement extends HTMLElement {
+        constructor() {
+            super();
+            this.attachShadow({mode: 'open'});
+            this.shadowRoot.innerHTML = '<slot></slot>';
+        }
+    }
+    customElements.define('new-el', class extends SlottedElement {});
+    customElements.define('my-item', class extends SlottedElement {});
+</script>
+
diff --git a/content/test/data/accessibility/mac/action/ax-press-button-expected-mac.txt b/content/test/data/accessibility/mac/action/ax-press-button-expected-mac.txt
new file mode 100644
index 0000000..4a523dd
--- /dev/null
+++ b/content/test/data/accessibility/mac/action/ax-press-button-expected-mac.txt
@@ -0,0 +1 @@
+AXFocusedUIElementChanged on AXButton AXTitle="Press Me"
diff --git a/content/test/data/accessibility/mac/action/ax-press-button.html b/content/test/data/accessibility/mac/action/ax-press-button.html
new file mode 100644
index 0000000..2fbd8b5
--- /dev/null
+++ b/content/test/data/accessibility/mac/action/ax-press-button.html
@@ -0,0 +1,15 @@
+<!--
+@MAC-SCRIPT:
+  button.AXPerformAction(AXPress)
+  wait for AXFocusedUIElementChanged on AXButton
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+</style>
+</head>
+<body>
+<button id="button">Press Me</button>
+</body>
+</html>
diff --git a/content/test/data/accessibility/readme.md b/content/test/data/accessibility/readme.md
index e01b21d7..98ad130 100644
--- a/content/test/data/accessibility/readme.md
+++ b/content/test/data/accessibility/readme.md
@@ -175,23 +175,54 @@
 to dump accessible name of an accessible node for a DOM element having
 `input` DOM id on Mac platform. You can also use `:LINE_NUM` syntax to indicate
 an accessible object, where `LINE_NUM` is index of a line where
-the accessible object is placed in the formatted tree.
+the accessible object is placed in the formatted tree. However you should avoid
+using `:LINE_NUM` in a test as it may break the test automatic rebaseling.
+
+You can put multiple instructions under the same `MAC-SCRIPT` directive, for
+example:
+```
+MAC-SCRIPT:
+  input.AXRole
+  input.AXName
+```
 
 Calls can be chained, for example:
 
 `input.AXFocusableAncestor.AXRole`
 
-Paramaterized attributes are also supported, for example:
+Parameterized attributes are also supported, for example:
 
+`paragraph.AXTextMarkerForIndex(0)`
+
+`AXTextMarker` is serialized as a `{:LINE_NUM, offset, direction}` triple, for
+example:
 `textarea.AXPreviousWordStartTextMarkerForTextMarker({:3, 3, down})`
 
+`AXTextMarkerRange` is serialized as a dictionary:
+`{anchor: TEXT_MARKER, focus: TEXT_MARKER}`.
+
+You can also retrieve `anchor` and `focus` text markers from a text marker range,
+for example:
+
+`p.AXTextMarkerRangeForUIElement(p).anchor` or
+`p.AXTextMarkerRangeForUIElement(p).focus`
+
 You can also use array operator[] to refer to an array element at a given index,
 for example `paragraph.AXChildren[0]` will refer to the first child of the paragraph.
 
-You can also rerieve `anchor` and `focus` text markers from a text marker range,
-for example:
+You can use `waitfor` instruction to wait for a specific event before the script
+continues, for example:
 
-`p.AXTextMarkerRangeForUIElement(p).anchor`
+```
+MAC-SCRIPT:
+  button.AXPerformAction(AXPress)
+  wait for AXFocusedUIElementChanged
+```
+
+will trigger `AXPress` action on a button and will wait for
+`AXFocusedUIElementChanged` event. You can also be more specific if you want to
+and provide the event target, for example:
+`wait for AXFocusedUIElementChanged on AXButton`
 
 ### Advanced directives
 
diff --git a/content/test/data/media/video-player.html b/content/test/data/media/video-player.html
index 3c80192..d81d093 100644
--- a/content/test/data/media/video-player.html
+++ b/content/test/data/media/video-player.html
@@ -5,7 +5,7 @@
   <meta name=viewport content='width=device-width initial-scale=1.0'>
 </head>
 <body>
-  <video controls id=video src=bear.webm controlsList='noremoteplayback'></video>
+  <video controls id=video src=bear.webm controlsList='noplaybackrate noremoteplayback'></video>
   <button id='fullscreen'>fullscreen</button>
 </body>
 <script>
diff --git a/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc b/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
index c1f50cb..d8b5b19 100644
--- a/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
+++ b/content/test/fuzzer/code_cache_host_mojolpm_fuzzer.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/i18n/icu_util.h"
+#include "base/no_destructor.h"
 #include "base/test/test_switches.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
diff --git a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc
index 453535e..992fd151 100644
--- a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc
+++ b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/i18n/icu_util.h"
+#include "base/no_destructor.h"
 #include "base/test/test_switches.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
diff --git a/content/test/gpu/PRESUBMIT.py b/content/test/gpu/PRESUBMIT.py
index f2d1fe1..6ee1289 100644
--- a/content/test/gpu/PRESUBMIT.py
+++ b/content/test/gpu/PRESUBMIT.py
@@ -50,6 +50,15 @@
                                  'unexpected_passes'), [r'^.+_unittest\.py$'],
           env=gpu_env))
 
+  results.extend(
+      input_api.canned_checks.RunUnitTestsInDirectory(
+          input_api,
+          output_api,
+          input_api.os_path.join(input_api.PresubmitLocalPath(),
+                                 'flake_suppressor'), [r'^.+_unittest\.py$'],
+          env=gpu_env,
+          run_on_python2=False))
+
   pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api)
   results.extend(input_api.RunTests(pylint_checks))
 
diff --git a/content/test/gpu/flake_suppressor/__init__.py b/content/test/gpu/flake_suppressor/__init__.py
new file mode 100644
index 0000000..ceffacc
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/__init__.py
@@ -0,0 +1,6 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from gpu_tests import path_util
+path_util.SetupTypPath()
diff --git a/content/test/gpu/flake_suppressor/expectations.py b/content/test/gpu/flake_suppressor/expectations.py
new file mode 100644
index 0000000..7e6e895a
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/expectations.py
@@ -0,0 +1,270 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Module for interacting with expectation files."""
+
+import os
+
+from typ import expectations_parser
+
+EXPECTATION_FILE_DIRECTORY = os.path.realpath(
+    os.path.join(os.path.dirname(__file__), '..', 'gpu_tests',
+                 'test_expectations'))
+# For most test suites reported to ResultDB, we can chop off "_integration_test"
+# and get the name used for the expectation file. However, there are a few
+# special cases, so map those there.
+EXPECTATION_FILE_OVERRIDE = {
+    'info_collection_test': 'info_collection',
+    'trace': 'trace_test',
+}
+
+
+def IterateThroughResultsForUser(result_map, group_by_tags):
+  """Iterates over |result_map| for the user to provide input.
+
+  For each unique result, user will be able to decide whether to ignore it (do
+  nothing), mark as flaky (add RetryOnFailure expectation), or mark as failing
+  (add Failure expectation). If the latter two are chosen, they can also
+  associate a bug with the new expectation.
+
+  Args:
+    result_map: Aggregated query results from results.AggregateResults to
+        iterate over.
+    group_by_tags: A boolean denoting whether to attempt to group expectations
+        by tags or not. If True, expectations will be added after an existing
+        expectation whose tags are the largest subset of the produced tags. If
+        False, new expectations will be appended to the end of the file.
+  """
+  for suite, test_map in result_map.items():
+    for test, tag_map in test_map.items():
+      for _, unique_result in tag_map.items():
+        typ_tags = unique_result['typ_tags']
+        build_url_list = unique_result['build_url_list']
+
+        print('')
+        print('Suite: %s' % suite)
+        print('Test: %s' % test)
+        print('Configuration:\n    %s' % '\n    '.join(typ_tags))
+        print('Failed builds:\n    %s' % '\n    '.join(build_url_list))
+
+        other_failures_for_test = FindFailuresInSameTest(
+            result_map, suite, test, typ_tags)
+        if other_failures_for_test:
+          print('Other failures in same test found on other configurations')
+          for (tags, failure_count) in other_failures_for_test:
+            print('    %d failures on %s' % (failure_count, ' '.join(tags)))
+
+        other_failures_for_config = FindFailuresInSameConfig(
+            result_map, suite, test, typ_tags)
+        if other_failures_for_config:
+          print('Other failures on same configuration found in other tests')
+          for (name, failure_count) in other_failures_for_config:
+            print('    %d failures in %s' % (failure_count, name))
+
+        expected_result, bug = PromptUserForExpectationAction()
+        if not expected_result:
+          continue
+
+        ModifyFileForResult(suite, test, typ_tags, bug, expected_result,
+                            group_by_tags)
+
+
+def FindFailuresInSameTest(result_map, target_suite, target_test,
+                           target_typ_tags):
+  """Finds all other failures that occurred in the given test.
+
+  Ignores the failures for the test on the same configuration.
+
+  Args:
+    result_map: Aggregated query results from results.AggregateResults.
+    target_suite: A string containing the test suite being checked.
+    target_test: A string containing the target test case being checked.
+    target_typ_tags: A list of strings containing the typ tags that the failure
+        took place on.
+
+  Returns:
+    A list of tuples (typ_tags, count). |typ_tags| is a list of strings
+    defining a configuration the specified test failed on. |count| is how many
+    times the test failed on that configuration.
+  """
+  other_failures = []
+  tag_map = result_map.get(target_suite, {}).get(target_test, {})
+  for _, unique_result in tag_map.items():
+    typ_tags = unique_result['typ_tags']
+    if typ_tags == target_typ_tags:
+      continue
+    other_failures.append((typ_tags, len(unique_result['build_url_list'])))
+  return other_failures
+
+
+def FindFailuresInSameConfig(result_map, target_suite, target_test,
+                             target_typ_tags):
+  """Finds all other failures that occurred on the given configuration.
+
+  Ignores the failures for the given test on the given configuration.
+
+  Args:
+    result_map: Aggregated query results from results.AggregateResults.
+    target_suite: A string containing the test suite the original failure was
+        found in.
+    target_test: A string containing the test case the original failure was
+        found in.
+    target_typ_tags: A list of strings containing the typ tags defining the
+        configuration to find failures for.
+
+  Returns:
+    A list of tuples (full_name, count). |full_name| is a string containing a
+    test suite and test case concatenated together. |count| is how many times
+    |full_name| failed on the configuration specified by |target_typ_tags|.
+  """
+  # TODO(crbug.com/1192733): Maybe create a typ_tags -> suite -> test_map dict
+  # elsewhere once and use that instead of looping through everything every
+  # time.
+  other_failures = []
+  for suite, test_map in result_map.items():
+    for test, tag_map in test_map.items():
+      if suite == target_suite and test == target_test:
+        continue
+      for _, unique_result in tag_map.items():
+        typ_tags = unique_result['typ_tags']
+        if typ_tags != target_typ_tags:
+          continue
+        full_name = '%s.%s' % (suite, test)
+        other_failures.append((full_name, len(unique_result['build_url_list'])))
+  return other_failures
+
+
+def PromptUserForExpectationAction():
+  """Prompts the user on what to do to handle a failure.
+
+  Returns:
+    A tuple (expected_result, bug). |expected_result| is a string containing
+    the expected result to use for the expectation, e.g. RetryOnFailure. |bug|
+    is a string containing the bug to use for the expectation. If the user
+    chooses to ignore the failure, both will be None. Otherwise, both are
+    filled, although |bug| may be an empty string if no bug is provided.
+  """
+  prompt = ('How should this failure be handled? (i)gnore/(r)etry on '
+            'failure/(f)ailure: ')
+  valid_inputs = ['f', 'i', 'r']
+  response = input(prompt).lower()
+  while response not in valid_inputs:
+    print('Invalid input, valid inputs are %s' % (', '.join(valid_inputs)))
+    response = input(prompt).lower()
+
+  if response == 'i':
+    return (None, None)
+  expected_result = 'RetryOnFailure' if response == 'r' else 'Failure'
+
+  prompt = ('What is the bug URL that should be associated with this '
+            'expectation? E.g. crbug.com/1234. ')
+  response = input(prompt)
+  return (expected_result, response)
+
+
+def ModifyFileForResult(suite, test, typ_tags, bug, expected_result,
+                        group_by_tags):
+  """Adds an expectation to the appropriate expectation file.
+
+  Args:
+    suite: A string containing the suite the failure occurred in.
+    test: A string containing the test case the failure occurred in.
+    typ_tags: A list of strings containing the typ tags the test produced.
+    bug: A string containing the bug to associate with the new expectation.
+    expected_result: A string containing the expected result to use for the new
+        expectation, e.g. RetryOnFailure.
+    group_by_tags: A boolean denoting whether to attempt to group expectations
+        by tags or not. If True, expectations will be added after an existing
+        expectation whose tags are the largest subset of the produced tags. If
+        False, new expectations will be appended to the end of the file.
+  """
+  expectation_file = GetExpectationFileForSuite(suite, typ_tags)
+  bug = '%s ' % bug if bug else bug
+
+  def AppendExpectationToEnd():
+    expectation_line = '%s[ %s ] %s [ %s ]\n' % (bug, ' '.join(typ_tags), test,
+                                                 expected_result)
+    with open(expectation_file, 'a') as outfile:
+      outfile.write(expectation_line)
+
+  if group_by_tags:
+    insertion_line, best_matching_tags = FindBestInsertionLineForExpectation(
+        typ_tags, expectation_file)
+    if insertion_line == -1:
+      AppendExpectationToEnd()
+    else:
+      # enumerate starts at 0 but line numbers start at 1.
+      insertion_line -= 1
+      best_matching_tags = list(best_matching_tags)
+      best_matching_tags.sort()
+      expectation_line = '%s[ %s ] %s [ %s ]\n' % (
+          bug, ' '.join(best_matching_tags), test, expected_result)
+      with open(expectation_file) as infile:
+        input_contents = infile.read()
+      output_contents = ''
+      for lineno, line in enumerate(input_contents.splitlines(True)):
+        output_contents += line
+        if lineno == insertion_line:
+          output_contents += expectation_line
+      with open(expectation_file, 'w') as outfile:
+        outfile.write(output_contents)
+  else:
+    AppendExpectationToEnd()
+
+
+def GetExpectationFileForSuite(suite, typ_tags):
+  """Finds the correct expectation file for the given suite.
+
+  Args:
+    suite: A string containing the test suite to look for.
+    typ_tags: A list of strings containing typ tags that were produced by the
+        failing test.
+
+  Returns:
+    A string containing a filepath to the correct expectation file for |suite|
+    and |typ_tags|.
+  """
+  truncated_suite = suite.replace('_integration_test', '')
+  if truncated_suite == 'webgl_conformance':
+    if 'webgl-version-2' in typ_tags:
+      truncated_suite = 'webgl2_conformance'
+
+  expectation_file = EXPECTATION_FILE_OVERRIDE.get(truncated_suite,
+                                                   truncated_suite)
+  expectation_file += '_expectations.txt'
+  expectation_file = os.path.join(EXPECTATION_FILE_DIRECTORY, expectation_file)
+  return expectation_file
+
+
+def FindBestInsertionLineForExpectation(typ_tags, expectation_file):
+  """Finds the best place to insert an expectation when grouping by tags.
+
+  Args:
+    typ_tags: A list of strings containing typ tags that were produced by the
+        failing test.
+    expectation_file: A string containing a filepath to the expectation file to
+        use.
+
+  Returns:
+    A tuple (insertion_line, best_matching_tags). |insertion_line| is an int
+    specifying the line number to insert the expectation into.
+    |best_matching_tags| is a set containing the tags of an existing expectation
+    that was found to be the closest match. If no appropriate line is found,
+    |insertion_line| is -1 and |best_matching_tags| is empty.
+  """
+  best_matching_tags = set()
+  best_insertion_line = -1
+  with open(expectation_file) as f:
+    content = f.read()
+  list_parser = expectations_parser.TaggedTestListParser(content)
+  for e in list_parser.expectations:
+    expectation_tags = e.tags
+    if not expectation_tags.issubset(typ_tags):
+      continue
+    if len(expectation_tags) > len(best_matching_tags):
+      best_matching_tags = expectation_tags
+      best_insertion_line = e.lineno
+    elif len(expectation_tags) == len(best_matching_tags):
+      if best_insertion_line < e.lineno:
+        best_insertion_line = e.lineno
+  return best_insertion_line, best_matching_tags
diff --git a/content/test/gpu/flake_suppressor/expectations_unittest.py b/content/test/gpu/flake_suppressor/expectations_unittest.py
new file mode 100755
index 0000000..f3efca6a
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/expectations_unittest.py
@@ -0,0 +1,384 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import unittest
+
+# This script is not Python 2-compatible, but some presubmit scripts end up
+# trying to parse this to find tests.
+# TODO(crbug.com/1198237): Remove this once all the GPU tests, and by
+# extension the presubmit scripts, are Python 3-compatible.
+if sys.version_info[0] == 3:
+  import unittest.mock as mock
+
+import validate_tag_consistency
+
+from pyfakefs import fake_filesystem_unittest
+
+from flake_suppressor import expectations
+from flake_suppressor import unittest_utils as uu
+
+
+# Note for all tests in this class: We can safely check the contents of the file
+# at the end despite potentially having multiple added lines because Python 3.7+
+# guarantees that dictionaries remember insertion order, so there is no risk of
+# the order of modification changing.
+@unittest.skipIf(sys.version_info[0] != 3, 'Python 3-only')
+class IterateThroughResultsForUserUnittest(fake_filesystem_unittest.TestCase):
+  def setUp(self):
+    self._new_stdout = open(os.devnull, 'w')
+    self.setUpPyfakefs()
+    # Redirect stdout since the tested function prints a lot.
+    self._old_stdout = sys.stdout
+    sys.stdout = self._new_stdout
+
+    self._input_patcher = mock.patch.object(expectations,
+                                            'PromptUserForExpectationAction')
+    self._input_mock = self._input_patcher.start()
+    self.addCleanup(self._input_patcher.stop)
+
+    self.result_map = {
+        'pixel_integration_test': {
+            'foo_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['a'],
+                },
+                'mac': {
+                    'typ_tags': ['mac'],
+                    'build_url_list': ['b'],
+                },
+            },
+            'bar_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['c'],
+                },
+            },
+        },
+    }
+
+    self.expectation_file = os.path.join(
+        expectations.EXPECTATION_FILE_DIRECTORY, 'pixel_expectations.txt')
+    uu.CreateFile(self, self.expectation_file)
+    expectation_file_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ android ] some_test [ Failure ]
+"""
+    with open(self.expectation_file, 'w') as outfile:
+      outfile.write(expectation_file_contents)
+
+  def tearDown(self):
+    sys.stdout = self._old_stdout
+    self._new_stdout.close()
+
+  def testIterateThroughResultsForUserIgnoreNoGroupByTags(self):
+    """Tests that everything appears to function with ignore and no group."""
+    self._input_mock.return_value = (None, None)
+    expectations.IterateThroughResultsForUser(self.result_map, False)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ android ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testIterateThroughResultsForUserIgnoreGroupByTags(self):
+    """Tests that everything appears to function with ignore and grouping."""
+    self._input_mock.return_value = (None, None)
+    expectations.IterateThroughResultsForUser(self.result_map, True)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ android ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testIterateThroughResultsForUserRetryNoGroupByTags(self):
+    """Tests that everything appears to function with retry and no group."""
+    self._input_mock.return_value = ('RetryOnFailure', '')
+    expectations.IterateThroughResultsForUser(self.result_map, False)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ android ] some_test [ Failure ]
+[ win ] foo_test [ RetryOnFailure ]
+[ mac ] foo_test [ RetryOnFailure ]
+[ win ] bar_test [ RetryOnFailure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testIterateThroughResultsForUserRetryGroupByTags(self):
+    """Tests that everything appears to function with retry and grouping."""
+    self._input_mock.return_value = ('RetryOnFailure', 'crbug.com/1')
+    expectations.IterateThroughResultsForUser(self.result_map, True)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+crbug.com/1 [ win ] foo_test [ RetryOnFailure ]
+crbug.com/1 [ win ] bar_test [ RetryOnFailure ]
+[ mac ] some_test [ Failure ]
+crbug.com/1 [ mac ] foo_test [ RetryOnFailure ]
+[ android ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testIterateThroughResultsForUserFailNoGroupByTags(self):
+    """Tests that everything appears to function with failure and no group."""
+    self._input_mock.return_value = ('Failure', 'crbug.com/1')
+    expectations.IterateThroughResultsForUser(self.result_map, False)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ android ] some_test [ Failure ]
+crbug.com/1 [ win ] foo_test [ Failure ]
+crbug.com/1 [ mac ] foo_test [ Failure ]
+crbug.com/1 [ win ] bar_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testIterateThroughResultsForUserFailGroupByTags(self):
+    """Tests that everything appears to function with failure and grouping."""
+    self._input_mock.return_value = ('Failure', '')
+    expectations.IterateThroughResultsForUser(self.result_map, True)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ win ] foo_test [ Failure ]
+[ win ] bar_test [ Failure ]
+[ mac ] some_test [ Failure ]
+[ mac ] foo_test [ Failure ]
+[ android ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+
+@unittest.skipIf(sys.version_info[0] != 3, 'Python 3-only')
+class FindFailuresInSameConditionUnittest(unittest.TestCase):
+  def setUp(self):
+    self.result_map = {
+        'pixel_integration_test': {
+            'foo_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['a'],
+                },
+                'mac': {
+                    'typ_tags': ['mac'],
+                    'build_url_list': ['a', 'b'],
+                },
+            },
+            'bar_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['a', 'b', 'c'],
+                },
+                'mac': {
+                    'typ_tags': ['mac'],
+                    'build_url_list': ['a', 'b', 'c', 'd'],
+                },
+            },
+        },
+        'webgl_conformance_integration_test': {
+            'foo_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['a', 'b', 'c', 'd', 'e'],
+                },
+                'mac': {
+                    'typ_tags': ['mac'],
+                    'build_url_list': ['a', 'b', 'c', 'd', 'e', 'f'],
+                },
+            },
+            'bar_test': {
+                'win': {
+                    'typ_tags': ['win'],
+                    'build_url_list': ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
+                },
+                'mac': {
+                    'typ_tags': ['mac'],
+                    'build_url_list': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
+                },
+            },
+        },
+    }
+
+  def testFindFailuresInSameTest(self):
+    other_failures = expectations.FindFailuresInSameTest(
+        self.result_map, 'pixel_integration_test', 'foo_test', ['win'])
+    self.assertEqual(other_failures, [(['mac'], 2)])
+
+  def testFindFailuresInSameConfig(self):
+    other_failures = expectations.FindFailuresInSameConfig(
+        self.result_map, 'pixel_integration_test', 'foo_test', ['win'])
+    expected_other_failures = [
+        ('pixel_integration_test.bar_test', 3),
+        ('webgl_conformance_integration_test.foo_test', 5),
+        ('webgl_conformance_integration_test.bar_test', 7),
+    ]
+    self.assertEqual(len(other_failures), len(expected_other_failures))
+    self.assertEqual(set(other_failures), set(expected_other_failures))
+
+
+@unittest.skipIf(sys.version_info[0] != 3, 'Python 3-only')
+class ModifyFileForResultUnittest(fake_filesystem_unittest.TestCase):
+  def setUp(self):
+    self.setUpPyfakefs()
+    self.expectation_file = os.path.join(
+        expectations.EXPECTATION_FILE_DIRECTORY, 'expectation.txt')
+    uu.CreateFile(self, self.expectation_file)
+    self._expectation_file_patcher = mock.patch.object(
+        expectations, 'GetExpectationFileForSuite')
+    self._expectation_file_mock = self._expectation_file_patcher.start()
+    self.addCleanup(self._expectation_file_patcher.stop)
+    self._expectation_file_mock.return_value = self.expectation_file
+
+  def testNoGroupByTags(self):
+    """Tests that not grouping by tags appends to the end."""
+    expectation_file_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+
+[ mac ] some_test [ Failure ]
+"""
+    with open(self.expectation_file, 'w') as outfile:
+      outfile.write(expectation_file_contents)
+    expectations.ModifyFileForResult(None, 'some_test', ['win', 'win10'], '',
+                                     'Failure', False)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+
+[ mac ] some_test [ Failure ]
+[ win win10 ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testGroupByTagsNoMatch(self):
+    """Tests that grouping by tags but finding no match appends to the end."""
+    expectation_file_contents = validate_tag_consistency.TAG_HEADER + """\
+[ mac ] some_test [ Failure ]
+"""
+    with open(self.expectation_file, 'w') as outfile:
+      outfile.write(expectation_file_contents)
+    expectations.ModifyFileForResult(None, 'some_test', ['win', 'win10'], '',
+                                     'Failure', True)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ mac ] some_test [ Failure ]
+[ win win10 ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+  def testGroupByTagsMatch(self):
+    """Tests that grouping by tags and finding a match adds mid-file."""
+    expectation_file_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+
+[ mac ] some_test [ Failure ]
+"""
+    with open(self.expectation_file, 'w') as outfile:
+      outfile.write(expectation_file_contents)
+    expectations.ModifyFileForResult(None, 'foo_test', ['win', 'win10'], '',
+                                     'Failure', True)
+    expected_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+[ win ] foo_test [ Failure ]
+
+[ mac ] some_test [ Failure ]
+"""
+    with open(self.expectation_file) as infile:
+      self.assertEqual(infile.read(), expected_contents)
+
+
+@unittest.skipIf(sys.version_info[0] != 3, 'Python 3-only')
+class GetExpectationFileForSuiteUnittest(unittest.TestCase):
+  def testRegularExpectationFile(self):
+    """Tests that a regular expectation file is found properly."""
+    expected_filepath = os.path.join(expectations.EXPECTATION_FILE_DIRECTORY,
+                                     'pixel_expectations.txt')
+    actual_filepath = expectations.GetExpectationFileForSuite(
+        'pixel_integration_test', ['webgl-version-2'])
+    self.assertEqual(actual_filepath, expected_filepath)
+
+  def testOverrideExpectationFile(self):
+    """Tests that an overridden expectation file is found properly."""
+    expected_filepath = os.path.join(expectations.EXPECTATION_FILE_DIRECTORY,
+                                     'info_collection_expectations.txt')
+    actual_filepath = expectations.GetExpectationFileForSuite(
+        'info_collection_test', ['webgl-version-2'])
+    self.assertEqual(actual_filepath, expected_filepath)
+
+  def testWebGl1Conformance(self):
+    """Tests that a WebGL 1 expectation file is found properly."""
+    expected_filepath = os.path.join(expectations.EXPECTATION_FILE_DIRECTORY,
+                                     'webgl_conformance_expectations.txt')
+    actual_filepath = expectations.GetExpectationFileForSuite(
+        'webgl_conformance_integration_test', [])
+    self.assertEqual(actual_filepath, expected_filepath)
+
+  def testWebGl2Conformance(self):
+    """Tests that a WebGL 2 expectation file is found properly."""
+    expected_filepath = os.path.join(expectations.EXPECTATION_FILE_DIRECTORY,
+                                     'webgl2_conformance_expectations.txt')
+    actual_filepath = expectations.GetExpectationFileForSuite(
+        'webgl_conformance_integration_test', ['webgl-version-2'])
+    self.assertEqual(actual_filepath, expected_filepath)
+
+
+@unittest.skipIf(sys.version_info[0] != 3, 'Python 3-only')
+class FindBestInsertionLineForExpectationUnittest(
+    fake_filesystem_unittest.TestCase):
+  def setUp(self):
+    self.setUpPyfakefs()
+    self.expectation_file = os.path.join(
+        expectations.EXPECTATION_FILE_DIRECTORY, 'expectation.txt')
+    uu.CreateFile(self, self.expectation_file)
+    expectation_file_contents = validate_tag_consistency.TAG_HEADER + """\
+[ win ] some_test [ Failure ]
+
+[ mac ] some_test [ Failure ]
+
+[ win release ] bar_test [ Failure ]
+[ win ] foo_test [ Failure ]
+
+[ chromeos ] some_test [ Failure ]
+"""
+    with open(self.expectation_file, 'w') as outfile:
+      outfile.write(expectation_file_contents)
+
+  def testNoMatchingTags(self):
+    """Tests behavior when there are no expectations with matching tags."""
+    insertion_line, tags = expectations.FindBestInsertionLineForExpectation(
+        ['android'], self.expectation_file)
+    self.assertEqual(insertion_line, -1)
+    self.assertEqual(tags, set())
+
+  def testMatchingTagsLastEntryChosen(self):
+    """Tests that the last matching line is chosen."""
+    insertion_line, tags = expectations.FindBestInsertionLineForExpectation(
+        ['win'], self.expectation_file)
+    # We expect "[ win ] foo_test [ Failure ]" to be chosen
+    expected_line = len(validate_tag_consistency.TAG_HEADER.splitlines()) + 6
+    self.assertEqual(insertion_line, expected_line)
+    self.assertEqual(tags, set(['win']))
+
+  def testMatchingTagsClosestMatchChosen(self):
+    """Tests that the closest tag match is chosen."""
+    insertion_line, tags = expectations.FindBestInsertionLineForExpectation(
+        ['win', 'release'], self.expectation_file)
+    # We expect "[ win release ] bar_test [ Failure ]" to be chosen
+    expected_line = len(validate_tag_consistency.TAG_HEADER.splitlines()) + 5
+    self.assertEqual(insertion_line, expected_line)
+    self.assertEqual(tags, set(['win', 'release']))
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/content/test/gpu/flake_suppressor/queries.py b/content/test/gpu/flake_suppressor/queries.py
new file mode 100644
index 0000000..8f95aec
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/queries.py
@@ -0,0 +1,77 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Module for querying BigQuery."""
+
+import json
+import os
+import subprocess
+
+MAX_ROWS = (2**31) - 1
+
+# Gets all failures from the past X days that did not already have an associated
+# test suppression when the test ran.
+# TODO(crbug.com/1192733): Update the query to also omit results for a test if
+# a suppression was added sometime between the failure and now.
+# TODO(crbug.com/1192733): Look into updating this to also check try results
+# once crbug.com/1217300 is complete.
+QUERY = """\
+WITH
+  failed_tests AS (
+    SELECT
+      exported.id,
+      status,
+      test_metadata.name,
+      ARRAY(
+        SELECT value
+        FROM tr.tags
+        WHERE key = "typ_tag") as typ_tags,
+      ARRAY(
+        SELECT value
+        FROM tr.tags
+        WHERE key = "raw_typ_expectation") as typ_expectations
+    FROM `luci-resultdb.chromium.gpu_ci_test_results` tr
+    WHERE
+      status = "FAIL"
+      AND exported.realm = "chromium:ci"
+      AND partition_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(),
+                                         INTERVAL @sample_period DAY)
+  )
+SELECT *
+FROM failed_tests ft
+WHERE
+  ARRAY_TO_STRING(ft.typ_expectations, '') = "Pass"
+"""
+
+
+def GetFlakyOrFailingTests(sample_period, billing_project):
+  """Gets all flaky or failing GPU tests in the given |sample_period|.
+
+  Args:
+    sample_period: An int containing the number of days in the past from the
+        current time to pull results from.
+    billing_project: A string containing the billing project to use for
+        BigQuery queries.
+
+  Returns:
+    A JSON representation of the BigQuery results containing all found flaky or
+    failing test results.
+  """
+  cmd = [
+      'bq',
+      'query',
+      '--max_rows=%d' % MAX_ROWS,
+      '--format=json',
+      '--project_id=%s' % billing_project,
+      '--use_legacy_sql=false',
+      '--parameter=sample_period:INT64:%d' % sample_period,
+      QUERY,
+  ]
+
+  with open(os.devnull, 'w') as devnull:
+    completed_process = subprocess.run(cmd,
+                                       stdout=subprocess.PIPE,
+                                       stderr=devnull,
+                                       check=True,
+                                       text=True)
+  return json.loads(completed_process.stdout)
diff --git a/content/test/gpu/flake_suppressor/result_output.py b/content/test/gpu/flake_suppressor/result_output.py
new file mode 100644
index 0000000..fbf6137e
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/result_output.py
@@ -0,0 +1,118 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Module for outputting results in a human-readable format."""
+
+import tempfile
+
+
+def GenerateHtmlOutputFile(aggregated_results, outfile=None):
+  """Generates an HTML results file.
+
+  Args:
+    aggregated_results: A map containing the aggregated test results.
+    outfile: A file-like object to output to. Will create one if not provided.
+  """
+  outfile = outfile or tempfile.NamedTemporaryFile(
+      mode='w', delete=False, suffix='.html')
+  try:
+    outfile.write('<html>\n<body>\n')
+    string_map = _ConvertAggregatedResultsToStringMap(aggregated_results)
+    _OutputMapToHtmlFile(string_map, 'Grouped By Test', outfile)
+    config_map = _ConvertFromTestGroupingToConfigGrouping(string_map)
+    _OutputMapToHtmlFile(config_map, 'Grouped By Config', outfile)
+    outfile.write('</body>\n</html>\n')
+  finally:
+    outfile.close()
+  print('HTML results: %s' % outfile.name)
+
+
+def _OutputMapToHtmlFile(string_map, result_header, output_file):
+  """Outputs a map to a file as a nested list.
+
+  Args:
+    string_map: The string map to output.
+    result_header: A string containing the header contents placed before the
+        nested list.
+    output_file: A file-like object to output the map to.
+  """
+  output_file.write('<h1>%s</h1>\n' % result_header)
+  output_file.write('<ul>\n')
+  _RecursiveHtmlToFile(string_map, output_file)
+  output_file.write('</ul>\n')
+
+
+def _RecursiveHtmlToFile(node, output_file):
+  """Recursively outputs a string map to an output file as HTML.
+
+  Specifically, contents are output as an unordered list (<ul>).
+
+  Args:
+    node: The current node to output. Must be either a dict or list.
+    output_file: A file-like object to output the HTML to.
+  """
+  if isinstance(node, dict):
+    for key, value in node.items():
+      output_file.write('<li>%s</li>\n' % key)
+      output_file.write('<ul>\n')
+      _RecursiveHtmlToFile(value, output_file)
+      output_file.write('</ul>\n')
+  elif isinstance(node, list):
+    for element in node:
+      output_file.write('<li><a href="%s">%s</a></li>\n' % (element, element))
+  else:
+    raise RuntimeError('Unsupported type %s' % type(node).__name__)
+
+
+def _ConvertAggregatedResultsToStringMap(aggregated_results):
+  """Converts aggregated results to a format usable by _RecursiveHtmlToFile.
+
+  Specifically, updates the string representation of the typ tags and replaces
+  the lowest level dict with the build URL list.
+
+  Args:
+    aggregated_results: A map containing the aggregated test results.
+
+  Returns:
+    A map in the format:
+    {
+      'suite': {
+        'test': {
+          'space separated typ tags': ['build', 'url', 'list']
+        }
+      }
+    }
+  """
+  string_map = {}
+  for suite, test_map in aggregated_results.items():
+    for test, tag_map in test_map.items():
+      for _, unique_result in tag_map.items():
+        str_typ_tags = ' '.join(unique_result['typ_tags'])
+        string_map.setdefault(suite, {}).setdefault(
+            test, {})[str_typ_tags] = unique_result['build_url_list']
+  return string_map
+
+
+def _ConvertFromTestGroupingToConfigGrouping(string_map):
+  """Converts |string| map to be grouped by typ tags/configuration.
+
+  Args:
+    string_map: The output of _ConvertAggregatedResultsToStringMap.
+
+  Returns:
+    A map in the format:
+    {
+      'space separated typ tags': {
+        'suite': {
+          'test': ['build', 'url', 'list']
+        }
+      }
+    }
+  """
+  converted_map = {}
+  for suite, test_map in string_map.items():
+    for test, tag_map in test_map.items():
+      for typ_tags, build_urls in tag_map.items():
+        converted_map.setdefault(typ_tags, {}).setdefault(suite,
+                                                          {})[test] = build_urls
+  return converted_map
diff --git a/content/test/gpu/flake_suppressor/result_output_unittest.py b/content/test/gpu/flake_suppressor/result_output_unittest.py
new file mode 100755
index 0000000..4c4864b
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/result_output_unittest.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import tempfile
+import unittest
+
+from pyfakefs import fake_filesystem_unittest
+
+from flake_suppressor import result_output
+
+
+class GenerateHtmlOutputFileUntitest(fake_filesystem_unittest.TestCase):
+  def setUp(self):
+    self.setUpPyfakefs()
+    self.output_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
+    self.output_file_name = self.output_file.name
+
+  def testBasic(self):
+    """Basic functionality test."""
+    result_map = {
+        'some_suite': {
+            'some_test': {
+                'some_tags': {
+                    'typ_tags': ['some', 'tags'],
+                    'build_url_list': ['url1', 'url2'],
+                },
+            },
+        },
+    }
+    result_output.GenerateHtmlOutputFile(result_map, self.output_file)
+    expected_output = """\
+<html>
+<body>
+<h1>Grouped By Test</h1>
+<ul>
+<li>some_suite</li>
+<ul>
+<li>some_test</li>
+<ul>
+<li>some tags</li>
+<ul>
+<li><a href="url1">url1</a></li>
+<li><a href="url2">url2</a></li>
+</ul>
+</ul>
+</ul>
+</ul>
+<h1>Grouped By Config</h1>
+<ul>
+<li>some tags</li>
+<ul>
+<li>some_suite</li>
+<ul>
+<li>some_test</li>
+<ul>
+<li><a href="url1">url1</a></li>
+<li><a href="url2">url2</a></li>
+</ul>
+</ul>
+</ul>
+</ul>
+</body>
+</html>
+"""
+    with open(self.output_file_name) as infile:
+      self.assertEqual(infile.read(), expected_output)
+
+
+class RecursiveHtmlToFileUnittest(fake_filesystem_unittest.TestCase):
+  def setUp(self):
+    self.setUpPyfakefs()
+    self.output_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
+    self.output_file_name = self.output_file.name
+
+  def testBasic(self):
+    """Basic functionality test."""
+    string_map = {
+        'some_suite': {
+            'some_test': {
+                'some tags': ['url1', 'url2'],
+            },
+        },
+    }
+    result_output._RecursiveHtmlToFile(string_map, self.output_file)
+    self.output_file.close()
+    expected_output = """\
+<li>some_suite</li>
+<ul>
+<li>some_test</li>
+<ul>
+<li>some tags</li>
+<ul>
+<li><a href="url1">url1</a></li>
+<li><a href="url2">url2</a></li>
+</ul>
+</ul>
+</ul>
+"""
+    with open(self.output_file_name) as infile:
+      self.assertEqual(infile.read(), expected_output)
+
+  def testUnsupportedType(self):
+    """Tests that providing an unsupported data type fails."""
+    with self.assertRaises(RuntimeError):
+      result_output._RecursiveHtmlToFile('a', self.output_file)
+
+
+class ConvertAggregatedResultsToStringMapUnittest(unittest.TestCase):
+  def testBasic(self):
+    """Basic functionality test."""
+    result_map = {
+        'some_suite': {
+            'some_test': {
+                'some_tags': {
+                    'typ_tags': ['some', 'tags'],
+                    'build_url_list': ['url1', 'url2'],
+                },
+            },
+        },
+    }
+    expected_map = {
+        'some_suite': {
+            'some_test': {
+                'some tags': ['url1', 'url2'],
+            },
+        },
+    }
+    self.assertEqual(
+        result_output._ConvertAggregatedResultsToStringMap(result_map),
+        expected_map)
+
+
+class ConvertFromTestGroupingToConfigGroupingUnittest(unittest.TestCase):
+  def testBasic(self):
+    """Basic functionality test."""
+    string_map = {
+        'some_suite': {
+            'some_test': {
+                'some tags': ['url1', 'url2'],
+            },
+        },
+    }
+    config_map = result_output._ConvertFromTestGroupingToConfigGrouping(
+        string_map)
+    expected_config_map = {
+        'some tags': {
+            'some_suite': {
+                'some_test': ['url1', 'url2'],
+            },
+        },
+    }
+    self.assertEqual(config_map, expected_config_map)
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/content/test/gpu/flake_suppressor/results.py b/content/test/gpu/flake_suppressor/results.py
new file mode 100644
index 0000000..4982f45
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/results.py
@@ -0,0 +1,40 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Module for working with BigQuery results."""
+
+
+def AggregateResults(results):
+  """Aggregates BigQuery results.
+
+  Args:
+    results: Parsed JSON results from a BigQuery query.
+
+  Returns:
+    A map in the following format:
+    {
+      'test_suite': {
+        'test_name': {
+          'typ_tags_as_string': {
+            'typ_tags': [ 'list', 'of', 'tags ],
+            'build_url_list': [ 'list', 'of', 'urls' ],
+          },
+        },
+      },
+    }
+  """
+  aggregated_results = {}
+  for r in results:
+    _, suite, __, test_name = r['name'].split('.', 3)
+    build_id = r['id'].split('-')[-1]
+    build_url = 'http://ci.chromium.org/b/%s' % build_id
+    typ_tags = r['typ_tags']
+    typ_tags.sort()
+    typ_tags_str = '__'.join(typ_tags)
+
+    unique_test = aggregated_results.setdefault(suite, {}).setdefault(
+        test_name, {}).setdefault(typ_tags_str, {})
+    build_url_list = unique_test.setdefault('build_url_list', [])
+    build_url_list.append(build_url)
+    unique_test.setdefault('typ_tags', typ_tags)
+  return aggregated_results
diff --git a/content/test/gpu/flake_suppressor/results_unittest.py b/content/test/gpu/flake_suppressor/results_unittest.py
new file mode 100755
index 0000000..2e319e40
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/results_unittest.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from flake_suppressor import results
+
+
+class AggregateResultsUnittest(unittest.TestCase):
+  def testBasic(self):
+    """Basic functionality test."""
+    query_results = [
+        {
+            'name': ('gpu_tests.webgl_conformance_integration_test.'
+                     'WebGLConformanceIntegrationTest.'
+                     'conformance/textures/misc/video-rotation.html'),
+            'id':
+            'build-1111',
+            'typ_tags': ['win', 'nvidia'],
+        },
+        {
+            'name': ('gpu_tests.webgl_conformance_integration_test.'
+                     'WebGLConformanceIntegrationTest.'
+                     'conformance/textures/misc/video-rotation.html'),
+            'id':
+            'build-2222',
+            'typ_tags': ['win', 'nvidia'],
+        },
+        {
+            'name': ('gpu_tests.webgl_conformance_integration_test.'
+                     'WebGLConformanceIntegrationTest.'
+                     'conformance/textures/misc/video-rotation.html'),
+            'id':
+            'build-3333',
+            'typ_tags': ['win', 'amd'],
+        },
+        {
+            'name': ('gpu_tests.webgl_conformance_integration_test.'
+                     'WebGLConformanceIntegrationTest.'
+                     'conformance/textures/misc/texture-npot-video.html'),
+            'id':
+            'build-4444',
+            'typ_tags': ['win', 'nvidia'],
+        },
+        {
+            'name': ('gpu_tests.pixel_integration_test.PixelIntegrationTest.'
+                     'Pixel_CSS3DBlueBox'),
+            'id':
+            'build-5555',
+            'typ_tags': ['win', 'nvidia'],
+        },
+    ]
+    expected_output = {
+        'webgl_conformance_integration_test': {
+            'conformance/textures/misc/video-rotation.html': {
+                'nvidia__win': {
+                    'typ_tags': ['nvidia', 'win'],
+                    'build_url_list': [
+                        'http://ci.chromium.org/b/1111',
+                        'http://ci.chromium.org/b/2222',
+                    ],
+                },
+                'amd__win': {
+                    'typ_tags': ['amd', 'win'],
+                    'build_url_list': ['http://ci.chromium.org/b/3333'],
+                },
+            },
+            'conformance/textures/misc/texture-npot-video.html': {
+                'nvidia__win': {
+                    'typ_tags': ['nvidia', 'win'],
+                    'build_url_list': ['http://ci.chromium.org/b/4444'],
+                },
+            },
+        },
+        'pixel_integration_test': {
+            'Pixel_CSS3DBlueBox': {
+                'nvidia__win': {
+                    'typ_tags': ['nvidia', 'win'],
+                    'build_url_list': ['http://ci.chromium.org/b/5555'],
+                },
+            },
+        },
+    }
+    self.assertEqual(results.AggregateResults(query_results), expected_output)
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/content/test/gpu/flake_suppressor/unittest_utils.py b/content/test/gpu/flake_suppressor/unittest_utils.py
new file mode 100644
index 0000000..32309ddaa
--- /dev/null
+++ b/content/test/gpu/flake_suppressor/unittest_utils.py
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def CreateFile(test, *args, **kwargs):
+  # TODO(crbug.com/1156806): Remove this and just use fs.create_file() when
+  # Catapult is updated to a newer version of pyfakefs that is compatible with
+  # Chromium's version.
+  if hasattr(test.fs, 'create_file'):
+    test.fs.create_file(*args, **kwargs)
+  else:
+    test.fs.CreateFile(*args, **kwargs)
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index 03f604d..184b96a3 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -139,3 +139,7 @@
 
 # Flaky for LaCrOS
 crbug.com/1205899 [ linux display-server-wayland ] ContextLost_WebGLBlockedAfterJSNavigation [ RetryOnFailure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
index 5af2f88..59549b4 100644
--- a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
@@ -63,3 +63,7 @@
 crbug.com/1080375 [ chromeos chromeos-board-kevin ] DepthCapture_depthStreamToRGBAFloatTexture [ Failure ]
 crbug.com/1159394 [ chromeos chromeos-board-kevin ] DepthCapture_depthStreamToR32FloatTexture [ Failure ]
 crbug.com/1159394 [ chromeos chromeos-board-kevin ] DepthCapture_depthStreamToRGBAUint8Texture [ Failure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
index 625f03b..39245d19 100644
--- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -92,3 +92,7 @@
 
 # Flakily hits a DCHECK during shared image creation.
 crbug.com/1188437 [ linux intel display-server-wayland ] GpuProcess_webgl [ RetryOnFailure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
index 2dc6367..ba7aeee 100644
--- a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
@@ -58,3 +58,7 @@
 # results: [ Failure RetryOnFailure Skip ]
 # END TAG HEADER
 
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
index ecd901f..d7c5dd6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -66,3 +66,7 @@
 
 # InfoCollection_basic is flaky on Fuchsia.
 crbug.com/1154597 [ fuchsia ] InfoCollection_basic [ RetryOnFailure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
index 2dc6367..918820a 100644
--- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -58,3 +58,6 @@
 # results: [ Failure RetryOnFailure Skip ]
 # END TAG HEADER
 
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index b93d7e87..3eb1070 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -415,3 +415,7 @@
 
 # Flaky on Android, haven't investigated why yet.
 crbug.com/1221258 [ android ] Pixel_OffscreenCanvas2DResizeOnWorker [ Failure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
index f27c4e3..883b823e 100644
--- a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
@@ -77,3 +77,6 @@
 crbug.com/941163 [ win10 intel-0x3e92 ] Video_720_MP4_Fullscreen [ RetryOnFailure ]
 crbug.com/941163 [ win10 intel-0x3e92 ] Video_720_MP4_Underlay_Fullscreen [ RetryOnFailure ]
 
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
index 8b00426..ce64709 100644
--- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -60,3 +60,7 @@
 
 crbug.com/1166379 [ android android-pixel-4 ] ScreenshotSync_GPURasterWithDivs [ RetryOnFailure ]
 crbug.com/1166379 [ android android-pixel-4 ] ScreenshotSync_SWRasterWithDivs [ RetryOnFailure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index 5a9cc145f..e4fa3e19 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -175,3 +175,7 @@
 crbug.com/852089 [ chromeos ] TraceTest_WebGPU* [ Skip ]
 crbug.com/852089 [ fuchsia ] TraceTest_WebGPU* [ Skip ]
 crbug.com/852089 [ win7 ] TraceTest_WebGPU* [ Skip ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
index b2ebab5..b795020 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -62,3 +62,6 @@
 
 crbug.com/1207682 [ android ] WebCodecs_* [ RetryOnFailure ]
 
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 8fb50ac..cb59ce6 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -423,6 +423,25 @@
 
 crbug.com/642822 [ mac amd ] conformance2/rendering/clipping-wide-points.html [ Failure ]
 
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/image_bitmap_from_video/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/video/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] conformance2/textures/webgl_canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-disabled no-passthrough skia-renderer-gl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ]
 
 # Mac Intel
 crbug.com/886970 [ mac intel-0xa2e ] conformance/rendering/canvas-alpha-bug.html [ Failure ]
@@ -476,6 +495,13 @@
 crbug.com/982294 [ mac passthrough amd ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ]
 crbug.com/982294 [ mac passthrough amd ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ]
 
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ]
+crbug.com/1227762 [ bigsur amd-0x6821 angle-opengl passthrough ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ]
+
 # Mac Passthrough / NVIDIA
 crbug.com/982294 [ mac passthrough nvidia ] conformance/renderbuffers/framebuffer-object-attachment.html [ Failure ]
 crbug.com/982294 [ mac passthrough nvidia ] conformance/textures/misc/tex-input-validation.html [ Failure ]
@@ -585,7 +611,6 @@
 crbug.com/1141066 [ mac apple-apple-m1 angle-opengl passthrough ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ]
 crbug.com/1141066 [ mac apple-apple-m1 angle-opengl passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ]
 
-
 ####################
 # Linux failures   #
 ####################
@@ -772,3 +797,7 @@
 # Conflicts if between a generic os condition and a specific version
 #[ sierra nvidia debug angle-opengl ] WebglExtension_test_10 [ Failure ]
 #[ mac nvidia debug angle-opengl ] WebglExtension_test_10 [ Failure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 4cc7dc5..cb80a2b 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -487,6 +487,9 @@
 crbug.com/angleproject/5505 [ mac angle-metal passthrough ] conformance/ogles/GL/asin/asin_001_to_006.html [ Failure ]
 crbug.com/1227129 [ mac angle-metal passthrough ] conformance/glsl/misc/ternary-operators-in-initializers.html [ Failure ]
 
+# Mac / Passthrough command decoder / Metal / AMD
+crbug.com/1227767 [ bigsur amd-0x6821 angle-metal passthrough ] conformance/ogles/GL/discard/discard_001_to_002.html [ Failure ]
+
 # Mac / Passthrough command decoder / Metal / Intel
 crbug.com/1144258 [ mac angle-metal passthrough intel-0x3e9b ] conformance/glsl/functions/glsl-function-atan-xy.html [ Failure ]
 crbug.com/angleproject/4846 [ mac angle-metal passthrough intel ] conformance/limits/gl-max-texture-dimensions.html [ Failure ]
@@ -857,3 +860,7 @@
 crbug.com/1134756 [ mac angle-swiftshader passthrough ] conformance/misc/uninitialized-test.html [ Failure ]
 crbug.com/1134756 [ mac angle-swiftshader passthrough ] conformance/textures/misc/copy-tex-image-and-sub-image-2d.html [ Failure ]
 crbug.com/1190853 [ mac angle-swiftshader passthrough ] conformance/textures/misc/video-rotation.html [ Failure ]
+
+#######################################################################
+# Automated Entries After This Point - Do Not Manually Add Below Here #
+#######################################################################
diff --git a/content/test/gpu/suppress_flakes.py b/content/test/gpu/suppress_flakes.py
new file mode 100755
index 0000000..062c395b
--- /dev/null
+++ b/content/test/gpu/suppress_flakes.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env vpython3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Script for finding and suppressing flaky GPU tests.
+
+This relies on ResultDB BigQuery data under the hood, so it requires the `bq`
+tool which is available as part of the Google Cloud SDK
+https://cloud.google.com/sdk/docs/quickstarts.
+
+Example usage, which finds all failures in the past 5 days. Any tests that
+failed more than twice on a configuration is marked as flaky, and any that
+failed more than 5 times is marked as failing:
+
+suppress_flakes.py \
+  --project chrome-unexpected-pass-data \
+  --sample-period 5
+"""
+
+import argparse
+
+from flake_suppressor import expectations
+from flake_suppressor import queries
+from flake_suppressor import result_output
+from flake_suppressor import results as results_module
+
+
+def ParseArgs():
+  # TODO(crbug.com/1192733): Add flaky and failure thresholds, likely in the
+  # form of % of failures out of the total runs for a (test, tags) combination.
+  # <1% can be ignored, > 50% can be treated as a failure instead of a flake.
+  parser = argparse.ArgumentParser(
+      description=('Script for automatically suppressing flaky/failing GPU '
+                   'Telemetry-based tests.'))
+  parser.add_argument('--project',
+                      required=True,
+                      help=('The billing project to use for BigQuery queries. '
+                            'Must have access to the ResultDB BQ tables, e.g. '
+                            '"luci-resultdb.chromium.gpu_ci_test_results".'))
+  parser.add_argument('--sample-period',
+                      type=int,
+                      default=1,
+                      help=('The number of days to sample data from.'))
+  parser.add_argument('--no-group-by-tags',
+                      action='store_false',
+                      default=True,
+                      dest='group_by_tags',
+                      help=('Append added expectations to the end of the file '
+                            'instead of attempting to automatically group with '
+                            'similar expectations.'))
+  args = parser.parse_args()
+
+  return args
+
+
+def main():
+  args = ParseArgs()
+  results = queries.GetFlakyOrFailingTests(args.sample_period, args.project)
+  aggregated_results = results_module.AggregateResults(results)
+  result_output.GenerateHtmlOutputFile(aggregated_results)
+  print('If there are many instances of failed tests, that may be indicative '
+        'of an issue that should be handled in some other way, e.g. reverting '
+        'a bad CL.')
+  input('\nBeginning of user input section - press any key to continue')
+  expectations.IterateThroughResultsForUser(aggregated_results,
+                                            args.group_by_tags)
+  print('\nGenerated expectations likely contain conflicting tags that need to '
+        'be removed.')
+
+
+if __name__ == '__main__':
+  main()
diff --git a/content/test/gpu/unexpected_passes/gpu_builders.py b/content/test/gpu/unexpected_passes/gpu_builders.py
index bcfa552..89d3c23 100644
--- a/content/test/gpu/unexpected_passes/gpu_builders.py
+++ b/content/test/gpu/unexpected_passes/gpu_builders.py
@@ -5,12 +5,24 @@
 
 from __future__ import print_function
 
+import os
+import sys
+
 from unexpected_passes_common import builders
 
+CHROMIUM_SRC_DIR = os.path.realpath(
+    os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
+TOOLS_PERF_DIR = os.path.join(CHROMIUM_SRC_DIR, 'tools', 'perf')
+
+sys.path.append(TOOLS_PERF_DIR)
+from chrome_telemetry_build import android_browser_types as abt
+sys.path.remove(TOOLS_PERF_DIR)
+
 
 class GpuBuilders(builders.Builders):
   def __init__(self):
     super(GpuBuilders, self).__init__()
+    self._isolate_names = None
     self._fake_ci_builders = None
 
   def _BuilderRunsTestOfInterest(self, test_map, suite):
@@ -23,10 +35,16 @@
     return False
 
   def GetIsolateNames(self):
-    return {
-        'fuchsia_telemetry_gpu_integration_test',
-        'telemetry_gpu_integration_test',
-    }
+    if self._isolate_names is None:
+      self._isolate_names = {
+          'fuchsia_telemetry_gpu_integration_test',
+          'telemetry_gpu_integration_test',
+      }
+      # Android targets are split based on binary type, so add those using the
+      # maintained list of suffixes.
+      for suffix in abt.TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES:
+        self._isolate_names.add('telemetry_gpu_integration_test' + suffix)
+    return self._isolate_names
 
   def GetFakeCiBuilders(self):
     if self._fake_ci_builders is None:
diff --git a/content/test/gpu/unexpected_passes/gpu_builders_unittest.py b/content/test/gpu/unexpected_passes/gpu_builders_unittest.py
index 4d86a225..1b81ba7 100755
--- a/content/test/gpu/unexpected_passes/gpu_builders_unittest.py
+++ b/content/test/gpu/unexpected_passes/gpu_builders_unittest.py
@@ -58,3 +58,11 @@
     }
     self.assertFalse(
         self.instance._BuilderRunsTestOfInterest(test_map, 'webgl_conformance'))
+
+  def testAndroidSuffixes(self):
+    """Tests that Android-specific isolates are added."""
+    isolate_names = self.instance.GetIsolateNames()
+    for isolate in isolate_names:
+      if 'telemetry_gpu_integration_test' in isolate and 'android' in isolate:
+        return
+    self.fail('Did not find any Android-specific isolate names')
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc
index 8f3760f..60ebbac 100644
--- a/content/web_test/browser/web_test_content_browser_client.cc
+++ b/content/web_test/browser/web_test_content_browser_client.cc
@@ -13,6 +13,7 @@
 
 #include "base/bind.h"
 #include "base/cxx17_backports.h"
+#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/pattern.h"
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index b81b863c..43925ec 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -133,10 +133,6 @@
   }
 
   defines = [ "CRYPTO_IMPLEMENTATION" ]
-
-  if (is_nacl) {
-    deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
-  }
 }
 
 test("crypto_unittests") {
diff --git a/device/bluetooth/bluez/bluetooth_device_bluez.cc b/device/bluetooth/bluez/bluetooth_device_bluez.cc
index b21ccd8a..9318d1b2 100644
--- a/device/bluetooth/bluez/bluetooth_device_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_device_bluez.cc
@@ -293,6 +293,13 @@
 }
 #endif
 
+std::string BluetoothDeviceBlueZ::GetIdentifier() const {
+  // The D-Bus object path is the original Bluetooth device address. If the
+  // device uses a resolvable address that rotates over time, BlueZ will resolve
+  // it back to its original address used for the D-Bus object path.
+  return object_path_.value();
+}
+
 std::string BluetoothDeviceBlueZ::GetAddress() const {
   bluez::BluetoothDeviceClient::Properties* properties =
       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
diff --git a/device/bluetooth/bluez/bluetooth_device_bluez.h b/device/bluetooth/bluez/bluetooth_device_bluez.h
index 30776c4..529a5a8 100644
--- a/device/bluetooth/bluez/bluetooth_device_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_device_bluez.h
@@ -55,6 +55,7 @@
   // BluetoothDevice override
   uint32_t GetBluetoothClass() const override;
   device::BluetoothTransport GetType() const override;
+  std::string GetIdentifier() const override;
   std::string GetAddress() const override;
   AddressType GetAddressType() const override;
   VendorIDSource GetVendorIDSource() const override;
diff --git a/device/fido/auth_token_requester.cc b/device/fido/auth_token_requester.cc
index 8ca8309..66f2310e 100644
--- a/device/fido/auth_token_requester.cc
+++ b/device/fido/auth_token_requester.cc
@@ -171,7 +171,9 @@
     return;
   }
 
-  NotifyAuthenticatorSelected();
+  if (!NotifyAuthenticatorSelected()) {
+    return;
+  }
 
   if (status == CtapDeviceResponseCode::kCtap2ErrOperationDenied) {
     // The user explicitly denied to the operation on an authenticator with
@@ -213,9 +215,10 @@
 }
 
 void AuthTokenRequester::ObtainTokenFromPIN() {
-  NotifyAuthenticatorSelected();
-  authenticator_->GetPinRetries(base::BindOnce(
-      &AuthTokenRequester::OnGetPINRetries, weak_factory_.GetWeakPtr()));
+  if (NotifyAuthenticatorSelected()) {
+    authenticator_->GetPinRetries(base::BindOnce(
+        &AuthTokenRequester::OnGetPINRetries, weak_factory_.GetWeakPtr()));
+  }
 }
 
 void AuthTokenRequester::OnGetPINRetries(
@@ -313,12 +316,14 @@
 }
 
 void AuthTokenRequester::ObtainTokenFromNewPIN() {
-  NotifyAuthenticatorSelected();
-  delegate_->CollectPIN(pin::PINEntryReason::kSet, pin::PINEntryError::kNoError,
-                        authenticator_->NewMinPINLength(),
-                        /*attempts=*/0,
-                        base::BindOnce(&AuthTokenRequester::HaveNewPIN,
-                                       weak_factory_.GetWeakPtr()));
+  if (NotifyAuthenticatorSelected()) {
+    delegate_->CollectPIN(pin::PINEntryReason::kSet,
+                          pin::PINEntryError::kNoError,
+                          authenticator_->NewMinPINLength(),
+                          /*attempts=*/0,
+                          base::BindOnce(&AuthTokenRequester::HaveNewPIN,
+                                         weak_factory_.GetWeakPtr()));
+  }
 }
 
 void AuthTokenRequester::HaveNewPIN(std::u16string pin16) {
@@ -366,19 +371,20 @@
                                              weak_factory_.GetWeakPtr(), pin));
 }
 
-void AuthTokenRequester::NotifyAuthenticatorSelected() {
-  if (authenticator_was_selected_) {
-    return;
+bool AuthTokenRequester::NotifyAuthenticatorSelected() {
+  if (!authenticator_selected_result_.has_value()) {
+    authenticator_selected_result_ =
+        delegate_->AuthenticatorSelectedForPINUVAuthToken(authenticator_);
   }
-  authenticator_was_selected_ = true;
-  delegate_->AuthenticatorSelectedForPINUVAuthToken(authenticator_);
+  return *authenticator_selected_result_;
 }
 
 void AuthTokenRequester::NotifyAuthenticatorSelectedAndFailWithResult(
     Result result) {
-  NotifyAuthenticatorSelected();
-  delegate_->HavePINUVAuthTokenResultForAuthenticator(authenticator_, result,
-                                                      absl::nullopt);
+  if (NotifyAuthenticatorSelected()) {
+    delegate_->HavePINUVAuthTokenResultForAuthenticator(authenticator_, result,
+                                                        absl::nullopt);
+  }
 }
 
 }  // namespace device
diff --git a/device/fido/auth_token_requester.h b/device/fido/auth_token_requester.h
index 7618a08..2a3a5f8 100644
--- a/device/fido/auth_token_requester.h
+++ b/device/fido/auth_token_requester.h
@@ -71,13 +71,15 @@
     // AuthenticatorSelectedForPINUVAuthToken is invoked to indicate that the
     // user has interacted with this authenticator (i.e. tapped its button).
     // The Delegate typically uses this signal to cancel outstanding requests to
-    // other authenticators.
+    // other authenticators. It returns false if another authenticator has
+    // already been chosen, and true otherwise. In the former case, no further
+    // methods will be called.
     //
     // This method is guaranteed to be called first and at exactly once
     // throughout the handler's lifetime, *unless*
     // HavePINUVAuthTokenResultForAuthenticator() is invoked first with one of
     // the Result codes starting with `kPreTouch`.
-    virtual void AuthenticatorSelectedForPINUVAuthToken(
+    virtual bool AuthenticatorSelectedForPINUVAuthToken(
         FidoAuthenticator* authenticator) = 0;
 
     // CollectNewPIN is invoked to prompt the user to enter a PIN for an
@@ -149,7 +151,7 @@
                 CtapDeviceResponseCode status,
                 absl::optional<pin::EmptyResponse> response);
 
-  void NotifyAuthenticatorSelected();
+  bool NotifyAuthenticatorSelected();
   void NotifyAuthenticatorSelectedAndFailWithResult(Result result);
 
   Delegate* delegate_;
@@ -157,7 +159,7 @@
 
   Options options_;
 
-  bool authenticator_was_selected_ = false;
+  absl::optional<bool> authenticator_selected_result_;
   bool is_internal_uv_retry_ = false;
   absl::optional<std::string> current_pin_;
   bool internal_uv_locked_ = false;
diff --git a/device/fido/auth_token_requester_unittest.cc b/device/fido/auth_token_requester_unittest.cc
index 4f5b7631..31c4d1d 100644
--- a/device/fido/auth_token_requester_unittest.cc
+++ b/device/fido/auth_token_requester_unittest.cc
@@ -64,12 +64,17 @@
   bool internal_uv_was_retried() { return internal_uv_num_retries_ > 0u; }
   size_t internal_uv_num_retries() { return internal_uv_num_retries_; }
   std::list<TestExpectation> expectations() { return expectations_; }
+  void set_selectable(bool selectable) { selectable_ = selectable; }
 
  private:
   // AuthTokenRequester::Delegate:
-  void AuthenticatorSelectedForPINUVAuthToken(
+  bool AuthenticatorSelectedForPINUVAuthToken(
       FidoAuthenticator* authenticator) override {
-    authenticator_selected_ = true;
+    DCHECK(!authenticator_selected_);
+    if (selectable_) {
+      authenticator_selected_ = true;
+    }
+    return selectable_;
   }
   void CollectPIN(pin::PINEntryReason reason,
                   pin::PINEntryError error,
@@ -117,6 +122,7 @@
 
   bool authenticator_selected_ = false;
   size_t internal_uv_num_retries_ = 0u;
+  bool selectable_ = true;
 
   base::RunLoop wait_for_result_loop_;
 };
@@ -173,7 +179,11 @@
     delegate_->WaitForResult();
   }
 
-  void TearDown() override { EXPECT_EQ(delegate_->expectations().size(), 0u); }
+  void TearDown() override {
+    if (delegate_) {
+      EXPECT_EQ(delegate_->expectations().size(), 0u);
+    }
+  }
 
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@@ -508,5 +518,34 @@
   EXPECT_TRUE(delegate_->response());
 }
 
+TEST_F(AuthTokenRequesterTest, NoCallsIfNotSelected) {
+  // Test that a failure to select an authenticator stops processing.
+
+  auto state = base::MakeRefCounted<VirtualFidoDevice::State>();
+  VirtualCtap2Device::Config config;
+
+  config.pin_support = true;
+  state->pin = kTestPIN;
+  config.internal_uv_support = true;
+  state->fingerprints_enrolled = true;
+
+  auto authenticator = std::make_unique<FidoDeviceAuthenticator>(
+      std::make_unique<VirtualCtap2Device>(state, std::move(config)));
+
+  base::RunLoop init_loop;
+  authenticator->InitializeAuthenticator(init_loop.QuitClosure());
+  init_loop.Run();
+
+  auto delegate = std::make_unique<TestAuthTokenRequesterDelegate>(
+      std::list<TestExpectation>());
+  delegate->set_selectable(false);
+  AuthTokenRequester::Options options;
+  options.token_permissions = {pin::Permissions::kMakeCredential};
+  options.rp_id = "foobar.com";
+  AuthTokenRequester requester(delegate.get(), authenticator.get(),
+                               std::move(options));
+  requester.ObtainPINUVAuthToken();
+}
+
 }  // namespace
 }  // namespace device
diff --git a/device/fido/authenticator_get_info_response.cc b/device/fido/authenticator_get_info_response.cc
index 31d2a7ca..e20504e 100644
--- a/device/fido/authenticator_get_info_response.cc
+++ b/device/fido/authenticator_get_info_response.cc
@@ -109,10 +109,10 @@
                                 *response.remaining_discoverable_credentials));
   }
 
-  if (!response.algorithms.empty()) {
+  if (response.algorithms.has_value()) {
     std::vector<cbor::Value> algorithms_cbor;
-    algorithms_cbor.reserve(response.algorithms.size());
-    for (const auto& algorithm : response.algorithms) {
+    algorithms_cbor.reserve(response.algorithms->size());
+    for (const auto& algorithm : *response.algorithms) {
       // Entries are PublicKeyCredentialParameters
       // https://w3c.github.io/webauthn/#dictdef-publickeycredentialparameters
       cbor::Value::MapValue entry;
diff --git a/device/fido/authenticator_get_info_response.h b/device/fido/authenticator_get_info_response.h
index d987ed11..82d5761 100644
--- a/device/fido/authenticator_get_info_response.h
+++ b/device/fido/authenticator_get_info_response.h
@@ -48,9 +48,7 @@
   absl::optional<uint32_t> max_credential_id_length;
   absl::optional<base::flat_set<PINUVAuthProtocol>> pin_protocols;
   absl::optional<std::vector<std::string>> extensions;
-  std::vector<int32_t> algorithms = {
-      static_cast<int32_t>(CoseAlgorithmIdentifier::kEs256),
-  };
+  absl::optional<std::vector<int32_t>> algorithms;
   absl::optional<uint32_t> max_serialized_large_blob_array;
   absl::optional<uint32_t> remaining_discoverable_credentials;
   absl::optional<bool> force_pin_change;
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc
index a2c59f29..23954f6 100644
--- a/device/fido/ctap_response_unittest.cc
+++ b/device/fido/ctap_response_unittest.cc
@@ -794,7 +794,7 @@
   response.options = std::move(options);
   response.max_msg_size = 1200;
   response.pin_protocols.emplace({PINUVAuthProtocol::kV1});
-  response.algorithms.clear();
+  response.algorithms.reset();
 
   EXPECT_THAT(AuthenticatorGetInfoResponse::EncodeToCBOR(response),
               ::testing::ElementsAreArray(
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc
index db931091..c200eea 100644
--- a/device/fido/device_response_converter.cc
+++ b/device/fido/device_response_converter.cc
@@ -519,7 +519,7 @@
       return absl::nullopt;
     }
 
-    response.algorithms.clear();
+    response.algorithms.emplace();
 
     const std::vector<cbor::Value>& algorithms = it->second.GetArray();
     for (const auto& algorithm : algorithms) {
@@ -550,7 +550,7 @@
         continue;
       }
 
-      response.algorithms.push_back(alg);
+      response.algorithms->push_back(alg);
     }
   }
 
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index 6cfcbe90..3aa26113 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -443,9 +443,15 @@
 #endif
 }
 
-void GetAssertionRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
+bool GetAssertionRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
     FidoAuthenticator* authenticator) {
-  DCHECK_EQ(state_, State::kWaitingForTouch);
+  if (state_ != State::kWaitingForTouch) {
+    // Some other authenticator was selected in the meantime.
+    FIDO_LOG(DEBUG) << "Rejecting select request from AuthTokenRequester "
+                       "because another authenticator was already selected.";
+    return false;
+  }
+
   state_ = State::kWaitingForToken;
   selected_authenticator_for_pin_uv_auth_token_ = authenticator;
 
@@ -453,6 +459,7 @@
     return entry.first != authenticator;
   });
   CancelActiveAuthenticators(authenticator->GetId());
+  return true;
 }
 
 void GetAssertionRequestHandler::CollectPIN(pin::PINEntryReason reason,
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h
index 4e6abe5..3eb8a8f 100644
--- a/device/fido/get_assertion_request_handler.h
+++ b/device/fido/get_assertion_request_handler.h
@@ -90,7 +90,7 @@
       FidoAuthenticator* platform_authenticator) override;
 
   // AuthTokenRequester::Delegate:
-  void AuthenticatorSelectedForPINUVAuthToken(
+  bool AuthenticatorSelectedForPINUVAuthToken(
       FidoAuthenticator* authenticator) override;
   void CollectPIN(pin::PINEntryReason reason,
                   pin::PINEntryError error,
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc
index e1a0559..659542c4 100644
--- a/device/fido/make_credential_request_handler.cc
+++ b/device/fido/make_credential_request_handler.cc
@@ -443,22 +443,23 @@
       new CtapMakeCredentialRequest(request_));
   SpecializeRequestForAuthenticator(request.get(), authenticator);
 
-  if (IsCandidateAuthenticatorPostTouch(*request.get(), authenticator, options_,
-                                        observer()) !=
-      MakeCredentialStatus::kSuccess) {
+  const MakeCredentialStatus post_touch_status =
+      IsCandidateAuthenticatorPostTouch(*request.get(), authenticator, options_,
+                                        observer());
+  if (post_touch_status != MakeCredentialStatus::kSuccess) {
 #if defined(OS_WIN)
     // If the Windows API cannot handle a request, just reject the request
     // outright. There are no other authenticators to attempt, so calling
     // GetTouch() would not make sense.
     if (authenticator->IsWinNativeApiAuthenticator()) {
-      HandleInapplicableAuthenticator(authenticator, std::move(request));
+      HandleInapplicableAuthenticator(authenticator, post_touch_status);
       return;
     }
 #endif  // defined(OS_WIN)
 
     if (authenticator->Options() &&
         authenticator->Options()->is_platform_device) {
-      HandleInapplicableAuthenticator(authenticator, std::move(request));
+      HandleInapplicableAuthenticator(authenticator, post_touch_status);
       return;
     }
 
@@ -467,7 +468,7 @@
     // will be shown if the user selects it.
     authenticator->GetTouch(base::BindOnce(
         &MakeCredentialRequestHandler::HandleInapplicableAuthenticator,
-        weak_factory_.GetWeakPtr(), authenticator, std::move(request)));
+        weak_factory_.GetWeakPtr(), authenticator, post_touch_status));
     return;
   }
 
@@ -565,9 +566,15 @@
   }
 }
 
-void MakeCredentialRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
+bool MakeCredentialRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
     FidoAuthenticator* authenticator) {
-  DCHECK_EQ(state_, State::kWaitingForTouch);
+  if (state_ != State::kWaitingForTouch) {
+    // Some other authenticator was selected in the meantime.
+    FIDO_LOG(DEBUG) << "Rejecting select request from AuthTokenRequester "
+                       "because another authenticator was already selected.";
+    return false;
+  }
+
   state_ = State::kWaitingForToken;
   selected_authenticator_for_pin_uv_auth_token_ = authenticator;
 
@@ -575,6 +582,7 @@
     return entry.first != authenticator;
   });
   CancelActiveAuthenticators(authenticator->GetId());
+  return true;
 }
 
 void MakeCredentialRequestHandler::CollectPIN(
@@ -592,8 +600,10 @@
 }
 
 void MakeCredentialRequestHandler::PromptForInternalUVRetry(int attempts) {
-  DCHECK(state_ == State::kWaitingForTouch ||
-         state_ == State::kWaitingForToken);
+  if (state_ != State::kWaitingForTouch && state_ != State::kWaitingForToken) {
+    // Some other authenticator was touched in the meantime.
+    return;
+  }
   observer()->OnRetryUserVerification(attempts);
 }
 
@@ -760,6 +770,17 @@
     return;
   }
 
+  if (status == CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm) {
+    // The authenticator didn't support any of the requested public-key
+    // algorithms. This status will have been returned immediately.
+    // Collect a touch and tell the user that it's unsupported.
+    authenticator->GetTouch(base::BindOnce(
+        &MakeCredentialRequestHandler::HandleInapplicableAuthenticator,
+        weak_factory_.GetWeakPtr(), authenticator,
+        MakeCredentialStatus::kNoCommonAlgorithms));
+    return;
+  }
+
   const absl::optional<MakeCredentialStatus> maybe_result =
       ConvertDeviceResponseCode(status);
   if (!maybe_result) {
@@ -821,15 +842,13 @@
 
 void MakeCredentialRequestHandler::HandleInapplicableAuthenticator(
     FidoAuthenticator* authenticator,
-    std::unique_ptr<CtapMakeCredentialRequest> request) {
+    MakeCredentialStatus status) {
   // User touched an authenticator that cannot handle this request.
+  DCHECK_NE(status, MakeCredentialStatus::kSuccess);
+
   state_ = State::kFinished;
   CancelActiveAuthenticators(authenticator->GetId());
-  const MakeCredentialStatus capability_error =
-      IsCandidateAuthenticatorPostTouch(*request.get(), authenticator, options_,
-                                        observer());
-  DCHECK_NE(capability_error, MakeCredentialStatus::kSuccess);
-  std::move(completion_callback_).Run(capability_error, absl::nullopt, nullptr);
+  std::move(completion_callback_).Run(status, absl::nullopt, nullptr);
 }
 
 void MakeCredentialRequestHandler::OnSampleCollected(
diff --git a/device/fido/make_credential_request_handler.h b/device/fido/make_credential_request_handler.h
index e003dae..c424ce6 100644
--- a/device/fido/make_credential_request_handler.h
+++ b/device/fido/make_credential_request_handler.h
@@ -95,7 +95,7 @@
                             FidoAuthenticator* authenticator) override;
 
   // AuthTokenRequester::Delegate:
-  void AuthenticatorSelectedForPINUVAuthToken(
+  bool AuthenticatorSelectedForPINUVAuthToken(
       FidoAuthenticator* authenticator) override;
   void CollectPIN(pin::PINEntryReason reason,
                   pin::PINEntryError error,
@@ -131,9 +131,8 @@
       CtapDeviceResponseCode response_code,
       absl::optional<AuthenticatorMakeCredentialResponse> response);
   void HandleExcludedAuthenticator(FidoAuthenticator* authenticator);
-  void HandleInapplicableAuthenticator(
-      FidoAuthenticator* authenticator,
-      std::unique_ptr<CtapMakeCredentialRequest> request);
+  void HandleInapplicableAuthenticator(FidoAuthenticator* authenticator,
+                                       MakeCredentialStatus status);
   void OnEnrollmentComplete(std::unique_ptr<CtapMakeCredentialRequest> request);
   void OnEnrollmentDismissed();
   void DispatchRequestWithToken(
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 493f62eb..14274f4a 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -616,10 +616,14 @@
   }
 
   if (config.support_invalid_for_testing_algorithm) {
-    device_info_->algorithms.push_back(
+    device_info_->algorithms->push_back(
         static_cast<int32_t>(CoseAlgorithmIdentifier::kInvalidForTesting));
   }
 
+  if (config.advertised_algorithms.has_value()) {
+    device_info_->algorithms = *config.advertised_algorithms;
+  }
+
   if (config.pin_support || config.pin_uv_auth_token_support) {
     device_info_->pin_protocols =
         base::flat_set<PINUVAuthProtocol>{config.pin_protocol};
@@ -708,10 +712,12 @@
       CtapDeviceResponseCode::kCtap1ErrInvalidCommand;
   std::vector<uint8_t> response_data;
 
+  mutable_state()->transact_callback = std::move(cb);
+
   switch (ctap_command) {
     case CtapRequestCommand::kAuthenticatorGetInfo:
       if (!request_bytes.empty()) {
-        ReturnCtap2Response(std::move(cb),
+        ReturnCtap2Response(std::move(mutable_state()->transact_callback),
                             CtapDeviceResponseCode::kCtap2ErrOther);
         return 0;
       }
@@ -773,7 +779,8 @@
 
   // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
   // support callback hairpinning.
-  ReturnCtap2Response(std::move(cb), response_code, std::move(response_data));
+  ReturnCtap2Response(std::move(mutable_state()->transact_callback),
+                      response_code, std::move(response_data));
   return 0;
 }
 
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
index 62e989b..68d2c8a 100644
--- a/device/fido/virtual_ctap2_device.h
+++ b/device/fido/virtual_ctap2_device.h
@@ -153,6 +153,10 @@
     // a makeCredential or getAssertion request carries any extension.
     bool reject_all_extensions = false;
 
+    // advertised_algorithms overrides the algorithms field of the getInfo
+    // response, if set.
+    absl::optional<absl::optional<std::vector<int32_t>>> advertised_algorithms;
+
     // support_invalid_for_testing_algorithm causes the
     // |CoseAlgorithmIdentifier::kInvalidForTesting| public-key algorithm to be
     // advertised and supported to aid testing of unknown public-key types.
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index 2326822a..11191bb 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -233,6 +233,11 @@
     FidoTransportProtocol transport =
         FidoTransportProtocol::kUsbHumanInterfaceDevice;
 
+    // transact_callback contains the outstanding callback in the event that
+    // |simulate_press_callback| returned false. This can be used to inject a
+    // response after simulating an unsatisfied touch for CTAP2 authenticators.
+    FidoDevice::DeviceCallback transact_callback;
+
     // Adds a new credential to the authenticator. Returns true on success,
     // false if there already exists a credential with the given ID.
     bool InjectRegistration(base::span<const uint8_t> credential_id,
diff --git a/device/vr/openxr/openxr_interaction_profiles.cc b/device/vr/openxr/openxr_interaction_profiles.cc
index 4dbbb34..17d8784 100644
--- a/device/vr/openxr/openxr_interaction_profiles.cc
+++ b/device/vr/openxr/openxr_interaction_profiles.cc
@@ -4,6 +4,8 @@
 
 #include "device/vr/openxr/openxr_interaction_profiles.h"
 
+#include "base/no_destructor.h"
+
 namespace device {
 OpenXrSystemInputProfiles::OpenXrSystemInputProfiles(
     std::string system_name,
diff --git a/device/vr/openxr/openxr_interaction_profiles.h b/device/vr/openxr/openxr_interaction_profiles.h
index 0e96462..6f8bf04 100644
--- a/device/vr/openxr/openxr_interaction_profiles.h
+++ b/device/vr/openxr/openxr_interaction_profiles.h
@@ -6,7 +6,6 @@
 #define DEVICE_VR_OPENXR_OPENXR_INTERACTION_PROFILES_H_
 
 #include "base/containers/flat_map.h"
-#include "base/no_destructor.h"
 #include "base/stl_util.h"
 #include "device/gamepad/public/cpp/gamepad.h"
 #include "device/vr/openxr/openxr_defs.h"
diff --git a/docs/commit_checklist.md b/docs/commit_checklist.md
index 3d3a09c..f3e22a6 100644
--- a/docs/commit_checklist.md
+++ b/docs/commit_checklist.md
@@ -212,11 +212,20 @@
 ## 18. Implement feedback from your reviewers
 
 Then go through this commit checklist again. Reply to all comments from the
-reviewers on Gerrit and mark all resolved issues as resolved (clicking `Done` or
-`Ack` will do this automatically). Click `Reply` to ensure that your reviewers
-receive a notification. Doing this signals that your CL is ready for review
-again, since the assumption is that your CL is not ready for review until you
-hit reply.
+reviewers on Gerrit and mark all resolved issues as resolved. To see all
+unresolved comments, click on the "Comments" tab in Gerrit. Other than freeform
+interaction on the comments (using `Reply` or `Quote`), here are common
+conventions:
+* Clicking `Done` on the comment will comment "Done" and resolve this comment.
+  This usually is used in response to a requested change by the reviewer, and
+  tells the reviewer that you have made the change that they requested.
+* Clicking `Ack` on the comment will comment "Ack" (short for "Acknowledged")
+  and resolve this comment. This usually is used in response to a non-actionable
+  comment by the reviewer, and tells the reviewer that you understand.
+
+Finally, click `Reply` on the CL to ensure that your reviewers receive a
+notification. Doing this signals that your CL is ready for review again, since
+the assumption is that your CL is not ready for review until you hit reply.
 
 If your change is simple and you feel confident that your reviewer will approve
 your CL on the next iteration, you can set Auto-Submit +1. The CL will proceed
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md
index f75b397..2e8ee16 100644
--- a/docs/threading_and_tasks.md
+++ b/docs/threading_and_tasks.md
@@ -567,7 +567,7 @@
   }
   void StartDoingStuff() {
     timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
-                 this, &MyClass::DoStuff);
+                 this, &A::DoStuff);
   }
   void StopDoingStuff() {
     timer_.Stop();
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 9b5ca3f..983ebcf8 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -2260,16 +2260,6 @@
   ClearExternalUninstallBit(id);
 }
 
-bool ExtensionPrefs::HasUserSeenExtensionsCheckupOnStartup() {
-  return prefs_->GetBoolean(pref_names::kExtensionCheckupOnStartup);
-}
-
-void ExtensionPrefs::SetUserHasSeenExtensionsCheckupOnStartup(
-    bool has_seen_extensions_checkup_on_startup) {
-  prefs_->SetBoolean(pref_names::kExtensionCheckupOnStartup,
-                     has_seen_extensions_checkup_on_startup);
-}
-
 const char ExtensionPrefs::kFakeObsoletePrefForTesting[] =
     "__fake_obsolete_pref_for_testing";
 
@@ -2351,8 +2341,6 @@
 #endif
 
   registry->RegisterBooleanPref(pref_names::kBlockExternalExtensions, false);
-
-  registry->RegisterBooleanPref(pref_names::kExtensionCheckupOnStartup, false);
 }
 
 template <class ExtensionIdContainer>
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
index 82ddd54..6677896 100644
--- a/extensions/browser/extension_prefs.h
+++ b/extensions/browser/extension_prefs.h
@@ -768,13 +768,6 @@
 
   void ClearExternalUninstallForTesting(const ExtensionId& id);
 
-  // Returns whether the user has seen the extension checkup on startup.
-  bool HasUserSeenExtensionsCheckupOnStartup();
-
-  // Sets if the user has seen the extension checkup on startup.
-  void SetUserHasSeenExtensionsCheckupOnStartup(
-      bool has_seen_extensions_checkup_on_startup);
-
   static const char kFakeObsoletePrefForTesting[];
 
  private:
diff --git a/extensions/browser/pref_names.cc b/extensions/browser/pref_names.cc
index d4c80ad..745b2f2d 100644
--- a/extensions/browser/pref_names.cc
+++ b/extensions/browser/pref_names.cc
@@ -33,7 +33,6 @@
 const char kAppFullscreenAllowed[] = "apps.fullscreen.allowed";
 const char kBlockExternalExtensions[] = "extensions.block_external_extensions";
 const char kExtensions[] = "extensions.settings";
-const char kExtensionCheckupOnStartup[] = "extensions.checkup_on_startup";
 const char kExtensionManagement[] = "extensions.management";
 const char kInstallAllowList[] = "extensions.install.allowlist";
 const char kInstallDenyList[] = "extensions.install.denylist";
diff --git a/extensions/browser/pref_names.h b/extensions/browser/pref_names.h
index 5a455e4..9fb79aad 100644
--- a/extensions/browser/pref_names.h
+++ b/extensions/browser/pref_names.h
@@ -46,9 +46,6 @@
 // extension ids.
 extern const char kExtensions[];
 
-// A boolean indicating if the extensions checkup has been shown on startup.
-extern const char kExtensionCheckupOnStartup[];
-
 // Dictionary pref that manages extensions, controlled by policy.
 // Values are expected to conform to the schema of the ExtensionManagement
 // policy.
diff --git a/extensions/browser/url_loader_factory_manager.h b/extensions/browser/url_loader_factory_manager.h
index 77015d9..6fd828b 100644
--- a/extensions/browser/url_loader_factory_manager.h
+++ b/extensions/browser/url_loader_factory_manager.h
@@ -6,7 +6,6 @@
 #define EXTENSIONS_BROWSER_URL_LOADER_FACTORY_MANAGER_H_
 
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "base/types/pass_key.h"
 #include "content/public/browser/navigation_handle.h"
 #include "extensions/common/extension.h"
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc
index 425d9f5..fe6888e 100644
--- a/extensions/common/extension_features.cc
+++ b/extensions/common/extension_features.cc
@@ -7,12 +7,6 @@
 
 namespace extensions_features {
 
-// Controls whether we redirect the NTP to the chrome://extensions page or show
-// a middle slot promo, and which of the the three checkup banner messages
-// (performance focused, privacy focused or neutral) to show.
-const base::Feature kExtensionsCheckup{"ExtensionsCheckup",
-                                       base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether we disable extensions for malware.
 const base::Feature kDisableMalwareExtensionsRemotely{
     "DisableMalwareExtensionsRemotely", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -43,23 +37,6 @@
 const base::Feature kSafeBrowsingCrxAllowlistAutoDisable{
     "SafeBrowsingCrxAllowlistAutoDisable", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Parameters for ExtensionsCheckup feature.
-const char kExtensionsCheckupEntryPointParameter[] = "entry_point";
-const char kExtensionsCheckupBannerMessageParameter[] = "banner_message_type";
-
-// Constants for ExtensionsCheckup parameters.
-// Indicates that the user should be shown the chrome://extensions page on
-// startup.
-const char kStartupEntryPoint[] = "startup";
-// Indicates that the user should be shown a promo on the NTP leading to the
-// chrome://extensions page.
-const char kNtpPromoEntryPoint[] = "promo";
-// Indicates the focus of the message shown on chrome://the extensions page
-// banner and the NTP promo.
-const char kPerformanceMessage[] = "0";
-const char kPrivacyMessage[] = "1";
-const char kNeutralMessage[] = "2";
-
 // Forces requests to go through WebRequestProxyingURLLoaderFactory.
 const base::Feature kForceWebRequestProxyForTest{
     "ForceWebRequestProxyForTest", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h
index a51676c..e945fff 100644
--- a/extensions/common/extension_features.h
+++ b/extensions/common/extension_features.h
@@ -15,16 +15,6 @@
 extern const base::Feature kSafeBrowsingCrxAllowlistShowWarnings;
 extern const base::Feature kSafeBrowsingCrxAllowlistAutoDisable;
 
-// Extension check up related features.
-extern const base::Feature kExtensionsCheckup;
-extern const char kExtensionsCheckupEntryPointParameter[];
-extern const char kExtensionsCheckupBannerMessageParameter[];
-extern const char kStartupEntryPoint[];
-extern const char kNtpPromoEntryPoint[];
-extern const char kPerformanceMessage[];
-extern const char kPrivacyMessage[];
-extern const char kNeutralMessage[];
-
 extern const base::Feature kForceWebRequestProxyForTest;
 
 extern const base::Feature kAllowWithholdingExtensionPermissionsOnInstall;
diff --git a/fuchsia/engine/web_instance_host/web_instance_host.cc b/fuchsia/engine/web_instance_host/web_instance_host.cc
index df9b7e3..a027450 100644
--- a/fuchsia/engine/web_instance_host/web_instance_host.cc
+++ b/fuchsia/engine/web_instance_host/web_instance_host.cc
@@ -157,8 +157,11 @@
 bool HandleDataDirectoryParam(fuchsia::web::CreateContextParams* params,
                               base::CommandLine* launch_args,
                               fuchsia::sys::LaunchInfo* launch_info) {
-  if (!params->has_data_directory())
+  if (!params->has_data_directory()) {
+    // Caller requested a web instance without any peristence.
+    launch_args->AppendSwitch(switches::kIncognito);
     return true;
+  }
 
   zx::channel data_directory_channel = ValidateDirectoryAndTakeChannel(
       std::move(*params->mutable_data_directory()));
diff --git a/google_apis/drive/auth_service.cc b/google_apis/drive/auth_service.cc
index f7c08e7..b1c49eb 100644
--- a/google_apis/drive/auth_service.cc
+++ b/google_apis/drive/auth_service.cc
@@ -11,10 +11,12 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/scoped_observation.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/signin/public/identity_manager/access_token_fetcher.h"
 #include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/scope_set.h"
 #include "google_apis/drive/auth_service_observer.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -111,25 +113,53 @@
 
 }  // namespace
 
+// This class is separate from AuthService itself so that AuthService doesn't
+// need a public dependency on signin::IdentityManager::Observer, and therefore
+// doesn't need to pull that dependency into all of its client classes.
+class AuthService::IdentityManagerObserver
+    : public signin::IdentityManager::Observer {
+ public:
+  explicit IdentityManagerObserver(AuthService* service) : service_(service) {
+    manager_observation_.Observe(service->identity_manager_);
+  }
+  ~IdentityManagerObserver() override = default;
+
+  // signin::IdentityManager::Observer:
+  void OnRefreshTokenUpdatedForAccount(
+      const CoreAccountInfo& account_info) override {
+    service_->OnHandleRefreshToken(account_info.account_id, true);
+  }
+
+  void OnRefreshTokenRemovedForAccount(
+      const CoreAccountId& account_id) override {
+    service_->OnHandleRefreshToken(account_id, false);
+  }
+
+ private:
+  AuthService* service_ = nullptr;
+  base::ScopedObservation<signin::IdentityManager,
+                          signin::IdentityManager::Observer>
+      manager_observation_{this};
+};
+
 AuthService::AuthService(
     signin::IdentityManager* identity_manager,
     const CoreAccountId& account_id,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::vector<std::string>& scopes)
     : identity_manager_(identity_manager),
+      identity_manager_observer_(
+          std::make_unique<IdentityManagerObserver>(this)),
       account_id_(account_id),
       url_loader_factory_(url_loader_factory),
       scopes_(scopes) {
   DCHECK(identity_manager_);
 
-  identity_manager_->AddObserver(this);
   has_refresh_token_ =
       identity_manager_->HasAccountWithRefreshToken(account_id_);
 }
 
-AuthService::~AuthService() {
-  identity_manager_->RemoveObserver(this);
-}
+AuthService::~AuthService() = default;
 
 void AuthService::StartAuthentication(AuthStatusCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -170,7 +200,7 @@
 }
 
 void AuthService::ClearRefreshToken() {
-  OnHandleRefreshToken(false);
+  OnHandleRefreshToken(account_id_, false);
 }
 
 void AuthService::OnAuthCompleted(AuthStatusCallback callback,
@@ -203,19 +233,11 @@
   observers_.RemoveObserver(observer);
 }
 
-void AuthService::OnRefreshTokenUpdatedForAccount(
-    const CoreAccountInfo& account_info) {
-  if (account_info.account_id == account_id_)
-    OnHandleRefreshToken(true);
-}
+void AuthService::OnHandleRefreshToken(const CoreAccountId& account_id,
+                                       bool has_refresh_token) {
+  if (account_id != account_id_)
+    return;
 
-void AuthService::OnRefreshTokenRemovedForAccount(
-    const CoreAccountId& account_id) {
-  if (account_id == account_id_)
-    OnHandleRefreshToken(false);
-}
-
-void AuthService::OnHandleRefreshToken(bool has_refresh_token) {
   access_token_.clear();
   has_refresh_token_ = has_refresh_token;
 
diff --git a/google_apis/drive/auth_service.h b/google_apis/drive/auth_service.h
index ebd5b43f..ef910f64 100644
--- a/google_apis/drive/auth_service.h
+++ b/google_apis/drive/auth_service.h
@@ -13,13 +13,17 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
 #include "google_apis/drive/auth_service_interface.h"
+#include "google_apis/gaia/core_account_id.h"
 
 namespace network {
 class SharedURLLoaderFactory;
 }
 
+namespace signin {
+class IdentityManager;
+}
+
 namespace google_apis {
 
 class AuthServiceObserver;
@@ -28,8 +32,7 @@
 // It integrates specific service integration with the Identity service
 // (IdentityManager) and provides OAuth2 token refresh infrastructure.
 // All public functions must be called on UI thread.
-class AuthService : public AuthServiceInterface,
-                    public signin::IdentityManager::Observer {
+class AuthService : public AuthServiceInterface {
  public:
   // |url_loader_factory| is used to perform authentication with
   // SimpleURLLoader.
@@ -51,15 +54,12 @@
   void ClearAccessToken() override;
   void ClearRefreshToken() override;
 
-  // Overridden from IdentityManager::Observer
-  void OnRefreshTokenUpdatedForAccount(
-      const CoreAccountInfo& account_info) override;
-  void OnRefreshTokenRemovedForAccount(
-      const CoreAccountId& account_id) override;
-
  private:
+  class IdentityManagerObserver;
+
   // Called when the state of the refresh token changes.
-  void OnHandleRefreshToken(bool has_refresh_token);
+  void OnHandleRefreshToken(const CoreAccountId& account_id,
+                            bool has_refresh_token);
 
   // Called when authentication request from StartAuthentication() is
   // completed.
@@ -68,6 +68,7 @@
                        const std::string& access_token);
 
   signin::IdentityManager* identity_manager_;
+  std::unique_ptr<IdentityManagerObserver> identity_manager_observer_;
   CoreAccountId account_id_;
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   bool has_refresh_token_;
diff --git a/gpu/command_buffer/client/dawn_client_memory_transfer_service.cc b/gpu/command_buffer/client/dawn_client_memory_transfer_service.cc
index 58ba657..4695ce1 100644
--- a/gpu/command_buffer/client/dawn_client_memory_transfer_service.cc
+++ b/gpu/command_buffer/client/dawn_client_memory_transfer_service.cc
@@ -45,24 +45,6 @@
     return true;
   }
 
-  // TODO(dawn:773): remove after main update on dawn side.
-  bool DeserializeInitialData(const void* deserialize_pointer,
-                              size_t deserialize_size,
-                              const void** data,
-                              size_t* data_length) override {
-    // No data is deserialized because we're using shared memory.
-    DCHECK_EQ(deserialize_size, 0u);
-    DCHECK(data);
-    DCHECK(data_length);
-
-    // Write the pointer and size of the shared memory allocation.
-    // |data| and |data_length| are provided by the dawn_wire client.
-    *data = ptr_;
-    *data_length = handle_.size;
-
-    return true;
-  }
-
  private:
   void* ptr_;  // Pointer to client-side shared memory.
   MemoryTransferHandle handle_;
@@ -105,22 +87,6 @@
     // No data is serialized because we're using shared memory.
   }
 
-  // TODO(dawn:773): remove after main update on dawn side.
-  std::pair<void*, size_t> Open() override {
-    return std::make_pair(ptr_, handle_.size);
-  }
-
-  // TODO(dawn:773): remove after main update on dawn side.
-  size_t SerializeFlushSize() override {
-    // No data is serialized because we're using shared memory.
-    return 0;
-  }
-
-  // TODO(dawn:773): remove after main update on dawn side.
-  void SerializeFlush(void* serialize_pointer) override {
-    // No data is serialized because we're using shared memory.
-  }
-
  private:
   void* ptr_;
   MemoryTransferHandle handle_;
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index 7fe983e..6462836f 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -203,6 +203,9 @@
 
   bool mesa_framebuffer_flip_y = false;
 
+  // Clients should use SharedImageInterface instead.
+  bool disable_legacy_mailbox = false;
+
   int major_version = 2;
   int minor_version = 0;
 
diff --git a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
index 7727f7f..2df536f 100644
--- a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
+++ b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
@@ -36,24 +36,6 @@
     memcpy(static_cast<uint8_t*>(ptr_) + offset, data, size);
   }
 
-  // TODO(dawn:773): remove after main update on dawn side.
-  size_t SerializeInitialDataSize(const void* data,
-                                  size_t data_length) override {
-    // Nothing is serialized because we're using shared memory.
-    return 0;
-  }
-
-  // TODO(dawn:773): remove after main update on dawn side.
-  void SerializeInitialData(const void* data,
-                            size_t data_length,
-                            void* serialize_pointer) override {
-    DCHECK_EQ(data_length, size_);
-    // Copy the initial data into the shared memory allocation.
-    // In the case of buffer mapping, this is the mapped GPU memory which we
-    // copy into client-visible shared memory.
-    memcpy(ptr_, data, data_length);
-  }
-
  private:
   void* ptr_;
   uint32_t size_;
@@ -79,27 +61,13 @@
     DCHECK(ptr_);
 
     // Copy from shared memory into the target buffer.
-    // TODO(dawn:773): mTargetData will always be the starting address
+    // mTargetData will always be the starting address
     // of the backing buffer after the dawn side change.
     memcpy(static_cast<uint8_t*>(mTargetData) + offset,
            static_cast<const uint8_t*>(ptr_) + offset, size);
     return true;
   }
 
-  // TODO(dawn:773): remove after main update on dawn side.
-  bool DeserializeFlush(const void* deserialize_pointer,
-                        size_t deserialize_size) override {
-    // Nothing is serialized because we're using shared memory.
-    DCHECK_EQ(deserialize_size, 0u);
-    DCHECK_EQ(mDataLength, size_);
-    DCHECK(mTargetData);
-    DCHECK(ptr_);
-
-    // Copy from shared memory into the target buffer.
-    memcpy(mTargetData, ptr_, size_);
-    return true;
-  }
-
  private:
   const void* ptr_;  // Pointer to client-visible shared memory.
   uint32_t size_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 9318cb6..db5b813 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4365,6 +4365,9 @@
   caps.num_surface_buffers = surface_->GetBufferCount();
   caps.mesa_framebuffer_flip_y =
       feature_info_->feature_flags().mesa_framebuffer_flip_y;
+  caps.disable_legacy_mailbox =
+      group_->shared_image_manager() &&
+      group_->shared_image_manager()->display_context_on_another_thread();
 
   caps.gpu_memory_buffer_formats =
       feature_info_->feature_flags().gpu_memory_buffer_formats;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index cb692ee..4d517d8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1686,6 +1686,9 @@
       feature_info_->feature_flags().gpu_memory_buffer_formats;
   caps.texture_target_exception_list =
       group_->gpu_preferences().texture_target_exception_list;
+  caps.disable_legacy_mailbox =
+      group_->shared_image_manager() &&
+      group_->shared_image_manager()->display_context_on_another_thread();
 
   return caps;
 }
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 2ada6fc..6814eb55 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -863,6 +863,7 @@
   static const CommandInfo command_info[kNumCommands - kFirstRasterCommand];
 
   const int raster_decoder_id_;
+  const bool disable_legacy_mailbox_;
 
   // Number of commands remaining to be processed in DoCommands().
   int commands_to_process_ = 0;
@@ -1023,6 +1024,9 @@
     bool is_privileged)
     : RasterDecoder(client, command_buffer_service, outputter),
       raster_decoder_id_(g_raster_decoder_id.GetNext() + 1),
+      disable_legacy_mailbox_(
+          shared_image_manager &&
+          shared_image_manager->display_context_on_another_thread()),
       supports_gpu_raster_(
           gpu_feature_info.status_values[GPU_FEATURE_TYPE_GPU_RASTERIZATION] ==
           kGpuFeatureStatusEnabled),
@@ -1274,6 +1278,7 @@
   caps.shared_image_swap_chain =
       SharedImageBackingFactoryD3D::IsSwapChainSupported();
 #endif  // OS_WIN
+  caps.disable_legacy_mailbox = disable_legacy_mailbox_;
   return caps;
 }
 
diff --git a/gpu/command_buffer/service/skia_utils.cc b/gpu/command_buffer/service/skia_utils.cc
index 015f407d..431ecfb 100644
--- a/gpu/command_buffer/service/skia_utils.cc
+++ b/gpu/command_buffer/service/skia_utils.cc
@@ -83,9 +83,10 @@
                                             &glyph_cache_max_texture_bytes);
   options.fDisableCoverageCountingPaths = true;
   options.fGlyphCacheTextureMaximumBytes = glyph_cache_max_texture_bytes;
-  // TODO(csmartdalton): enable internal multisampling after the related Skia
-  // rolls are in.
-  options.fInternalMultisampleCount = 0;
+  // TODO(junov, csmartdalton): Find a way to control fInternalMultisampleCount
+  // in a more granular way.  For OOPR-Canvas we want 8, but for other purposes,
+  // a texture atlas with sample count of 4 would be sufficient
+  options.fInternalMultisampleCount = 8;
   if (type == GrContextType::kMetal)
     options.fRuntimeProgramCacheSize = 1024;
 
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
index 5fbf4e2..cff50ee 100644
--- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -681,6 +681,14 @@
     return false;
 #endif
   }
+
+  bool IsMac() const {
+#if defined(OS_MAC)
+    return true;
+#else
+    return false;
+#endif
+  }
 };
 
 INSTANTIATE_TEST_SUITE_P(CopyType,
@@ -752,6 +760,12 @@
         << "Passthrough command decoder expected failure. Skipping test...";
     return;
   }
+  if (IsMac() && !gl_.gpu_preferences().use_passthrough_cmd_decoder) {
+    // TODO(crbug.com/1227853): Remove this suppression once this passes on Mac
+    // 11.
+    LOG(INFO) << "Validating decoder on Mac. Skipping.";
+    return;
+  }
   const CopyType copy_type = GetParam();
 
   FormatType src_format_types[] = {
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
index 1466177..b32548a 100644
--- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -154,6 +154,7 @@
   IPC_STRUCT_TRAITS_MEMBER(context_supports_distance_field_text)
   IPC_STRUCT_TRAITS_MEMBER(chromium_nonblocking_readback)
   IPC_STRUCT_TRAITS_MEMBER(mesa_framebuffer_flip_y)
+  IPC_STRUCT_TRAITS_MEMBER(disable_legacy_mailbox)
 
   IPC_STRUCT_TRAITS_MEMBER(major_version)
   IPC_STRUCT_TRAITS_MEMBER(minor_version)
diff --git a/gpu/ipc/service/dcomp_texture_win.cc b/gpu/ipc/service/dcomp_texture_win.cc
index 7a6744c..f48e76d 100644
--- a/gpu/ipc/service/dcomp_texture_win.cc
+++ b/gpu/ipc/service/dcomp_texture_win.cc
@@ -19,6 +19,7 @@
 #include "gpu/ipc/common/gpu_channel.mojom.h"
 #include "gpu/ipc/service/gpu_channel.h"
 #include "gpu/ipc/service/gpu_channel_manager.h"
+#include "ipc/ipc_mojo_bootstrap.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gl/dcomp_surface_registry.h"
@@ -79,7 +80,11 @@
       context_state_(std::move(context_state)),
       sequence_(channel_->scheduler()->CreateSequence(SchedulingPriority::kLow,
                                                       channel_->task_runner())),
-      receiver_(this, std::move(receiver)) {
+      receiver_(this) {
+  auto runner = base::MakeRefCounted<SchedulerTaskRunner>(
+      *channel_->scheduler(), sequence_);
+  IPC::ScopedAllowOffSequenceChannelAssociatedBindings allow_binding;
+  receiver_.Bind(std::move(receiver), runner);
   context_state_->AddContextLostObserver(this);
   channel_->AddRoute(route_id, sequence_);
 }
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index d92f410..ba51280 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -274,6 +274,7 @@
   base::AutoLock auto_lock(gpu_channel_lock_);
   DCHECK(gpu_channel_);
   DCHECK(scheduler_);
+  DCHECK(!route_sequences_.count(route_id));
   route_sequences_[route_id] = sequence_id;
 }
 
@@ -281,6 +282,7 @@
   base::AutoLock auto_lock(gpu_channel_lock_);
   DCHECK(gpu_channel_);
   DCHECK(scheduler_);
+  DCHECK(route_sequences_.count(route_id));
   route_sequences_.erase(route_id);
 }
 
diff --git a/gpu/vulkan/x/vulkan_surface_x11.cc b/gpu/vulkan/x/vulkan_surface_x11.cc
index 30836b23..f8600686 100644
--- a/gpu/vulkan/x/vulkan_surface_x11.cc
+++ b/gpu/vulkan/x/vulkan_surface_x11.cc
@@ -27,23 +27,13 @@
     return nullptr;
   }
 
-  x11::VisualId visual_id{};
-  uint8_t depth = 0;
-  x11::ColorMap colormap{};
-  auto* visual_manager = ui::XVisualManager::GetInstance();
-  visual_manager->ChooseVisualForWindow(true, &visual_id, &depth, &colormap,
-                                        nullptr);
-
   auto window = connection->GenerateId<x11::Window>();
   connection->CreateWindow(x11::CreateWindowRequest{
-      .depth = depth,
       .wid = window,
       .parent = parent_window,
       .width = geometry->width,
       .height = geometry->height,
       .c_class = x11::WindowClass::InputOutput,
-      .visual = visual_id,
-      .colormap = colormap,
   });
   if (connection->MapWindow({window}).Sync().error) {
     LOG(ERROR) << "Failed to create or map window.";
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index 506f1e5..b9120ae 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -326,8 +326,8 @@
   if (command_line.HasSwitch(::switches::kDisableBreakpad))
     return;
 #if defined(OS_FUCHSIA)
-  // TODO(fuchsia): Implement this when crash reporting/Breakpad are available
-  // in Fuchsia. (crbug.com/753619)
+  // TODO(crbug.com/1226159): Implement this when crash reporting/Breakpad are
+  // available in Fuchsia.
   NOTIMPLEMENTED();
 #else
   const std::string process_type =
diff --git a/infra/config/dev.star b/infra/config/dev.star
index de79fad..315917fa 100755
--- a/infra/config/dev.star
+++ b/infra/config/dev.star
@@ -9,7 +9,7 @@
 load("//lib/branches.star", "branches")
 
 lucicfg.check_version(
-    min = "1.23.6",
+    min = "1.27.0",
     message = "Update depot_tools",
 )
 
diff --git a/infra/config/generated/cr-buildbucket-dev.cfg b/infra/config/generated/cr-buildbucket-dev.cfg
index ff1908a..654eabbb 100644
--- a/infra/config/generated/cr-buildbucket-dev.cfg
+++ b/infra/config/generated/cr-buildbucket-dev.cfg
@@ -33,7 +33,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -73,7 +93,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -113,7 +153,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -160,7 +220,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -201,7 +281,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -242,7 +342,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -282,7 +401,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
@@ -322,7 +461,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver-dev.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dev\",\"recipe\":\"swarming/staging\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver-dev.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dev",'
+        '  "recipe": "swarming/staging"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index bff277c3..6709bd8 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -36,7 +36,42 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/chromium_3pp\":{\"gclient_apply_config\":[\"android\"],\"gclient_config\":\"chromium\",\"platform\":\"linux-amd64\",\"preprocess\":[{\"cmd\":[\"{CHECKOUT}/src/third_party/android_deps/fetch_all.py\",\"-v\",\"--ignore-vulnerabilities\"],\"name\":\"third_party/android_deps\"}]},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.packager\",\"recipe\":\"chromium_3pp\"}"
+      properties:
+        '{'
+        '  "$build/chromium_3pp": {'
+        '    "gclient_apply_config": ['
+        '      "android"'
+        '    ],'
+        '    "gclient_config": "chromium",'
+        '    "platform": "linux-amd64",'
+        '    "preprocess": ['
+        '      {'
+        '        "cmd": ['
+        '          "{CHECKOUT}/src/third_party/android_deps/fetch_all.py",'
+        '          "-v",'
+        '          "--ignore-vulnerabilities"'
+        '        ],'
+        '        "name": "third_party/android_deps"'
+        '      }'
+        '    ]'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.packager",'
+        '  "recipe": "chromium_3pp"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -104,7 +139,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -172,7 +231,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -240,7 +323,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -308,7 +415,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -376,7 +507,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -444,7 +599,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -512,7 +691,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -580,7 +783,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_afl\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_afl"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -648,7 +875,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -716,7 +968,37 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$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\":150,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$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": 150,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -784,7 +1066,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -852,7 +1159,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -920,7 +1252,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -988,7 +1345,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1056,7 +1438,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1124,7 +1531,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1192,7 +1624,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1260,7 +1717,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1328,7 +1810,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1396,7 +1903,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1464,7 +1996,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1532,7 +2088,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1600,7 +2181,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1668,7 +2274,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1736,7 +2367,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1804,7 +2460,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1872,7 +2553,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -1940,7 +2645,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2008,7 +2738,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 18000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2080,7 +2835,37 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$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\":150,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$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": 150,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 18000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2148,7 +2933,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 18000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2216,7 +3026,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2284,7 +3119,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2352,7 +3212,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2420,7 +3299,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2488,7 +3392,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2556,7 +3485,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":50,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 50,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2624,7 +3578,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2692,7 +3671,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2760,7 +3764,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2828,7 +3857,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2896,7 +3949,41 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":250,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"reclient_goma_comparison\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 250,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Comparison Linux - cache siloed"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "reclient_goma_comparison"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -2964,7 +4051,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3032,7 +4138,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3100,7 +4225,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3168,7 +4317,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3236,7 +4409,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3304,7 +4495,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3372,7 +4581,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3440,7 +4667,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3506,7 +4751,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3572,7 +4840,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3640,7 +4931,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3708,7 +5017,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3776,7 +5103,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3844,7 +5189,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3912,7 +5275,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -3980,7 +5367,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4048,7 +5459,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4116,7 +5551,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4184,7 +5637,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4252,7 +5723,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4320,7 +5809,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4388,7 +5895,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4456,7 +5987,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4524,7 +6079,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4592,7 +6165,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4660,7 +6251,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4728,7 +6337,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.dawn\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.dawn",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4796,7 +6423,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 25200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4864,7 +6516,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -4932,7 +6609,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5000,7 +6701,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5068,7 +6794,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5136,7 +6887,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5204,7 +6980,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5272,7 +7073,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5340,7 +7166,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5408,7 +7259,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5476,7 +7352,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5542,7 +7443,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5608,7 +7533,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5676,7 +7625,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5744,7 +7718,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5812,7 +7811,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5880,7 +7904,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -5948,7 +7997,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6016,7 +8090,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6084,7 +8183,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6152,7 +8275,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6218,7 +8365,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6284,7 +8454,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6352,7 +8545,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6420,7 +8637,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6488,7 +8729,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6556,7 +8816,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6624,7 +8903,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6692,7 +8996,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6760,7 +9088,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6828,7 +9180,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6896,7 +9272,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -6963,7 +9363,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7031,7 +9455,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7099,7 +9547,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7167,7 +9639,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7235,7 +9731,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7303,7 +9823,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7371,7 +9915,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7438,7 +10006,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7505,7 +10096,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium_libfuzzer\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium_libfuzzer"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7573,7 +10188,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7641,7 +10281,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7709,7 +10374,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7777,7 +10467,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7849,7 +10564,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7917,7 +10657,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -7985,7 +10749,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-gvisor-shadow\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-gvisor-shadow",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8053,7 +10841,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8121,7 +10934,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8189,7 +11027,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8257,7 +11119,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8325,7 +11211,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_platform\":\"container-image=docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:b4dad0bfc4951d619229ab15343a311f2415a16ef83bcaa55b44f4e2bf1cf635,pool=linux-n2-standard\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_platform": "container-image=docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:b4dad0bfc4951d619229ab15343a311f2415a16ef83bcaa55b44f4e2bf1cf635,pool=linux-n2-standard"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8393,7 +11306,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":500,\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_platform\":\"container-image=docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:b4dad0bfc4951d619229ab15343a311f2415a16ef83bcaa55b44f4e2bf1cf635,pool=linux-e2-custom_0\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 500,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_platform": "container-image=docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:b4dad0bfc4951d619229ab15343a311f2415a16ef83bcaa55b44f4e2bf1cf635,pool=linux-e2-custom_0"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8461,7 +11401,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 18000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8529,7 +11494,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8597,7 +11587,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8665,7 +11680,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8733,7 +11772,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8801,7 +11865,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8869,7 +11958,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -8937,7 +12044,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9005,7 +12131,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9073,7 +12218,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9141,7 +12305,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9209,7 +12398,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9277,7 +12485,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9345,7 +12572,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 64800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9413,7 +12659,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9481,7 +12746,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9549,7 +12839,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9617,7 +12926,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9685,7 +13013,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9753,7 +13100,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9821,7 +13187,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9889,7 +13280,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -9957,7 +13373,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10025,7 +13466,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10093,7 +13559,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10161,7 +13652,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10229,7 +13738,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10297,7 +13831,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10365,7 +13924,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10433,7 +14016,33 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"Linux TSan Builder (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Linux TSan Builder (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10501,7 +14110,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10569,7 +14203,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10637,7 +14296,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10705,7 +14389,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10773,7 +14482,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10841,7 +14568,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10909,7 +14661,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -10977,7 +14753,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11045,7 +14846,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11113,7 +14939,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11181,7 +15031,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11248,7 +15122,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11315,7 +15212,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11381,7 +15301,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"debug\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "debug": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11448,7 +15392,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11514,7 +15482,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11580,7 +15571,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11645,7 +15659,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11713,7 +15750,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11781,7 +15836,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11849,7 +15923,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11917,7 +16010,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -11985,7 +16097,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 43200
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12051,7 +16182,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12119,7 +16274,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12187,7 +16361,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12255,7 +16448,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12323,7 +16535,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12391,7 +16622,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12459,7 +16709,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12525,7 +16794,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12593,7 +16886,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12661,7 +16973,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12729,7 +17059,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12797,7 +17145,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12863,7 +17229,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12929,7 +17318,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -12997,7 +17409,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13065,7 +17495,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13133,7 +17581,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13201,7 +17667,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13269,7 +17753,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13337,7 +17839,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13405,7 +17925,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13473,7 +18011,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13541,7 +18104,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 43200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13609,7 +18197,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mojo\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mojo",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13677,7 +18289,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mojo\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mojo",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13745,7 +18381,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mojo\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mojo",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13812,7 +18472,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mojo\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mojo",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13880,7 +18564,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -13948,7 +18657,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14016,7 +18750,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14084,7 +18843,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14152,7 +18935,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14220,7 +19027,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"Linux TSan Builder (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Linux TSan Builder (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14288,7 +19122,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14356,7 +19214,33 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":250,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 250,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14424,7 +19308,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"TSAN Release (core-32) (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "TSAN Release (core-32) (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14492,7 +19403,33 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"TSAN Release (deps-cache) (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "TSAN Release (deps-cache) (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14560,7 +19497,33 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"Linux TSan Builder (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Linux TSan Builder (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14628,7 +19591,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"Linux TSan Builder (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Linux TSan Builder (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14696,7 +19686,33 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\",\"rewrapper_env\":{\"RBE_cache_silo\":\"Linux TSan Builder (reclient)\"}},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "rewrapper_env": {'
+        '      "RBE_cache_silo": "Linux TSan Builder (reclient)"'
+        '    }'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14764,7 +19780,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-gvisor-shadow\",\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-gvisor-shadow",'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14832,7 +19871,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14900,7 +19958,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -14968,7 +20045,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15036,7 +20132,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15104,7 +20219,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15172,7 +20306,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15240,7 +20393,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15308,7 +20480,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15376,7 +20567,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15444,7 +20654,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15512,7 +20741,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15580,7 +20828,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15648,7 +20915,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15715,7 +21001,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15783,7 +21088,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium_clang_coverage_tot\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium_clang_coverage_tot"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15851,7 +21175,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15919,7 +21262,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -15987,7 +21349,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16055,7 +21436,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16123,7 +21523,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16191,7 +21611,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16259,7 +21699,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16327,7 +21787,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium_clang_coverage_tot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium_clang_coverage_tot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16395,7 +21875,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16462,7 +21961,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16530,7 +22048,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16598,7 +22135,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16666,7 +22222,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16734,7 +22309,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16802,7 +22396,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16869,7 +22482,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -16937,7 +22569,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17005,7 +22656,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17073,7 +22743,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium_clang_coverage_tot\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium_clang_coverage_tot"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17140,7 +22829,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       caches {
         name: "xcode_ios_12d4e"
@@ -17211,7 +22920,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 50400
       caches {
         name: "xcode_ios_12d4e"
@@ -17283,7 +23012,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17351,7 +23104,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17419,7 +23196,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17487,7 +23288,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17555,7 +23380,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"jobs\":250,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 250,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17623,7 +23472,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17691,7 +23565,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17759,7 +23658,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17826,7 +23750,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17893,7 +23841,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17961,7 +23933,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18028,7 +24024,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18095,7 +24115,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fuzz\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fuzz",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18162,7 +24206,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18229,7 +24297,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18296,7 +24388,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18364,7 +24480,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18432,7 +24572,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18500,7 +24663,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\",\"profiler_service\":\"reclient-win\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics",'
+        '    "profiler_service": "reclient-win"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18568,7 +24755,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18636,7 +24842,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18704,7 +24929,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18772,7 +25016,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18840,7 +25103,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18908,7 +25190,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18976,7 +25277,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19044,7 +25364,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 64800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19112,7 +25451,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19180,7 +25538,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19248,7 +25625,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19316,7 +25718,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19383,7 +25804,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19450,7 +25895,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19517,7 +25986,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19585,7 +26072,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19653,7 +26158,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19721,7 +26244,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19789,7 +26336,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19857,7 +26423,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19925,7 +26510,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.gpu.fyi\",\"perf_dashboard_machine_group\":\"ChromiumGPUFYI\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.gpu.fyi",'
+        '  "perf_dashboard_machine_group": "ChromiumGPUFYI",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -19993,7 +26597,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20061,7 +26689,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20128,7 +26780,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.win\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.win",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 43200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20196,7 +26873,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20264,7 +26966,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20332,7 +27058,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20400,7 +27150,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.packager\",\"recipe\":\"android/androidx_packager\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.packager",'
+        '  "recipe": "android/androidx_packager"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20468,7 +27236,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20536,7 +27329,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20604,7 +27416,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20672,7 +27509,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20740,7 +27596,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20808,7 +27688,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20876,7 +27780,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 21600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -20944,7 +27873,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21012,7 +27966,37 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"avd_configs\":[\"tools/android/avd/proto/creation/generic_android23.textpb\",\"tools/android/avd/proto/creation/generic_android27.textpb\",\"tools/android/avd/proto/creation/generic_android28.textpb\",\"tools/android/avd/proto/creation/generic_android29.textpb\",\"tools/android/avd/proto/creation/generic_android30.textpb\",\"tools/android/avd/proto/creation/generic_androidS.textpb\",\"tools/android/avd/proto/creation/generic_playstore_android27.textpb\",\"tools/android/avd/proto/creation/generic_playstore_android28.textpb\",\"tools/android/avd/proto/creation/generic_playstore_android30.textpb\",\"tools/android/avd/proto/creation/generic_playstore_androidS.textpb\"],\"builder_group\":\"chromium.packager\",\"recipe\":\"android/avd_packager\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "avd_configs": ['
+        '    "tools/android/avd/proto/creation/generic_android23.textpb",'
+        '    "tools/android/avd/proto/creation/generic_android27.textpb",'
+        '    "tools/android/avd/proto/creation/generic_android28.textpb",'
+        '    "tools/android/avd/proto/creation/generic_android29.textpb",'
+        '    "tools/android/avd/proto/creation/generic_android30.textpb",'
+        '    "tools/android/avd/proto/creation/generic_androidS.textpb",'
+        '    "tools/android/avd/proto/creation/generic_playstore_android27.textpb",'
+        '    "tools/android/avd/proto/creation/generic_playstore_android28.textpb",'
+        '    "tools/android/avd/proto/creation/generic_playstore_android30.textpb",'
+        '    "tools/android/avd/proto/creation/generic_playstore_androidS.textpb"'
+        '  ],'
+        '  "builder_group": "chromium.packager",'
+        '  "recipe": "android/avd_packager"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21080,7 +28064,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21148,7 +28156,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21216,7 +28248,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21284,7 +28341,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"binary_size_generator_tot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "binary_size_generator_tot"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21352,7 +28434,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_java_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_java_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21420,7 +28529,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21488,7 +28624,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21556,7 +28717,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21624,7 +28810,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21692,7 +28903,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21760,7 +28996,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21828,7 +29089,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21896,7 +29182,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21964,7 +29275,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22029,7 +29365,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"cronet\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "cronet"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22097,7 +29457,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22165,7 +29550,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22233,7 +29643,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22301,7 +29736,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22369,7 +29829,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22437,7 +29922,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22505,7 +30015,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22573,7 +30108,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22640,7 +30200,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 25200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22708,7 +30292,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22776,7 +30385,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22844,7 +30478,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22912,7 +30571,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -22980,7 +30663,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23048,7 +30756,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23116,7 +30849,123 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.packager\",\"packages\":[{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/25.0.2.yaml\",\"sdk_package_name\":\"build-tools;25.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/29.0.2.yaml\",\"sdk_package_name\":\"build-tools;29.0.2\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/build-tools/30.0.1.yaml\",\"sdk_package_name\":\"build-tools;30.0.1\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/cmdline-tools.yaml\",\"sdk_package_name\":\"cmdline-tools;latest\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/emulator.yaml\",\"sdk_package_name\":\"emulator\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/patcher/v4.yaml\",\"sdk_package_name\":\"patcher;v4\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-29.yaml\",\"sdk_package_name\":\"platforms;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platforms/android-30.yaml\",\"sdk_package_name\":\"platforms;android-30\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/platform-tools.yaml\",\"sdk_package_name\":\"platform-tools\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/sources/android-29.yaml\",\"sdk_package_name\":\"sources;android-29\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-23;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-27/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-27;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-27/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-27;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-28/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-28;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-28/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-28;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-29/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-29;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-30/google_apis_playstore/x86.yaml\",\"sdk_package_name\":\"system-images;android-30;google_apis_playstore;x86\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-S/google_apis/x86_64.yaml\",\"sdk_package_name\":\"system-images;android-S;google_apis;x86_64\"},{\"cipd_yaml\":\"third_party/android_sdk/cipd/system_images/android-S/google_apis_playstore/x86_64.yaml\",\"sdk_package_name\":\"system-images;android-S;google_apis_playstore;x86_64\"}],\"recipe\":\"android/sdk_packager\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.packager",'
+        '  "packages": ['
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/build-tools/25.0.2.yaml",'
+        '      "sdk_package_name": "build-tools;25.0.2"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/build-tools/29.0.2.yaml",'
+        '      "sdk_package_name": "build-tools;29.0.2"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/build-tools/30.0.1.yaml",'
+        '      "sdk_package_name": "build-tools;30.0.1"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/build-tools/31.0.0.yaml",'
+        '      "sdk_package_name": "build-tools;31.0.0"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/cmdline-tools.yaml",'
+        '      "sdk_package_name": "cmdline-tools;latest"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/emulator.yaml",'
+        '      "sdk_package_name": "emulator"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/patcher/v4.yaml",'
+        '      "sdk_package_name": "patcher;v4"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/platforms/android-29.yaml",'
+        '      "sdk_package_name": "platforms;android-29"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/platforms/android-30.yaml",'
+        '      "sdk_package_name": "platforms;android-30"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/platforms/android-31.yaml",'
+        '      "sdk_package_name": "platforms;android-31"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/platform-tools.yaml",'
+        '      "sdk_package_name": "platform-tools"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/sources/android-29.yaml",'
+        '      "sdk_package_name": "sources;android-29"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/sources/android-30.yaml",'
+        '      "sdk_package_name": "sources;android-30"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-23;google_apis;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-27/google_apis/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-27;google_apis;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-27/google_apis_playstore/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-27;google_apis_playstore;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-28/google_apis/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-28;google_apis;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-28/google_apis_playstore/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-28;google_apis_playstore;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-29/google_apis/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-29;google_apis;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-29/google_apis_playstore/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-29;google_apis_playstore;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-30/google_apis/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-30;google_apis;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-30/google_apis_playstore/x86.yaml",'
+        '      "sdk_package_name": "system-images;android-30;google_apis_playstore;x86"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-31/google_apis/x86_64.yaml",'
+        '      "sdk_package_name": "system-images;android-31;google_apis;x86_64"'
+        '    },'
+        '    {'
+        '      "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-31/google_apis_playstore/x86_64.yaml",'
+        '      "sdk_package_name": "system-images;android-31;google_apis_playstore;x86_64"'
+        '    }'
+        '  ],'
+        '  "recipe": "android/sdk_packager"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23184,7 +31033,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23252,7 +31125,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23320,7 +31217,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23388,7 +31310,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23456,7 +31403,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23524,7 +31496,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23592,7 +31588,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23660,7 +31680,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23728,7 +31772,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23796,7 +31865,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23864,7 +31958,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.android.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.android.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -23932,7 +32050,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24000,7 +32142,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24068,7 +32234,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24136,7 +32326,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24204,7 +32418,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24272,7 +32510,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24340,7 +32602,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24408,7 +32693,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24476,7 +32785,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24544,7 +32877,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24612,7 +32969,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24680,7 +33061,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24748,7 +33154,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24816,7 +33247,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24884,7 +33342,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -24952,7 +33434,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25020,7 +33526,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25088,7 +33618,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25156,7 +33710,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25224,7 +33802,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25292,7 +33894,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25360,7 +33987,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25426,7 +34078,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_12d4e"
@@ -25498,7 +34175,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -25564,7 +34260,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -25634,7 +34354,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_12d4e"
@@ -25704,7 +34448,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_12d4e"
@@ -25775,7 +34543,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_exclude_sources": "ios_test_files_and_test_utils",'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 72000
       caches {
         name: "xcode_ios_12d4e"
@@ -25845,7 +34645,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -25915,7 +34739,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_12d4e"
@@ -25985,7 +34833,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -26055,7 +34927,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\",\"xcode_build_version\":\"13a5155e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "13a5155e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_13a5155e"
@@ -26125,7 +35021,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12e262wk\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12e262wk"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12e262wk"
@@ -26195,7 +35115,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -26265,7 +35209,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12e262\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12e262"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12e262"
@@ -26335,7 +35303,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -26405,7 +35397,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"13a5155e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "13a5155e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_13a5155e"
@@ -26475,7 +35491,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"13a5155e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "13a5155e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_13a5155e"
@@ -26547,7 +35587,56 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/archive\":{\"archive_datas\":[{\"archive_type\":\"ARCHIVE_TYPE_ZIP\",\"dirs\":[\"locales\",\"swiftshader\"],\"files\":[\"chrome\",\"chrome_100_percent.pak\",\"chrome_200_percent.pak\",\"crashpad_handler\",\"headless_lib.pak\",\"icudtl.dat\",\"nacl_helper\",\"nacl_irt_x86_64.nexe\",\"resources.pak\",\"snapshot_blob.bin\"],\"gcs_bucket\":\"chromium-lacros-fishfood\",\"gcs_path\":\"x86_64/{%position%}/lacros.zip\"}]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/archive": {'
+        '    "archive_datas": ['
+        '      {'
+        '        "archive_type": "ARCHIVE_TYPE_ZIP",'
+        '        "dirs": ['
+        '          "locales",'
+        '          "swiftshader"'
+        '        ],'
+        '        "files": ['
+        '          "chrome",'
+        '          "chrome_100_percent.pak",'
+        '          "chrome_200_percent.pak",'
+        '          "crashpad_handler",'
+        '          "headless_lib.pak",'
+        '          "icudtl.dat",'
+        '          "nacl_helper",'
+        '          "nacl_irt_x86_64.nexe",'
+        '          "resources.pak",'
+        '          "snapshot_blob.bin"'
+        '        ],'
+        '        "gcs_bucket": "chromium-lacros-fishfood",'
+        '        "gcs_path": "x86_64/{%position%}/lacros.zip"'
+        '      }'
+        '    ]'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26615,7 +35704,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26683,7 +35796,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26751,7 +35888,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26819,7 +35980,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26887,7 +36073,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -26955,7 +36166,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27023,7 +36253,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27091,7 +36340,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27159,7 +36427,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27227,7 +36514,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27295,7 +36606,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27363,7 +36698,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27431,7 +36790,62 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/archive\":{\"archive_datas\":[{\"archive_type\":\"ARCHIVE_TYPE_ZIP\",\"dirs\":[\"locales\",\"swiftshader\"],\"files\":[\"chrome\",\"chrome_100_percent.pak\",\"chrome_200_percent.pak\",\"crashpad_handler\",\"headless_lib.pak\",\"icudtl.dat\",\"libminigbm.so\",\"nacl_helper\",\"nacl_irt_x86_64.nexe\",\"resources.pak\",\"snapshot_blob.bin\",\"test_ash_chrome\"],\"gcs_bucket\":\"ash-chromium-on-linux-prebuilts\",\"gcs_path\":\"x86_64/{%position%}/ash-chromium.zip\",\"latest_upload\":{\"gcs_file_content\":\"{%position%}\",\"gcs_path\":\"x86_64/latest/ash-chromium.txt\"}}]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/archive": {'
+        '    "archive_datas": ['
+        '      {'
+        '        "archive_type": "ARCHIVE_TYPE_ZIP",'
+        '        "dirs": ['
+        '          "locales",'
+        '          "swiftshader"'
+        '        ],'
+        '        "files": ['
+        '          "chrome",'
+        '          "chrome_100_percent.pak",'
+        '          "chrome_200_percent.pak",'
+        '          "crashpad_handler",'
+        '          "headless_lib.pak",'
+        '          "icudtl.dat",'
+        '          "libminigbm.so",'
+        '          "nacl_helper",'
+        '          "nacl_irt_x86_64.nexe",'
+        '          "resources.pak",'
+        '          "snapshot_blob.bin",'
+        '          "test_ash_chrome"'
+        '        ],'
+        '        "gcs_bucket": "ash-chromium-on-linux-prebuilts",'
+        '        "gcs_path": "x86_64/{%position%}/ash-chromium.zip",'
+        '        "latest_upload": {'
+        '          "gcs_file_content": "{%position%}",'
+        '          "gcs_path": "x86_64/latest/ash-chromium.txt"'
+        '        }'
+        '      }'
+        '    ]'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27499,7 +36913,47 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/archive\":{\"cipd_archive_datas\":[{\"only_set_refs_on_tests_success\":true,\"refs\":[\"{%channel%}\"],\"tags\":{\"version\":\"{%chromium_version%}\"},\"yaml_files\":[\"gen_linux_ash_chromium_cipd_yaml_cipd.yaml\"]}]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/archive": {'
+        '    "cipd_archive_datas": ['
+        '      {'
+        '        "only_set_refs_on_tests_success": true,'
+        '        "refs": ['
+        '          "{%channel%}"'
+        '        ],'
+        '        "tags": {'
+        '          "version": "{%chromium_version%}"'
+        '        },'
+        '        "yaml_files": ['
+        '          "gen_linux_ash_chromium_cipd_yaml_cipd.yaml"'
+        '        ]'
+        '      }'
+        '    ]'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27567,7 +37021,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27635,7 +37113,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27703,7 +37206,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27771,7 +37299,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27839,7 +37391,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27907,7 +37483,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -27975,7 +37575,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28043,7 +37667,27 @@
         cipd_version: "latest"
         cmd: "bootstrapper"
       }
-      properties: "{\"$bootstrap\":{\"exe\":{\"cipd_package\":\"infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build\",\"cipd_version\":\"refs/heads/master\",\"cmd\":[\"luciexe\"]},\"properties_file\":\"infra/config/generated/builders/ci/linux-bootstrap/properties.textpb\",\"top_level_project\":{\"ref\":\"refs/heads/main\",\"repo\":{\"host\":\"chromium.googlesource.com\",\"project\":\"chromium/src\"}}},\"builder_group\":\"infra\"}"
+      properties:
+        '{'
+        '  "$bootstrap": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/master",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    },'
+        '    "properties_file": "infra/config/generated/builders/ci/linux-bootstrap/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "infra"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28111,7 +37755,27 @@
         cipd_version: "latest"
         cmd: "bootstrapper"
       }
-      properties: "{\"$bootstrap\":{\"exe\":{\"cipd_package\":\"infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build\",\"cipd_version\":\"refs/heads/master\",\"cmd\":[\"luciexe\"]},\"properties_file\":\"infra/config/generated/builders/ci/linux-bootstrap-tests/properties.textpb\",\"top_level_project\":{\"ref\":\"refs/heads/main\",\"repo\":{\"host\":\"chromium.googlesource.com\",\"project\":\"chromium/src\"}}},\"builder_group\":\"infra\"}"
+      properties:
+        '{'
+        '  "$bootstrap": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/master",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    },'
+        '    "properties_file": "infra/config/generated/builders/ci/linux-bootstrap-tests/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "infra"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28179,7 +37843,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28247,7 +37935,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28315,7 +38034,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28383,7 +38126,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_javascript_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_javascript_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28451,7 +38221,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28519,7 +38313,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28587,7 +38405,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28655,7 +38497,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28722,7 +38595,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"infra\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "infra",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28789,7 +38686,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"infra\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "infra",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28857,7 +38778,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28925,7 +38870,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_reference_commit\":\"c942891373445199f69afd905965ad1e89cdee09\",\"coverage_test_types\":[\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_reference_commit": "c942891373445199f69afd905965ad1e89cdee09",'
+        '    "coverage_test_types": ['
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -28993,7 +38969,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29061,7 +39062,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29129,7 +39154,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29197,7 +39240,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29265,7 +39332,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29333,7 +39424,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29401,7 +39523,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29469,7 +39615,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.chromiumos\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.chromiumos",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29537,7 +39707,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29604,7 +39798,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"infra\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "infra",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29671,7 +39889,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"infra\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "infra",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29738,7 +39980,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29806,7 +40072,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29873,7 +40164,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"infra\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "infra",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -29941,7 +40256,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30009,7 +40348,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30077,7 +40440,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30145,7 +40532,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30213,7 +40624,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30281,7 +40716,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30349,7 +40809,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30417,7 +40902,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30485,7 +40994,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.clang\",\"perf_dashboard_machine_group\":\"ChromiumClang\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.clang",'
+        '  "perf_dashboard_machine_group": "ChromiumClang",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 50400
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30553,7 +41081,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30622,7 +41174,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30691,7 +41267,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30760,7 +41360,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30828,7 +41453,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30894,7 +41538,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -30962,7 +41630,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31028,7 +41715,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31096,7 +41807,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31164,7 +41894,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31232,7 +41981,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31299,7 +42067,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31366,7 +42157,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31433,7 +42247,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31500,7 +42337,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31566,7 +42426,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31632,7 +42515,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31700,7 +42606,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mac\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mac",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31768,7 +42692,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31836,7 +42784,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31904,7 +42876,37 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -31971,7 +42973,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32038,7 +43063,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.mojo\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.mojo",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32104,7 +43152,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32172,7 +43243,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32239,7 +43334,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32306,7 +43424,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32372,7 +43513,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32438,7 +43602,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32504,7 +43691,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32571,7 +43781,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32639,7 +43872,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32707,7 +43964,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32775,7 +44056,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32843,7 +44148,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32911,7 +44240,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -32979,7 +44332,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33047,7 +44424,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33115,7 +44516,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33183,7 +44608,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33251,7 +44700,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33319,7 +44792,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33387,7 +44884,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33455,7 +44976,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.linux\",\"recipe\":\"chromium_export_metadata\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.linux",'
+        '  "recipe": "chromium_export_metadata"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "component-mapping-updater@chops-service-accounts.iam.gserviceaccount.com"
@@ -33521,7 +45067,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.packager\",\"recipe\":\"chromium_rts/create_model\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.packager",'
+        '  "recipe": "chromium_rts/create_model"'
+        '}'
       execution_timeout_secs: 28800
       build_numbers: YES
       service_account: "chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33589,7 +45153,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33657,7 +45246,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33725,7 +45339,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33793,7 +45432,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33861,7 +45525,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 57600
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33928,7 +45616,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -33995,7 +45707,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34063,7 +45799,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.memory\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 500,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.memory",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34131,7 +45892,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34199,7 +45984,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34266,7 +46075,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"exclude\":\"chrome_only\",\"pool_name\":\"celab-chromium-ci\",\"pool_size\":20,\"recipe\":\"celab\",\"tests\":\"*\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "exclude": "chrome_only",'
+        '  "pool_name": "celab-chromium-ci",'
+        '  "pool_size": 20,'
+        '  "recipe": "celab",'
+        '  "tests": "*"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34333,7 +46170,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"exclude\":\"chrome_only\",\"pool_name\":\"celab-chromium-ci\",\"pool_size\":20,\"recipe\":\"celab\",\"tests\":\"*\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "exclude": "chrome_only",'
+        '  "pool_name": "celab-chromium-ci",'
+        '  "pool_size": 20,'
+        '  "recipe": "celab",'
+        '  "tests": "*"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34400,7 +46265,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 25200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34467,7 +46356,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34535,7 +46448,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34603,7 +46540,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34671,7 +46632,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34739,7 +46724,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34807,7 +46816,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34875,7 +46908,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -34943,7 +47000,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35011,7 +47092,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.swangle\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.swangle",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35079,7 +47184,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35147,7 +47276,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35215,7 +47368,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35283,7 +47460,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35351,7 +47547,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35419,7 +47634,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35487,7 +47721,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35555,7 +47808,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 72000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35623,7 +47907,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35691,7 +47999,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35758,7 +48090,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35825,7 +48181,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35892,7 +48272,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -35959,7 +48364,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 25200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36027,7 +48456,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36095,7 +48548,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36163,7 +48640,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36231,7 +48732,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36299,7 +48824,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36367,7 +48911,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36435,7 +48998,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.angle\",\"perf_dashboard_machine_group\":\"ChromiumANGLE\",\"recipe\":\"angle_chromium\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.angle",'
+        '  "perf_dashboard_machine_group": "ChromiumANGLE",'
+        '  "recipe": "angle_chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36503,7 +49085,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36571,7 +49177,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.updater\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.updater",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -36655,7 +49285,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -36728,7 +49378,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -36801,7 +49471,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -36874,7 +49564,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -36947,7 +49657,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -37020,7 +49750,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.codesearch\",\"recipe\":\"chromium_codesearch\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.codesearch",'
+        '  "recipe": "chromium_codesearch"'
+        '}'
       execution_timeout_secs: 32400
       expiration_secs: 7200
       caches {
@@ -37109,7 +49859,29 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"recipe\":\"findit/chromium/single_revision\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "recipe": "findit/chromium/single_revision"'
+        '}'
       execution_timeout_secs: 28800
       caches {
         name: "win_toolchain"
@@ -37137,7 +49909,29 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"recipe\":\"findit/chromium/compile\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "recipe": "findit/chromium/compile"'
+        '}'
       execution_timeout_secs: 28800
       caches {
         name: "win_toolchain"
@@ -37166,7 +49960,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"gs_bucket\":\"findit-for-me\",\"gs_object\":\"bot_db.json\",\"recipe\":\"findit/chromium/export_bot_db\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "gs_bucket": "findit-for-me",'
+        '  "gs_object": "bot_db.json",'
+        '  "recipe": "findit/chromium/export_bot_db"'
+        '}'
       execution_timeout_secs: 28800
       caches {
         name: "win_toolchain"
@@ -37212,7 +50025,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37238,7 +50075,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37264,7 +50125,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37290,7 +50175,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37316,7 +50225,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37342,7 +50275,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37368,7 +50325,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37394,7 +50375,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37420,7 +50425,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37446,7 +50475,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37472,7 +50525,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37498,7 +50575,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37524,7 +50625,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37550,7 +50675,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37576,7 +50725,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37602,7 +50775,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37628,7 +50825,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37654,7 +50875,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37680,7 +50925,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 14400
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37706,7 +50975,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 10800
       caches {
         name: "xcode_ios_12d4e"
@@ -37737,7 +51031,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37764,7 +51082,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37790,7 +51132,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37816,7 +51182,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37841,7 +51231,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37867,7 +51281,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37893,7 +51331,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37919,7 +51381,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37945,7 +51431,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37971,7 +51481,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -37997,7 +51531,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38023,7 +51581,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38049,7 +51631,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38075,7 +51681,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38102,7 +51732,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38129,7 +51783,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38156,7 +51834,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38183,7 +51885,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38210,7 +51936,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38237,7 +51987,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38263,7 +52037,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?staging\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?staging",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38289,7 +52087,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?tot",'
+        '    "server_host": "staging-goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38314,7 +52136,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -38343,7 +52189,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 36000
       caches {
         name: "xcode_ios_12d4e"
@@ -38374,7 +52244,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38401,7 +52295,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38428,7 +52346,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38455,7 +52397,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38481,7 +52447,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38507,7 +52497,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.goma.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 80,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.goma.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 36000
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -38550,7 +52564,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/reclient\":{\"instance\":\"rbe-chromium-trusted\",\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.reclient.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.reclient.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -38669,7 +52706,43 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/chromium_3pp\":{\"gclient_apply_config\":[\"android\"],\"gclient_config\":\"chromium\",\"package_prefix\":\"chromium_3pp\",\"platform\":\"linux-amd64\",\"preprocess\":[{\"cmd\":[\"{CHECKOUT}/src/third_party/android_deps/fetch_all.py\",\"-v\",\"--ignore-vulnerabilities\"],\"name\":\"third_party/android_deps\"}]},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.packager\",\"recipe\":\"chromium_3pp\"}"
+      properties:
+        '{'
+        '  "$build/chromium_3pp": {'
+        '    "gclient_apply_config": ['
+        '      "android"'
+        '    ],'
+        '    "gclient_config": "chromium",'
+        '    "package_prefix": "chromium_3pp",'
+        '    "platform": "linux-amd64",'
+        '    "preprocess": ['
+        '      {'
+        '        "cmd": ['
+        '          "{CHECKOUT}/src/third_party/android_deps/fetch_all.py",'
+        '          "-v",'
+        '          "--ignore-vulnerabilities"'
+        '        ],'
+        '        "name": "third_party/android_deps"'
+        '      }'
+        '    ]'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.packager",'
+        '  "recipe": "chromium_3pp"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -38748,7 +52821,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -38827,7 +52924,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -38906,7 +53027,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -38984,7 +53129,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39062,7 +53232,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39141,7 +53336,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39220,7 +53439,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39298,7 +53541,46 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/binary_size\":{\"analyze_targets\":[\"//chrome/android:monochrome_public_minimal_apks\",\"//chrome/android:trichrome_minimal_apks\",\"//chrome/android:validate_expectations\",\"//tools/binary_size:binary_size_trybot_py\"],\"compile_targets\":[\"monochrome_public_minimal_apks\",\"monochrome_static_initializers\",\"trichrome_minimal_apks\",\"validate_expectations\"]},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"binary_size_trybot\"}"
+      properties:
+        '{'
+        '  "$build/binary_size": {'
+        '    "analyze_targets": ['
+        '      "//chrome/android:monochrome_public_minimal_apks",'
+        '      "//chrome/android:trichrome_minimal_apks",'
+        '      "//chrome/android:validate_expectations",'
+        '      "//tools/binary_size:binary_size_trybot_py"'
+        '    ],'
+        '    "compile_targets": ['
+        '      "monochrome_public_minimal_apks",'
+        '      "monochrome_static_initializers",'
+        '      "trichrome_minimal_apks",'
+        '      "validate_expectations"'
+        '    ]'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "binary_size_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39377,7 +53659,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39456,7 +53762,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39535,7 +53865,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -39614,7 +53968,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -39693,7 +54071,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39771,7 +54173,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39850,7 +54277,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_java_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_java_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -39929,7 +54388,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40008,7 +54492,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40087,7 +54595,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40166,7 +54699,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40245,7 +54802,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40324,7 +54905,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40403,7 +55008,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40482,7 +55111,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40561,7 +55218,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40639,7 +55324,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40718,7 +55428,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40797,7 +55532,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40876,7 +55635,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -40955,7 +55739,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41034,7 +55842,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41113,7 +55945,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41192,7 +56048,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41271,7 +56151,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41350,7 +56254,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41429,7 +56357,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41508,7 +56460,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41587,7 +56563,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41666,7 +56666,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41745,7 +56769,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41824,7 +56872,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41902,7 +56974,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -41980,7 +57077,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42059,7 +57181,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42138,7 +57284,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42217,7 +57388,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42296,7 +57491,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42375,7 +57594,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42453,7 +57697,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42532,7 +57801,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42611,7 +57904,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42689,7 +58006,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42768,7 +58109,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42847,7 +58212,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -42925,7 +58314,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -43004,7 +58418,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43083,7 +58521,56 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"branch_configs\":[{\"branch_types\":[\"standard\"],\"name\":\"standard\"},{\"branch_types\":[\"desktop-extended-stable\"],\"name\":\"desktop-extended-stable\"},{\"branch_types\":[\"cros-lts\"],\"name\":\"cros-lts\"},{\"branch_types\":[\"desktop-extended-stable\",\"cros-lts\"],\"name\":\"desktop-extended-stable + cros-lts\"}],\"branch_script\":\"infra/config/scripts/branch.py\",\"recipe\":\"branch_configuration/tester\",\"verification_scripts\":[\"infra/config/main.star\",\"infra/config/dev.star\"]}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "branch_configs": ['
+        '    {'
+        '      "branch_types": ['
+        '        "standard"'
+        '      ],'
+        '      "name": "standard"'
+        '    },'
+        '    {'
+        '      "branch_types": ['
+        '        "desktop-extended-stable"'
+        '      ],'
+        '      "name": "desktop-extended-stable"'
+        '    },'
+        '    {'
+        '      "branch_types": ['
+        '        "cros-lts"'
+        '      ],'
+        '      "name": "cros-lts"'
+        '    },'
+        '    {'
+        '      "branch_types": ['
+        '        "desktop-extended-stable",'
+        '        "cros-lts"'
+        '      ],'
+        '      "name": "desktop-extended-stable + cros-lts"'
+        '    }'
+        '  ],'
+        '  "branch_script": "infra/config/scripts/branch.py",'
+        '  "recipe": "branch_configuration/tester",'
+        '  "verification_scripts": ['
+        '    "infra/config/main.star",'
+        '    "infra/config/dev.star"'
+        '  ]'
+        '}'
       priority: 25
       execution_timeout_secs: 14400
       expiration_secs: 7200
@@ -43163,7 +58650,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/binary_size\":{\"analyze_targets\":[\"//chromecast:cast_shell\"],\"compile_targets\":[\"cast_shell\"]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"binary_size_cast_trybot\"}"
+      properties:
+        '{'
+        '  "$build/binary_size": {'
+        '    "analyze_targets": ['
+        '      "//chromecast:cast_shell"'
+        '    ],'
+        '    "compile_targets": ['
+        '      "cast_shell"'
+        '    ]'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "binary_size_cast_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43241,7 +58760,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43320,7 +58863,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43398,7 +58965,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43477,7 +59068,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43556,7 +59171,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43635,7 +59274,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43713,7 +59376,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43792,7 +59479,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43870,7 +59581,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -43949,7 +59684,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44027,7 +59786,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44106,7 +59889,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44185,7 +59992,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44264,7 +60095,29 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$depot_tools/presubmit\":{\"runhooks\":true,\"timeout_s\":480},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"recipe\":\"presubmit\",\"repo_name\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$depot_tools/presubmit": {'
+        '    "runhooks": true,'
+        '    "timeout_s": 480'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "recipe": "presubmit",'
+        '  "repo_name": "chromium"'
+        '}'
       priority: 25
       execution_timeout_secs: 14400
       expiration_secs: 7200
@@ -44342,7 +60195,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44419,7 +60296,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44496,7 +60396,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44573,7 +60497,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44650,7 +60598,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44727,7 +60699,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44805,7 +60801,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44883,7 +60904,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -44962,7 +61008,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45041,7 +61111,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45120,7 +61214,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45199,7 +61317,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45278,7 +61420,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45357,7 +61523,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45436,7 +61626,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45515,7 +61729,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45594,7 +61832,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45672,7 +61934,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45750,7 +62036,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45828,7 +62138,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45906,7 +62240,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -45984,7 +62342,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46059,7 +62441,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46134,7 +62540,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46209,7 +62639,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46284,7 +62738,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46359,7 +62837,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46434,7 +62936,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46509,7 +63035,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46584,7 +63134,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46659,7 +63233,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46734,7 +63332,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46809,7 +63431,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46884,7 +63530,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -46959,7 +63629,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47034,7 +63728,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47109,7 +63827,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47184,7 +63926,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47259,7 +64025,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47334,7 +64124,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47409,7 +64223,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47484,7 +64322,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47559,7 +64421,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47634,7 +64520,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47709,7 +64619,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47784,7 +64718,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47859,7 +64817,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -47933,7 +64915,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48007,7 +65012,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48081,7 +65109,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48155,7 +65206,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48229,7 +65303,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48303,7 +65400,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48377,7 +65497,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48451,7 +65594,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48525,7 +65691,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48599,7 +65788,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48673,7 +65885,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48747,7 +65982,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 43200
       expiration_secs: 7200
       caches {
@@ -48821,7 +66079,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48896,7 +66177,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -48971,7 +66276,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49046,7 +66375,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49121,7 +66474,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49196,7 +66573,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49271,7 +66672,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49346,7 +66771,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49421,7 +66870,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49496,7 +66969,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49571,7 +67068,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49646,7 +67167,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49721,7 +67266,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49796,7 +67365,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49871,7 +67464,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -49946,7 +67563,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -50021,7 +67662,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -50095,7 +67760,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -50169,7 +67857,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -50244,7 +67955,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -50318,7 +68053,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\",\"xcode_build_version\":\"12a7209\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot",'
+        '  "xcode_build_version": "12a7209"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -50396,7 +68155,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50477,7 +68260,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_exclude_sources": "ios_test_files_and_test_utils",'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50558,7 +68373,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50639,7 +68478,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"overall\",\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_exclude_sources": "ios_test_files_and_test_utils",'
+        '    "coverage_test_types": ['
+        '      "overall",'
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50720,7 +68591,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50801,7 +68696,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50882,7 +68801,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"13a5155e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "13a5155e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -50963,7 +68906,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_exclude_sources\":\"ios_test_files_and_test_utils\",\"coverage_test_types\":[\"unit\"],\"use_clang_coverage\":true},\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_exclude_sources": "ios_test_files_and_test_utils",'
+        '    "coverage_test_types": ['
+        '      "unit"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51044,7 +69018,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51125,7 +69123,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12e262\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12e262"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51206,7 +69228,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51287,7 +69333,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"13a5155e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot",'
+        '  "xcode_build_version": "13a5155e"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51369,7 +69439,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51447,7 +69541,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51526,7 +69644,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51605,7 +69747,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51683,7 +69849,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"bot_update_experiments\":[\"no_sync\"],\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "bot_update_experiments": ['
+        '    "no_sync"'
+        '  ],'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51761,7 +69955,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51839,7 +70058,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51917,7 +70161,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -51996,7 +70265,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52075,7 +70368,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52154,7 +70471,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52233,7 +70574,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52312,7 +70678,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52391,7 +70781,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52470,7 +70884,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52549,7 +70987,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52628,7 +71090,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52707,7 +71193,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52786,7 +71296,27 @@
         cipd_version: "latest"
         cmd: "bootstrapper"
       }
-      properties: "{\"$bootstrap\":{\"exe\":{\"cipd_package\":\"infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build\",\"cipd_version\":\"refs/heads/master\",\"cmd\":[\"luciexe\"]},\"properties_file\":\"infra/config/generated/builders/try/linux-bootstrap/properties.textpb\",\"top_level_project\":{\"ref\":\"refs/heads/main\",\"repo\":{\"host\":\"chromium.googlesource.com\",\"project\":\"chromium/src\"}}},\"builder_group\":\"tryserver.infra\"}"
+      properties:
+        '{'
+        '  "$bootstrap": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/master",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    },'
+        '    "properties_file": "infra/config/generated/builders/try/linux-bootstrap/properties.textpb",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.infra"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52865,7 +71395,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -52943,7 +71497,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53022,7 +71600,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53101,7 +71703,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53180,7 +71806,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true,\"use_javascript_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true,'
+        '    "use_javascript_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53258,7 +71912,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53337,7 +72023,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"tricium_clang_tidy_wrapper\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "tricium_clang_tidy_wrapper"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53416,7 +72127,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"tricium_clang_tidy_wrapper\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "tricium_clang_tidy_wrapper"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53493,7 +72229,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53572,7 +72332,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53651,7 +72435,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53730,7 +72538,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53809,7 +72641,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53888,7 +72738,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -53967,7 +72841,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54046,7 +72944,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.chromiumos",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54125,7 +73048,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54204,7 +73151,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54282,7 +73253,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_libfuzzer_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_libfuzzer_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54361,7 +73356,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54440,7 +73459,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54519,7 +73562,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54597,7 +73664,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54676,7 +73767,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54754,7 +73869,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54831,7 +73978,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"orchestrator\":{\"builder_group\":\"tryserver.chromium.linux\",\"builder_name\":\"linux-rel-orchestrator\"},\"recipe\":\"chromium/compilator\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "orchestrator": {'
+        '    "builder_group": "tryserver.chromium.linux",'
+        '    "builder_name": "linux-rel-orchestrator"'
+        '  },'
+        '  "recipe": "chromium/compilator"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54909,7 +74088,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"compilator\":\"linux-rel-compilator\",\"recipe\":\"chromium/orchestrator\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "compilator": "linux-rel-compilator",'
+        '  "recipe": "chromium/orchestrator"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -54988,7 +74195,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/reclient\":{\"instance\":\"rbe-chromium-gvisor-shadow\",\"jobs\":150,\"metrics_project\":\"chromium-reclient-metrics\"},\"$kitchen\":{\"devshell\":true,\"emulate_gce\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-gvisor-shadow",'
+        '    "jobs": 150,'
+        '    "metrics_project": "chromium-reclient-metrics"'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "emulate_gce": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55066,7 +74300,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55145,7 +74407,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -55221,7 +74507,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -55297,7 +74607,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -55373,7 +74707,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -55449,7 +74807,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55528,7 +74911,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55607,7 +75014,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55686,7 +75117,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55765,7 +75220,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55844,7 +75323,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -55923,7 +75426,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56002,7 +75530,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56080,7 +75632,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56159,7 +75736,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56238,7 +75839,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56317,7 +75942,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56396,7 +76046,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56475,7 +76149,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 25200
       expiration_secs: 7200
       grace_period {
@@ -56554,7 +76253,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56633,7 +76357,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"swarming/deterministic_build\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "swarming/deterministic_build"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -56712,7 +76460,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56791,7 +76563,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56869,7 +76665,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -56952,7 +76773,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57031,7 +76876,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57114,7 +76983,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57192,7 +77086,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57270,7 +77189,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57349,7 +77293,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57428,7 +77396,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57507,7 +77499,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57586,7 +77602,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57665,7 +77705,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57743,7 +77807,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -57822,7 +77910,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_upload_clang\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_upload_clang"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57901,7 +78007,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -57978,7 +78108,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58055,7 +78209,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58133,7 +78311,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58210,7 +78412,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58288,7 +78513,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58365,7 +78613,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58443,7 +78714,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58521,7 +78815,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58599,7 +78920,34 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58676,7 +79024,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -58750,7 +79121,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.updater\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.updater",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58827,7 +79221,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.updater\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.updater",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58905,7 +79322,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -58983,7 +79423,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59061,7 +79524,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59139,7 +79625,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59217,7 +79726,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59295,7 +79827,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59373,7 +79928,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59451,7 +80029,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59529,7 +80130,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59607,7 +80231,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59685,7 +80332,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59763,7 +80433,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59841,7 +80534,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59919,7 +80636,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -59997,7 +80738,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60075,7 +80839,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60152,7 +80939,30 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -60230,7 +81040,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_upload_clang\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_upload_clang"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -60308,7 +81136,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_upload_clang\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.mac",'
+        '  "recipe": "chromium_upload_clang"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -60387,7 +81233,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60466,7 +81336,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"tricium_metrics\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "tricium_metrics"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60545,7 +81439,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"tricium_oilpan\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "tricium_oilpan"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60624,7 +81542,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"tricium_simple\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.linux",'
+        '  "recipe": "tricium_simple"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60703,7 +81645,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60781,7 +81747,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60859,7 +81850,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -60937,7 +81953,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61015,7 +82056,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.angle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.angle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61094,7 +82160,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61173,7 +82263,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61252,7 +82367,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"exclude\":\"chrome_only\",\"pool_name\":\"celab-chromium-try\",\"pool_size\":20,\"recipe\":\"celab\",\"tests\":\"*\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "exclude": "chrome_only",'
+        '  "pool_name": "celab-chromium-try",'
+        '  "pool_size": 20,'
+        '  "recipe": "celab",'
+        '  "tests": "*"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61329,7 +82472,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.dawn\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.dawn",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61407,7 +82574,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_libfuzzer_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_libfuzzer_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -61486,7 +82677,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -61565,7 +82780,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       caches {
@@ -61641,7 +82880,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -61717,7 +82980,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -61793,7 +83080,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -61869,7 +83180,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"angle_chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "angle_chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -61945,7 +83280,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -62021,7 +83380,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.swangle\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.swangle",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 7200
       expiration_secs: 7200
       caches {
@@ -62097,7 +83480,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.updater\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.updater",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62176,7 +83583,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.updater\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.updater",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62255,7 +83686,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62334,7 +83789,43 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":false,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"orchestrator\":{\"builder_group\":\"tryserver.chromium.win\",\"builder_name\":\"win10-rel-orchestrator\"},\"recipe\":\"chromium/compilator\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "orchestrator": {'
+        '    "builder_group": "tryserver.chromium.win",'
+        '    "builder_name": "win10-rel-orchestrator"'
+        '  },'
+        '  "recipe": "chromium/compilator"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62412,7 +83903,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"compilator\":\"win10-rel-compilator\",\"recipe\":\"chromium/orchestrator\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "compilator": "win10-rel-compilator",'
+        '  "recipe": "chromium/orchestrator"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62491,7 +84014,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62570,7 +84117,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62648,7 +84219,38 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62727,7 +84329,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62806,7 +84432,39 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"coverage_test_types\":[\"unit\",\"overall\"],\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":false,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "coverage_test_types": ['
+        '      "unit",'
+        '      "overall"'
+        '    ],'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62884,7 +84542,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -62962,7 +84644,35 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/code_coverage": {'
+        '    "use_clang_coverage": true'
+        '  },'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63041,7 +84751,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -63120,7 +84854,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.blink\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.blink",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63199,7 +84957,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 300,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 16200
       expiration_secs: 7200
       grace_period {
@@ -63278,7 +85061,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63357,7 +85164,32 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "jobs": 150,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63436,7 +85268,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63515,7 +85371,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63594,7 +85474,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63673,7 +85577,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -63752,7 +85680,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -63830,7 +85782,25 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_upload_clang\"}"
+      properties:
+        '{'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_upload_clang"'
+        '}'
       execution_timeout_secs: 21600
       expiration_secs: 7200
       grace_period {
@@ -63909,7 +85879,31 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":false,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": false,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$kitchen": {'
+        '    "devshell": true,'
+        '    "git_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "tryserver.chromium.win",'
+        '  "recipe": "chromium_trybot"'
+        '}'
       execution_timeout_secs: 14400
       expiration_secs: 7200
       grace_period {
@@ -64001,7 +85995,28 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64025,7 +86040,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64049,7 +86079,28 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64073,7 +86124,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64098,7 +86164,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64122,7 +86208,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64146,7 +86247,28 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64170,7 +86292,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64194,7 +86331,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64218,7 +86370,22 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc\",\"perf_dashboard_machine_group\":\"ChromiumWebRTC\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc",'
+        '  "perf_dashboard_machine_group": "ChromiumWebRTC",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64258,7 +86425,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64282,7 +86469,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64306,7 +86513,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64330,7 +86557,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64354,7 +86595,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64378,7 +86633,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64402,7 +86677,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64426,7 +86721,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64451,7 +86760,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64476,7 +86804,26 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64500,7 +86847,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64524,7 +86885,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64548,7 +86929,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "enable_ats": true,'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64572,7 +86973,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64596,7 +87011,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64620,7 +87049,21 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"chromium\"}"
+      properties:
+        '{'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "chromium"'
+        '}'
       execution_timeout_secs: 7200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -64644,7 +87087,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"webrtc/chromium_ios\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "webrtc/chromium_ios",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 7200
       caches {
         name: "xcode_ios_12d4e"
@@ -64672,7 +87135,27 @@
         cipd_version: "refs/heads/master"
         cmd: "luciexe"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"$recipe_engine/resultdb/test_presentation\":{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]},\"builder_group\":\"chromium.webrtc.fyi\",\"recipe\":\"webrtc/chromium_ios\",\"xcode_build_version\":\"12d4e\"}"
+      properties:
+        '{'
+        '  "$build/goma": {'
+        '    "rpc_extra_params": "?prod",'
+        '    "server_host": "goma.chromium.org",'
+        '    "use_luci_auth": true'
+        '  },'
+        '  "$recipe_engine/isolated": {'
+        '    "server": "https://isolateserver.appspot.com"'
+        '  },'
+        '  "$recipe_engine/resultdb/test_presentation": {'
+        '    "column_keys": [],'
+        '    "grouping_keys": ['
+        '      "status",'
+        '      "v.test_suite"'
+        '    ]'
+        '  },'
+        '  "builder_group": "chromium.webrtc.fyi",'
+        '  "recipe": "webrtc/chromium_ios",'
+        '  "xcode_build_version": "12d4e"'
+        '}'
       execution_timeout_secs: 7200
       caches {
         name: "xcode_ios_12d4e"
diff --git a/infra/config/main.star b/infra/config/main.star
index 79cd1820..04a7385 100755
--- a/infra/config/main.star
+++ b/infra/config/main.star
@@ -10,7 +10,7 @@
 load("//project.star", "settings")
 
 lucicfg.check_version(
-    min = "1.23.6",
+    min = "1.27.0",
     message = "Update depot_tools",
 )
 
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 0df96ce..c5a23df 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -2009,6 +2009,10 @@
                 "cipd_yaml": "third_party/android_sdk/cipd/build-tools/30.0.1.yaml",
             },
             {
+                "sdk_package_name": "build-tools;31.0.0",
+                "cipd_yaml": "third_party/android_sdk/cipd/build-tools/31.0.0.yaml",
+            },
+            {
                 "sdk_package_name": "cmdline-tools;latest",
                 "cipd_yaml": "third_party/android_sdk/cipd/cmdline-tools.yaml",
             },
@@ -2029,6 +2033,10 @@
                 "cipd_yaml": "third_party/android_sdk/cipd/platforms/android-30.yaml",
             },
             {
+                "sdk_package_name": "platforms;android-31",
+                "cipd_yaml": "third_party/android_sdk/cipd/platforms/android-31.yaml",
+            },
+            {
                 "sdk_package_name": "platform-tools",
                 "cipd_yaml": "third_party/android_sdk/cipd/platform-tools.yaml",
             },
@@ -2036,11 +2044,15 @@
                 "sdk_package_name": "sources;android-29",
                 "cipd_yaml": "third_party/android_sdk/cipd/sources/android-29.yaml",
             },
-            # Not yet available as R is not released to AOSP.
-            #{
-            #    'sdk_package_name': 'sources;android-30',
-            #    'cipd_yaml': 'third_party/android_sdk/cipd/sources/android-30.yaml'
-            #},
+            {
+                "sdk_package_name": "sources;android-30",
+                "cipd_yaml": "third_party/android_sdk/cipd/sources/android-30.yaml",
+            },
+            # TODO(crbug.com/1223110): Enable once S is released to AOSP.
+            # {
+            #     "sdk_package_name": "sources;android-31",
+            #     "cipd_yaml": "third_party/android_sdk/cipd/sources/android-31.yaml",
+            # },
             {
                 "sdk_package_name": "system-images;android-23;google_apis;x86",
                 "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-23/google_apis/x86.yaml",
@@ -2077,16 +2089,14 @@
                 "sdk_package_name": "system-images;android-30;google_apis_playstore;x86",
                 "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-30/google_apis_playstore/x86.yaml",
             },
-            # Preview system images for Android S.
-            # Should be updated once it is fully released.
-            # sdkmanager don't have x86 for Android S so use x86_64 for now.
+            # sdkmanager don't have x86 for android-31 so use x86_64.
             {
-                "sdk_package_name": "system-images;android-S;google_apis;x86_64",
-                "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-S/google_apis/x86_64.yaml",
+                "sdk_package_name": "system-images;android-31;google_apis;x86_64",
+                "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-31/google_apis/x86_64.yaml",
             },
             {
-                "sdk_package_name": "system-images;android-S;google_apis_playstore;x86_64",
-                "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-S/google_apis_playstore/x86_64.yaml",
+                "sdk_package_name": "system-images;android-31;google_apis_playstore;x86_64",
+                "cipd_yaml": "third_party/android_sdk/cipd/system_images/android-31/google_apis_playstore/x86_64.yaml",
             },
         ],
     },
@@ -3771,6 +3781,7 @@
     goma_jobs = 250,
     executable = "recipe:reclient_goma_comparison",
     execution_timeout = 6 * time.hour,
+    reclient_rewrapper_env = {"RBE_cache_silo": "Comparison Linux - cache siloed"},
     reclient_instance = rbe_instance.DEFAULT,
     reclient_jobs = 250,
     configure_kitchen = True,
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 5e906286..8f07c69 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -390,6 +390,7 @@
     main_list_view = "try",
     ssd = True,
     use_java_coverage = True,
+    coverage_test_types = ["unit", "overall"],
     tryjob = try_.job(),
     # TODO(crbug/1202741)
     os = os.LINUX_XENIAL_OR_BIONIC_REMOVE,
diff --git a/ios/chrome/browser/device_sharing/device_sharing_browser_agent.h b/ios/chrome/browser/device_sharing/device_sharing_browser_agent.h
index 2fe44d1..fe6600e 100644
--- a/ios/chrome/browser/device_sharing/device_sharing_browser_agent.h
+++ b/ios/chrome/browser/device_sharing/device_sharing_browser_agent.h
@@ -54,6 +54,9 @@
   void DidFinishNavigation(web::WebState* web_state,
                            web::NavigationContext* navigation_context) override;
 
+  // web::WebStateObserver
+  void TitleWasSet(web::WebState* web_state) override;
+
   // The Browser this agent is associated with.
   Browser* browser_;
   // Whether the browser state assoicated with |browser_| is inocgnito or not.
diff --git a/ios/chrome/browser/device_sharing/device_sharing_browser_agent.mm b/ios/chrome/browser/device_sharing/device_sharing_browser_agent.mm
index d45ae7e..cc1bcc9a 100644
--- a/ios/chrome/browser/device_sharing/device_sharing_browser_agent.mm
+++ b/ios/chrome/browser/device_sharing/device_sharing_browser_agent.mm
@@ -50,6 +50,7 @@
       browser_->GetWebStateList()->GetActiveWebState();
   if (active_web_state) {
     manager->UpdateActiveUrl(browser_, active_web_state->GetVisibleURL());
+    manager->UpdateActiveTitle(browser_, active_web_state->GetTitle());
     return;
   }
 
@@ -88,3 +89,7 @@
     web::NavigationContext* navigation_context) {
   UpdateForActiveWebState();
 }
+
+void DeviceSharingBrowserAgent::TitleWasSet(web::WebState* web_state) {
+  UpdateForActiveWebState();
+}
diff --git a/ios/chrome/browser/device_sharing/device_sharing_manager.h b/ios/chrome/browser/device_sharing/device_sharing_manager.h
index 3b24ede..6baeb7e 100644
--- a/ios/chrome/browser/device_sharing/device_sharing_manager.h
+++ b/ios/chrome/browser/device_sharing/device_sharing_manager.h
@@ -5,6 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_DEVICE_SHARING_DEVICE_SHARING_MANAGER_H_
 #define IOS_CHROME_BROWSER_DEVICE_SHARING_DEVICE_SHARING_MANAGER_H_
 
+#include <string>
+
 #include "components/keyed_service/core/keyed_service.h"
 
 class Browser;
@@ -25,7 +27,12 @@
   // If |browser| is not the active browser, do nothing.
   virtual void UpdateActiveUrl(Browser* browser, const GURL& active_url) = 0;
 
-  // If |browser| is the active browser, clear the active URL.
+  // If |browser| is the active browser, set |active_title| as the active
+  // page title. If |browser| is not the active browser, do nothing.
+  virtual void UpdateActiveTitle(Browser* browser,
+                                 const std::u16string& active_title) = 0;
+
+  // If |browser| is the active browser, clear the active URL and title.
   // If |browser| is not the active browser, do nothing.
   virtual void ClearActiveUrl(Browser* browser) = 0;
 };
diff --git a/ios/chrome/browser/device_sharing/device_sharing_manager_impl.h b/ios/chrome/browser/device_sharing/device_sharing_manager_impl.h
index f244074c..6918a5e 100644
--- a/ios/chrome/browser/device_sharing/device_sharing_manager_impl.h
+++ b/ios/chrome/browser/device_sharing/device_sharing_manager_impl.h
@@ -26,6 +26,8 @@
 
   void SetActiveBrowser(Browser* browser) override;
   void UpdateActiveUrl(Browser* browser, const GURL& active_url) override;
+  void UpdateActiveTitle(Browser* browser,
+                         const std::u16string& title) override;
   void ClearActiveUrl(Browser* browser) override;
 
  private:
diff --git a/ios/chrome/browser/device_sharing/device_sharing_manager_impl.mm b/ios/chrome/browser/device_sharing/device_sharing_manager_impl.mm
index 14607f0..f487805 100644
--- a/ios/chrome/browser/device_sharing/device_sharing_manager_impl.mm
+++ b/ios/chrome/browser/device_sharing/device_sharing_manager_impl.mm
@@ -26,6 +26,7 @@
                           base::Unretained(this)));
   UpdateHandoffManager();
   [handoff_manager_ updateActiveURL:GURL()];
+  [handoff_manager_ updateActiveTitle:std::u16string()];
 }
 
 DeviceSharingManagerImpl::~DeviceSharingManagerImpl() {}
@@ -47,11 +48,20 @@
   [handoff_manager_ updateActiveURL:active_url];
 }
 
+void DeviceSharingManagerImpl::UpdateActiveTitle(Browser* browser,
+                                                 const std::u16string& title) {
+  if (browser != active_browser_)
+    return;
+
+  [handoff_manager_ updateActiveTitle:title];
+}
+
 void DeviceSharingManagerImpl::ClearActiveUrl(Browser* browser) {
   if (browser != active_browser_)
     return;
 
   [handoff_manager_ updateActiveURL:GURL()];
+  [handoff_manager_ updateActiveTitle:std::u16string()];
 }
 
 void DeviceSharingManagerImpl::UpdateHandoffManager() {
diff --git a/ios/chrome/browser/download/background_service/BUILD.gn b/ios/chrome/browser/download/background_service/BUILD.gn
index 0fcc544..7719292 100644
--- a/ios/chrome/browser/download/background_service/BUILD.gn
+++ b/ios/chrome/browser/download/background_service/BUILD.gn
@@ -9,6 +9,7 @@
   ]
 
   deps = [
+    "//components/download/internal/background_service:common",
     "//components/download/internal/background_service:storage",
     "//components/download/internal/background_service/ios:background_service",
     "//components/download/internal/background_service/proto",
diff --git a/ios/chrome/browser/download/background_service/background_download_service_factory.cc b/ios/chrome/browser/download/background_service/background_download_service_factory.cc
index a418e8b..b79c256 100644
--- a/ios/chrome/browser/download/background_service/background_download_service_factory.cc
+++ b/ios/chrome/browser/download/background_service/background_download_service_factory.cc
@@ -8,6 +8,7 @@
 
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "components/download/internal/background_service/client_set.h"
 #include "components/download/internal/background_service/download_store.h"
 #include "components/download/internal/background_service/ios/background_download_service_impl.h"
 #include "components/download/internal/background_service/ios/background_download_task_helper.h"
@@ -57,6 +58,7 @@
 BackgroundDownloadServiceFactory::BuildServiceInstanceFor(
     web::BrowserState* context) const {
   auto clients = std::make_unique<download::DownloadClientMap>();
+  auto client_set = std::make_unique<download::ClientSet>(std::move(clients));
   base::FilePath storage_dir =
       context->GetStatePath().Append(kDownloadServiceStorageDir);
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
@@ -68,7 +70,7 @@
   auto store = std::make_unique<download::DownloadStore>(std::move(entry_db));
   auto model = std::make_unique<download::ModelImpl>(std::move(store));
   return std::make_unique<download::BackgroundDownloadServiceImpl>(
-      std::move(clients), std::move(model),
+      std::move(client_set), std::move(model),
       download::BackgroundDownloadTaskHelper::Create(
           storage_dir.Append(kFilesStorageDir)));
 }
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/add_to_reading_list_modal_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/add_to_reading_list_modal_infobar_interaction_handler.mm
index f3d811e..d4b029b 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/add_to_reading_list_modal_infobar_interaction_handler.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/add_to_reading_list_modal_infobar_interaction_handler.mm
@@ -23,7 +23,8 @@
 #pragma mark - Public
 
 void ReadingListInfobarModalInteractionHandler::NeverAsk(InfoBarIOS* infobar) {
-  // TODO(crbug.com/1195978): Save Never Ask pref.
+  IOSAddToReadingListInfobarDelegate* delegate = GetDelegate(infobar);
+  delegate->NeverShow();
 
   // Remove infobar.
   infobar->RemoveSelf();
diff --git a/ios/chrome/browser/policy/enterprise_policy_test_helper.cc b/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
index 7fe7e1d..e90da1f0 100644
--- a/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
+++ b/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
@@ -18,11 +18,9 @@
 
 EnterprisePolicyTestHelper::EnterprisePolicyTestHelper(
     const base::FilePath& state_directory_path) {
-  ON_CALL(policy_provider_, IsInitializationComplete(testing::_))
-      .WillByDefault(testing::Return(true));
-  ON_CALL(policy_provider_, IsFirstPolicyLoadComplete(testing::_))
-      .WillByDefault(testing::Return(true));
-
+  policy_provider_.SetDefaultReturns(
+      true /* is_initialization_complete_return */,
+      true /* is_first_policy_load_complete_return */);
   // Create a BrowserPolicyConnectorIOS, install the mock policy
   // provider, and hook up Local State.
   browser_policy_connector_ =
diff --git a/ios/chrome/browser/policy/enterprise_policy_test_helper.h b/ios/chrome/browser/policy/enterprise_policy_test_helper.h
index cf41b97..77ff103 100644
--- a/ios/chrome/browser/policy/enterprise_policy_test_helper.h
+++ b/ios/chrome/browser/policy/enterprise_policy_test_helper.h
@@ -36,7 +36,7 @@
 
  private:
   // The enterprise configuration policy provider.
-  policy::MockConfigurationPolicyProvider policy_provider_;
+  testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
   // The application-level policy connector. Must outlive |local_state_|.
   std::unique_ptr<BrowserPolicyConnectorIOS> browser_policy_connector_;
   // The local state PrefService managed by policy.
diff --git a/ios/chrome/browser/policy/test_platform_policy_provider.cc b/ios/chrome/browser/policy/test_platform_policy_provider.cc
index be920c41..748694c 100644
--- a/ios/chrome/browser/policy/test_platform_policy_provider.cc
+++ b/ios/chrome/browser/policy/test_platform_policy_provider.cc
@@ -7,13 +7,11 @@
 #include "base/no_destructor.h"
 
 policy::MockConfigurationPolicyProvider* GetTestPlatformPolicyProvider() {
-  static base::NoDestructor<policy::MockConfigurationPolicyProvider> provider;
+  static base::NoDestructor<
+      testing::NiceMock<policy::MockConfigurationPolicyProvider>>
+      provider;
   provider->SetAutoRefresh();
-  EXPECT_CALL(*provider.get(), IsInitializationComplete(testing::_))
-      .Times(testing::AnyNumber())
-      .WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(*provider.get(), IsFirstPolicyLoadComplete(testing::_))
-      .Times(testing::AnyNumber())
-      .WillRepeatedly(testing::Return(true));
+  provider->SetDefaultReturns(true /* is_initialization_complete_return */,
+                              true /* is_first_policy_load_complete_return */);
   return provider.get();
 }
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn
index 89efb1f..f614c2bf 100644
--- a/ios/chrome/browser/prefs/BUILD.gn
+++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -87,6 +87,8 @@
     "//ios/chrome/browser/ui/content_suggestions",
     "//ios/chrome/browser/ui/first_run:field_trial",
     "//ios/chrome/browser/ui/incognito_reauth:incognito_reauth_scene_agent",
+    "//ios/chrome/browser/ui/reading_list:features",
+    "//ios/chrome/browser/ui/reading_list:reading_list_constants",
     "//ios/chrome/browser/voice:prefs",
     "//ios/chrome/browser/web",
     "//ios/chrome/browser/web/font_size",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 239812d..b49244f 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -71,6 +71,8 @@
 #include "ios/chrome/browser/ui/first_run/fre_field_trial.h"
 #import "ios/chrome/browser/ui/first_run/location_permissions_field_trial.h"
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_constants.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_features.h"
 #include "ios/chrome/browser/voice/voice_search_prefs_registration.h"
 #import "ios/chrome/browser/web/font_size/font_size_tab_helper.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
@@ -266,6 +268,10 @@
   registry->RegisterIntegerPref(kPasswordManagerOnboardingState, 0);
   registry->RegisterBooleanPref(kWasOnboardingFeatureCheckedBefore, false);
   registry->RegisterDictionaryPref(kDomainsWithCookiePref);
+
+  if (IsReadingListMessagesEnabled()) {
+    registry->RegisterBooleanPref(kPrefReadingListMessagesNeverShow, false);
+  }
 }
 
 // This method should be periodically pruned of year+ old migrations.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
index 2a7a5f2..1152b48 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
@@ -574,7 +574,8 @@
 }
 
 // Tests that the manual fallback view is not duplicated after incognito.
-- (void)testReturningFromIncognitoDoesNotDuplicatesManualFallbackMenu {
+// TODO(crbug.com/1228283): Disabled due to flakiness.
+- (void)DISABLED_testReturningFromIncognitoDoesNotDuplicatesManualFallbackMenu {
   // Add the profile to use for verification.
   [AutofillAppInterface saveExampleProfile];
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credit_card+CreditCard.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credit_card+CreditCard.mm
index 4ed0c0e..0a34992 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credit_card+CreditCard.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_credit_card+CreditCard.mm
@@ -41,9 +41,9 @@
   constexpr char16_t separator[] = {0x2060, 0x0020, 0};
   const std::u16string digits = creditCard.LastFourDigits();
   NSString* obfuscatedNumber = base::SysUTF16ToNSString(
-      autofill::kMidlineEllipsis + std::u16string(separator) +
-      autofill::kMidlineEllipsis + std::u16string(separator) +
-      autofill::kMidlineEllipsis + std::u16string(separator) + digits);
+      autofill::kMidlineEllipsis4Dots + std::u16string(separator) +
+      autofill::kMidlineEllipsis4Dots + std::u16string(separator) +
+      autofill::kMidlineEllipsis4Dots + std::u16string(separator) + digits);
 
   // Use 2 digits year.
   NSString* expirationYear =
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
index 8da3597..cdebd9a 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
@@ -100,10 +100,11 @@
     config.features_enabled.push_back(
         password_manager::features::kEnableManualPasswordGeneration);
   }
-  if ([self isRunningTest:@selector(testPasswordControllerKeepsRightSize)]) {
-    config.features_disabled.push_back(
-        password_manager::features::kEnableManualPasswordGeneration);
-  }
+  // TODO(crbug.com/1226894): Uncomment this once the test is fixed.
+  // if ([self isRunningTest:@selector(testPasswordControllerKeepsRightSize)]) {
+  //   config.features_disabled.push_back(
+  //       password_manager::features::kEnableManualPasswordGeneration);
+  // }
   return config;
 }
 
@@ -510,7 +511,8 @@
 
 // Tests that after switching fields the content size of the table view didn't
 // grow.
-- (void)testPasswordControllerKeepsRightSize {
+// TODO(crbug.com/1226894): Disabled due to flakiness.
+- (void)DISABLED_testPasswordControllerKeepsRightSize {
   // Bring up the keyboard.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
       performAction:TapWebElementWithId(kFormElementUsername)];
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index eb42f137..c0ffc9a 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -4650,7 +4650,7 @@
     translate::TranslateManager* translateManager =
         translateClient->GetTranslateManager();
     DCHECK(translateManager);
-    translateManager->InitiateManualTranslation(/*auto_translate=*/true);
+    translateManager->ShowTranslateUI(/*auto_translate=*/true);
   }
 }
 
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn
index 7fe25b4..a36102e8 100644
--- a/ios/chrome/browser/ui/dialogs/BUILD.gn
+++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -42,8 +42,6 @@
 source_set("dialogs_internal") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "java_script_dialog_metrics.cc",
-    "java_script_dialog_metrics.h",
     "nsurl_protection_space_util.h",
     "nsurl_protection_space_util.mm",
     "overlay_java_script_dialog_presenter.h",
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.cc b/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.cc
deleted file mode 100644
index fff6a89..0000000
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2019 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 "ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h"
-
-#include "base/metrics/histogram_macros.h"
-
-// Records a histogram for a dialog dismissal for |cause|.
-void RecordDialogDismissalCause(IOSJavaScriptDialogDismissalCause cause) {
-  UMA_HISTOGRAM_ENUMERATION("IOS.Dialogs.JavaScriptDialogClosed", cause);
-}
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h b/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h
deleted file mode 100644
index 3567007b..0000000
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 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 IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_METRICS_H_
-#define IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_METRICS_H_
-
-// Possible reasons for JavaScript dialog dismissals.  These values are
-// persisted to logs. Entries should not be renumbered and numeric values should
-// never be reused.
-enum class IOSJavaScriptDialogDismissalCause {
-  // The tab was closed while a JavaScript dialog was displayed.
-  kClosure = 0,
-  // The user taps the OK, Cancel, or Suppress Dialogs button.
-  kUser = 1,
-  // The dialog was blocked by the Suppress Dialog option.
-  kBlocked = 2,
-  // The dialog was closed due to navigation.
-  kNavigation = 3,
-
-  kMaxValue = kNavigation,
-};
-
-// Records a histogram for a dialog dismissal for |cause|.
-void RecordDialogDismissalCause(IOSJavaScriptDialogDismissalCause cause);
-
-#endif  // IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_METRICS_H_
diff --git a/ios/chrome/browser/ui/dialogs/overlay_java_script_dialog_presenter.mm b/ios/chrome/browser/ui/dialogs/overlay_java_script_dialog_presenter.mm
index 58bc5226..cfb9a19 100644
--- a/ios/chrome/browser/ui/dialogs/overlay_java_script_dialog_presenter.mm
+++ b/ios/chrome/browser/ui/dialogs/overlay_java_script_dialog_presenter.mm
@@ -13,7 +13,6 @@
 #import "ios/chrome/browser/overlays/public/overlay_response.h"
 #import "ios/chrome/browser/overlays/public/web_content_area/java_script_dialog_overlay.h"
 #import "ios/chrome/browser/ui/dialogs/java_script_dialog_blocking_state.h"
-#include "ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h"
 #import "ios/web/public/web_state.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -41,10 +40,6 @@
   if (!dialog_response) {
     // A null response is used if the dialog was not closed by user interaction.
     // This occurs either for navigation or because of WebState closures.
-    IOSJavaScriptDialogDismissalCause cause =
-        web_state ? IOSJavaScriptDialogDismissalCause::kNavigation
-                  : IOSJavaScriptDialogDismissalCause::kClosure;
-    RecordDialogDismissalCause(cause);
     std::move(callback).Run(/*success=*/false, /*user_input=*/nil);
     return;
   }
@@ -56,7 +51,6 @@
     blocking_state->JavaScriptDialogBlockingOptionSelected();
   }
 
-  RecordDialogDismissalCause(IOSJavaScriptDialogDismissalCause::kUser);
   bool confirmed = action == JavaScriptDialogResponse::Action::kConfirm;
   NSString* user_input = confirmed ? dialog_response->user_input() : nil;
   std::move(callback).Run(confirmed, user_input);
@@ -83,7 +77,6 @@
   JavaScriptDialogBlockingState::CreateForWebState(web_state);
   if (JavaScriptDialogBlockingState::FromWebState(web_state)->blocked()) {
     // Block the dialog if needed.
-    RecordDialogDismissalCause(IOSJavaScriptDialogDismissalCause::kBlocked);
     std::move(callback).Run(NO, nil);
     return;
   }
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn
index 54db023..1a209a5 100644
--- a/ios/chrome/browser/ui/first_run/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -84,7 +84,6 @@
     "//ios/chrome/browser/ui/first_run/sync",
     "//ios/chrome/browser/ui/first_run/welcome",
     "//ios/chrome/browser/ui/settings/resources:enterprise_icon",
-    "//ios/chrome/browser/ui/settings/sync/utils",
     "//ios/chrome/browser/ui/settings/utils",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/util:terms_util",
diff --git a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
index 3e3e227..e255077 100644
--- a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
@@ -19,7 +19,6 @@
 #import "ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/welcome/welcome_screen_coordinator.h"
-#import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -76,11 +75,6 @@
   void (^completion)(void) = ^{
     base::UmaHistogramEnumeration("FirstRun.Stage", first_run::kComplete);
     WriteFirstRunSentinel();
-    // Display the sync errors infobar.
-    web::WebState* webState =
-        self.browser->GetWebStateList()->GetActiveWebState();
-    DisplaySyncErrors(self.browser->GetBrowserState(), webState,
-                      self.presenter);
 
     // If the remaining screens have been skipped, additional actions will be
     // executed.
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index b325381..840c0e4 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -90,6 +90,7 @@
     "//base",
     "//components/dom_distiller/core",
     "//components/infobars/core",
+    "//components/prefs",
     "//components/reading_list/core",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
@@ -120,8 +121,10 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   deps = [
     "//components/infobars/core",
+    "//components/prefs",
     "//components/reading_list/core",
     "//components/ukm/ios:ukm_url_recorder",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/ui/reading_list:reading_list_constants",
     "//ios/web/public",
     "//services/metrics/public/cpp:ukm_builders",
@@ -175,6 +178,7 @@
     "resources:reading_list_tools_icon",
     "//base",
     "//base:i18n",
+    "//components/prefs",
     "//components/reading_list/core",
     "//components/strings",
     "//components/url_formatter",
diff --git a/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h b/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h
index bdf5822f..55a6fd39 100644
--- a/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h
+++ b/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h
@@ -45,6 +45,9 @@
   // ConfirmInfoBarDelegate implementation.
   bool Accept() override;
 
+  // If called, sets the pref to never show the Reading List Message.
+  void NeverShow();
+
  private:
   // The URL of the page to be saved to Reading List.
   GURL url_;
diff --git a/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.mm b/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.mm
index 73799b7..fd90285 100644
--- a/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.mm
+++ b/ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.mm
@@ -9,8 +9,10 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/infobars/core/infobar.h"
+#include "components/prefs/pref_service.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "components/ukm/ios/ukm_url_recorder.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_constants.h"
 #import "ios/web/public/web_state.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
@@ -70,3 +72,10 @@
        forKey:kLastReadingListEntryAddedFromMessages];
   return true;
 }
+
+void IOSAddToReadingListInfobarDelegate::NeverShow() {
+  ChromeBrowserState* browser_state =
+      ChromeBrowserState::FromBrowserState(web_state_->GetBrowserState());
+  PrefService* user_prefs = browser_state->GetPrefs();
+  user_prefs->SetBoolean(kPrefReadingListMessagesNeverShow, true);
+}
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_constants.h b/ios/chrome/browser/ui/reading_list/reading_list_constants.h
index 3f4143a..ace459f 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_constants.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_constants.h
@@ -27,4 +27,7 @@
 extern NSString* const kShouldAnimateReadingListOverflowMenuUnreadCountBadge;
 extern CGFloat const kReadingListUnreadCountBadgeAnimationDuration;
 
+// ChromeBrowserState pref key to never show the Reading List Message prompt.
+extern const char kPrefReadingListMessagesNeverShow[];
+
 #endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_constants.mm b/ios/chrome/browser/ui/reading_list/reading_list_constants.mm
index c19ecfe..fc984e4 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_constants.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_constants.mm
@@ -33,3 +33,6 @@
 NSString* const kShouldAnimateReadingListOverflowMenuUnreadCountBadge =
     @"ShouldAnimateReadingListOverflowMenuUnreadCountBadge";
 CGFloat const kReadingListUnreadCountBadgeAnimationDuration = 0.3;
+
+const char kPrefReadingListMessagesNeverShow[] =
+    "reading_list_message_never_show";
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_javascript_feature.mm b/ios/chrome/browser/ui/reading_list/reading_list_javascript_feature.mm
index 998ed842..11c8787 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_javascript_feature.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_javascript_feature.mm
@@ -11,6 +11,7 @@
 #include "components/dom_distiller/core/distillable_page_detector.h"
 #include "components/dom_distiller/core/page_features.h"
 #include "components/infobars/core/infobar_manager.h"
+#include "components/prefs/pref_service.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/chrome_url_util.h"
@@ -174,6 +175,15 @@
     // entry.
     return;
   }
+  ChromeBrowserState* browser_state =
+      ChromeBrowserState::FromBrowserState(web_state->GetBrowserState());
+  PrefService* user_prefs = browser_state->GetPrefs();
+  bool neverShowPrefSet =
+      user_prefs->GetBoolean(kPrefReadingListMessagesNeverShow);
+  if (neverShowPrefSet) {
+    // Do not show prompt if user explicitly selected to never show it.
+    return;
+  }
 
   infobars::InfoBarManager* manager =
       InfoBarManagerImpl::FromWebState(web_state);
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
index e21773c..ad3317e5 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -11,8 +11,10 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/app/tests_hook.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/drag_and_drop/drag_item_util.h"
 #import "ios/chrome/browser/drag_and_drop/table_view_url_drag_drop_handler.h"
 #import "ios/chrome/browser/main/browser.h"
@@ -258,6 +260,10 @@
     DCHECK(IsReadingListMessagesEnabled());
     SettingsSwitchCell* switchCell =
         base::mac::ObjCCastStrict<SettingsSwitchCell>(cell);
+    PrefService* user_prefs = self.browser->GetBrowserState()->GetPrefs();
+    BOOL neverShowPrefSet =
+        user_prefs->GetBoolean(kPrefReadingListMessagesNeverShow);
+    switchCell.switchView.on = !neverShowPrefSet;
     [switchCell.switchView addTarget:self
                               action:@selector(switchAction:)
                     forControlEvents:UIControlEventValueChanged];
@@ -299,8 +305,10 @@
 #pragma mark - SettingsSwitchCell action
 
 - (void)switchAction:(UISwitch*)sender {
-  // TODO(crbug.com/1195978): Log metric to indicate toggle. Toggle Reading List
-  // Browser Pref.
+  // TODO(crbug.com/1195978): Log metric to indicate toggle.
+  PrefService* user_prefs = self.browser->GetBrowserState()->GetPrefs();
+  BOOL neverShowPrompt = ![sender isOn];
+  user_prefs->SetBoolean(kPrefReadingListMessagesNeverShow, neverShowPrompt);
 }
 
 #pragma mark - UITableViewDelegate
diff --git a/ios/chrome/browser/variations/BUILD.gn b/ios/chrome/browser/variations/BUILD.gn
index d4e4cf7a..3037df2d 100644
--- a/ios/chrome/browser/variations/BUILD.gn
+++ b/ios/chrome/browser/variations/BUILD.gn
@@ -42,3 +42,55 @@
   header_filename = "ios_ui_string_overrider_factory.h"
   source_filename = "ios_ui_string_overrider_factory.cc"
 }
+
+source_set("eg_app_support+eg2") {
+  defines = [ "CHROME_EARL_GREY_2" ]
+  configs += [
+    "//build/config/compiler:enable_arc",
+    "//build/config/ios:xctest_config",
+  ]
+  testonly = true
+  sources = [
+    "variations_app_interface.h",
+    "variations_app_interface.mm",
+  ]
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//components/metrics",
+    "//components/prefs",
+    "//components/variations",
+    "//components/variations:test_support",
+    "//ios/chrome/browser",
+    "//ios/chrome/test/app:test_support",
+  ]
+}
+
+source_set("eg_test_support+eg2") {
+  defines = [ "CHROME_EARL_GREY_2" ]
+  configs += [
+    "//build/config/compiler:enable_arc",
+    "//build/config/ios:xctest_config",
+  ]
+  testonly = true
+  sources = [ "variations_app_interface.h" ]
+}
+
+source_set("eg2_tests") {
+  defines = [ "CHROME_EARL_GREY_2" ]
+  configs += [
+    "//build/config/compiler:enable_arc",
+    "//build/config/ios:xctest_config",
+  ]
+  testonly = true
+  sources = [ "variations_safe_mode_egtest.mm" ]
+  deps = [
+    ":eg_test_support+eg2",
+    "//base",
+    "//base/test:test_support",
+    "//ios/chrome/test/earl_grey:eg_test_support+eg2",
+    "//ios/testing/earl_grey:eg_test_support+eg2",
+    "//ios/third_party/earl_grey2:test_lib",
+  ]
+  frameworks = [ "UIKit.framework" ]
+}
diff --git a/ios/chrome/browser/variations/variations_app_interface.h b/ios/chrome/browser/variations/variations_app_interface.h
new file mode 100644
index 0000000..a545579
--- /dev/null
+++ b/ios/chrome/browser/variations/variations_app_interface.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_VARIATIONS_VARIATIONS_APP_INTERFACE_H_
+#define IOS_CHROME_BROWSER_VARIATIONS_VARIATIONS_APP_INTERFACE_H_
+
+#import <Foundation/Foundation.h>
+
+// The app interface for variations tests.
+@interface VariationsAppInterface : NSObject
+
+// Clears all local state variations prefs.
++ (void)clearVariationsPrefs;
+
+// Returns true if there is a field trial for the test seed study.
++ (BOOL)fieldTrialExistsForTestSeed;
+
+// Returns true if the variations safe seed pref is set.
++ (BOOL)hasSafeSeed;
+
+// Sets a test safe seed and signature pair.
++ (void)setTestSafeSeedAndSignature;
+
+// Returns the value of the variations crash streak pref.
++ (int)crashStreak;
+
+// Sets the variations crash streak pref to |value|.
++ (void)setCrashValue:(int)value;
+
+// Returns the value of the variations failed fetch streak pref.
++ (int)failedFetchStreak;
+
+// Sets the variations fetch failure pref to |value|.
++ (void)setFetchFailureValue:(int)value;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_VARIATIONS_VARIATIONS_APP_INTERFACE_H_
diff --git a/ios/chrome/browser/variations/variations_app_interface.mm b/ios/chrome/browser/variations/variations_app_interface.mm
new file mode 100644
index 0000000..716dc9a
--- /dev/null
+++ b/ios/chrome/browser/variations/variations_app_interface.mm
@@ -0,0 +1,97 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/variations/variations_app_interface.h"
+
+#include <string>
+
+#include "base/metrics/field_trial.h"
+#include "components/prefs/pref_service.h"
+#include "components/variations/pref_names.h"
+#include "components/variations/variations_test_utils.h"
+#include "ios/chrome/browser/application_context.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation VariationsAppInterface
+
++ (void)clearVariationsPrefs {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+
+  // Clear variations seed prefs.
+  prefService->ClearPref(variations::prefs::kVariationsCompressedSeed);
+  prefService->ClearPref(variations::prefs::kVariationsCountry);
+  prefService->ClearPref(variations::prefs::kVariationsLastFetchTime);
+  prefService->ClearPref(
+      variations::prefs::kVariationsPermanentConsistencyCountry);
+  prefService->ClearPref(
+      variations::prefs::kVariationsPermanentOverriddenCountry);
+  prefService->ClearPref(variations::prefs::kVariationsSeedDate);
+  prefService->ClearPref(variations::prefs::kVariationsSeedSignature);
+
+  // Clear variations safe seed prefs.
+  prefService->ClearPref(variations::prefs::kVariationsSafeCompressedSeed);
+  prefService->ClearPref(variations::prefs::kVariationsSafeSeedDate);
+  prefService->ClearPref(variations::prefs::kVariationsSafeSeedFetchTime);
+  prefService->ClearPref(variations::prefs::kVariationsSafeSeedLocale);
+  prefService->ClearPref(
+      variations::prefs::kVariationsSafeSeedPermanentConsistencyCountry);
+  prefService->ClearPref(
+      variations::prefs::kVariationsSafeSeedSessionConsistencyCountry);
+  prefService->ClearPref(variations::prefs::kVariationsSafeSeedSignature);
+
+  // Clear variations policy prefs.
+  prefService->ClearPref(variations::prefs::kVariationsRestrictionsByPolicy);
+  prefService->ClearPref(variations::prefs::kVariationsRestrictParameter);
+
+  // Clear prefs that may trigger variations safe mode.
+  prefService->ClearPref(variations::prefs::kVariationsCrashStreak);
+  prefService->ClearPref(variations::prefs::kVariationsFailedToFetchSeedStreak);
+}
+
++ (BOOL)fieldTrialExistsForTestSeed {
+  return base::FieldTrialList::TrialExists(variations::kTestSeedStudyName);
+}
+
++ (BOOL)hasSafeSeed {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  const std::string& safe_seed =
+      prefService->GetString(variations::prefs::kVariationsSafeCompressedSeed);
+  return !safe_seed.empty();
+}
+
++ (void)setTestSafeSeedAndSignature {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  prefService->SetString(variations::prefs::kVariationsSafeCompressedSeed,
+                         variations::kCompressedBase64TestSeedData);
+  prefService->SetString(variations::prefs::kVariationsSafeSeedSignature,
+                         variations::kBase64TestSeedSignature);
+}
+
++ (int)crashStreak {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  return prefService->GetInteger(variations::prefs::kVariationsCrashStreak);
+}
+
++ (void)setCrashValue:(int)value {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  prefService->SetInteger(variations::prefs::kVariationsCrashStreak, value);
+}
+
++ (int)failedFetchStreak {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  return prefService->GetInteger(
+      variations::prefs::kVariationsFailedToFetchSeedStreak);
+}
+
++ (void)setFetchFailureValue:(int)value {
+  PrefService* prefService = GetApplicationContext()->GetLocalState();
+  prefService->SetInteger(variations::prefs::kVariationsFailedToFetchSeedStreak,
+                          value);
+}
+
+@end
diff --git a/ios/chrome/browser/variations/variations_safe_mode_egtest.mm b/ios/chrome/browser/variations/variations_safe_mode_egtest.mm
new file mode 100644
index 0000000..73f3dbd
--- /dev/null
+++ b/ios/chrome/browser/variations/variations_safe_mode_egtest.mm
@@ -0,0 +1,208 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/variations/variations_app_interface.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/testing/earl_grey/app_launch_manager.h"
+#import "ios/testing/earl_grey/earl_grey_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// TODO(crbug.com/1015113): The EG2 macro is breaking indexing for some reason
+// without the trailing semicolon. For now, disable the extra semi warning
+// so that Xcode indexing works for the egtest.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
+GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(VariationsAppInterface);
+#pragma clang diagnostic pop
+
+@interface VariationsSafeModeTestCase : ChromeTestCase
+@end
+
+@implementation VariationsSafeModeTestCase
+
+- (void)setUp {
+  [super setUp];
+  // Clear local state variations prefs since local state is persisted between
+  // EG tests. See crbug.com/1069086.
+  [VariationsAppInterface clearVariationsPrefs];
+}
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config;
+  config.additional_args = {"--disable-field-trial-config"};
+  return config;
+}
+
+#pragma mark - Helpers
+
+// Returns an AppLaunchConfiguration that shuts down Chrome cleanly and
+// relaunches it without using the field trial testing config. Shutting down
+// cleanly flushes local state. Disabling the testing config means that the only
+// field trials after the relaunch, if any, are client-side field trials.
+- (AppLaunchConfiguration)appConfigForPersistingPrefs {
+  AppLaunchConfiguration config;
+  config.relaunch_policy = ForceRelaunchByCleanShutdown;
+  config.additional_args = {"--disable-field-trial-config"};
+  return config;
+}
+
+// Returns an AppLaunchConfiguration that crashes and relaunches Chrome. The
+// config also disables the use of the field trial testing config so that
+// VariationsFieldTrialCreator::CreateTrialsFromSeed() executes and determines
+// whether to use variations safe mode. See the comment above
+// appConfigForPersistingPrefs for more info on disabling the testing config.
+- (AppLaunchConfiguration)appConfigForCrashing {
+  AppLaunchConfiguration config;
+  config.relaunch_policy = ForceRelaunchByKilling;
+  config.additional_args = {"--disable-field-trial-config"};
+  return config;
+}
+
+// Checks that the variations crash streak is |value|.
+- (void)checkCrashStreakValue:(int)value {
+  int actualStreak = [VariationsAppInterface crashStreak];
+  GREYAssertEqual(actualStreak, value,
+                  @"Expected a crash streak of %d, but got %d", value,
+                  actualStreak);
+}
+
+// Checks that the variations failed fetch streak is |value|.
+- (void)checkFailedFetchStreakValue:(int)value {
+  int actualStreak = [VariationsAppInterface failedFetchStreak];
+  GREYAssertEqual(actualStreak, value,
+                  @"Expected a failed fetch streak of %d, but got %d", value,
+                  actualStreak);
+}
+
+#pragma mark - Tests
+
+// The tests in this file should roughly correspond to the tests in
+// chrome/browser/metrics/variations/variations_safe_mode_browsertest.cc.
+// "Roughly" because there is a significant difference between the tests.
+//
+// The browser tests use a HistogramTester to check if Chrome is running in safe
+// mode while the EG tests use the existence of a field trial associated with
+// the test safe seed's sole study. HistogramTesters are not an option in EG
+// tests because ensureAppLaunchedWithConfiguration() both shuts down and
+// relaunches Chrome. It is not possible to initialize a HistogramTester until
+// after the startup code under test has executed. Initializing a
+// HistogramTester before shutting down Chrome isn't helpful because the
+// tester is not persisted across sessions.
+
+// Tests that three crashes trigger variations safe mode.
+//
+// Corresponds to VariationsSafeModeBrowserTest.ThreeCrashesTriggerSafeMode in
+// variations_safe_mode_browsertest.cc.
+- (void)testThreeCrashesTriggerSafeMode {
+  [VariationsAppInterface setTestSafeSeedAndSignature];
+
+  // Persist the local state pref changes made above and in setUp().
+  [[AppLaunchManager sharedManager]
+      ensureAppLaunchedWithConfiguration:[self appConfigForPersistingPrefs]];
+
+  // Verify that (i) the crash and failed fetch streaks were reset, (ii) the
+  // safe seed was persisted, and (iii) there is no field trial associated with
+  // the test safe seed's sole study. There should be a field trial associated
+  // with the study only after variations safe mode is triggered.
+  [self checkCrashStreakValue:0];
+  [self checkFailedFetchStreakValue:0];
+  GREYAssertTrue([VariationsAppInterface hasSafeSeed],
+                 @"The variations safe seed pref should be set.");
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+
+  // Crash the app three times since a crash streak of three or more triggers
+  // variations safe mode. Also, verify the crash streak and the field trial
+  // after crashes.
+  AppLaunchConfiguration config = [self appConfigForCrashing];
+  // First crash.
+  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
+  [self checkCrashStreakValue:1];
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+  // Second crash.
+  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
+  [self checkCrashStreakValue:2];
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+  // Third crash.
+  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
+  [self checkCrashStreakValue:3];
+  GREYAssertTrue([VariationsAppInterface hasSafeSeed],
+                 @"The variations safe seed pref should be set.");
+  // Verify that Chrome fell back to variations safe mode by checking that there
+  // is a field trial for the test safe seed's study.
+  GREYAssertTrue([VariationsAppInterface fieldTrialExistsForTestSeed],
+                 @"There should be a field trial for |kTestSeedStudyName|.");
+}
+
+// Tests that variations seed fetch failures trigger variations safe mode.
+//
+// Corresponds to VariationsSafeModeBrowserTest.FetchFailuresTriggerSafeMode in
+// variations_safe_mode_browsertest.cc.
+- (void)testFetchFailuresTriggerSafeMode {
+  [VariationsAppInterface setTestSafeSeedAndSignature];
+  // The fetch failure streak threshold for triggering safe mode is 25.
+  [VariationsAppInterface setFetchFailureValue:25];
+
+  // Verify that there is no field trial associated with the test safe seed's
+  // sole study.
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+
+  // Persist the local state pref changes made above and in setUp().
+  [[AppLaunchManager sharedManager]
+      ensureAppLaunchedWithConfiguration:[self appConfigForPersistingPrefs]];
+
+  // Verify that (i) the crash streak was reset, (ii) the failed fetch streak
+  // and the safe seed were persisted, and (iii) safe mode was triggered.
+  [self checkCrashStreakValue:0];
+  [self checkFailedFetchStreakValue:25];
+  GREYAssertTrue([VariationsAppInterface hasSafeSeed],
+                 @"The variations safe seed pref should be set.");
+  // Verify that Chrome fell back to variations safe mode by checking that there
+  // is a field trial for the test safe seed's study.
+  GREYAssertTrue([VariationsAppInterface fieldTrialExistsForTestSeed],
+                 @"There should be a field trial for |kTestSeedStudyName|.");
+}
+
+// Tests that variations safe mode is not triggered.
+//
+// Corresponds to VariationsSafeModeBrowserTest.DoNotTriggerSafeMode in
+// variations_safe_mode_browsertest.cc.
+- (void)testDoNotTriggerSafeMode {
+  [VariationsAppInterface setTestSafeSeedAndSignature];
+  // Neither a crash streak of 2 nor a fetch failure streak of 24 will trigger
+  // variations safe mode in the next session.
+  int crashes = 2;
+  int fetchFailures = 24;
+  [VariationsAppInterface setCrashValue:crashes];
+  [VariationsAppInterface setFetchFailureValue:fetchFailures];
+
+  // Verify that there is no field trial associated with the test safe seed's
+  // sole study.
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+
+  // Persist the local state pref changes made above and in setUp().
+  [[AppLaunchManager sharedManager]
+      ensureAppLaunchedWithConfiguration:[self appConfigForPersistingPrefs]];
+
+  // Verify that (i) the crash and failed fetch streaks are as expected, (ii)
+  // the safe seed was stored, and (iii) safe mode was not triggered.
+  [self checkCrashStreakValue:2];
+  [self checkFailedFetchStreakValue:24];
+  GREYAssertTrue([VariationsAppInterface hasSafeSeed],
+                 @"The variations safe seed pref should be set.");
+  // Verify that Chrome did not fall back to variations safe mode by checking
+  // that there isn't a field trial for the test safe seed's study.
+  GREYAssertFalse([VariationsAppInterface fieldTrialExistsForTestSeed],
+                  @"There should be no field trial for |kTestSeedStudyName|.");
+}
+
+@end
diff --git a/ios/chrome/browser/voice/speech_input_locale_config.mm b/ios/chrome/browser/voice/speech_input_locale_config.mm
index 366fe5b..b03189a 100644
--- a/ios/chrome/browser/voice/speech_input_locale_config.mm
+++ b/ios/chrome/browser/voice/speech_input_locale_config.mm
@@ -4,6 +4,7 @@
 
 #include "ios/chrome/browser/voice/speech_input_locale_config.h"
 
+#include "base/no_destructor.h"
 #include "ios/chrome/browser/voice/speech_input_locale_config_impl.h"
 #include "ios/chrome/browser/voice/speech_input_locale_match.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
diff --git a/ios/chrome/browser/voice/speech_input_locale_config_impl.h b/ios/chrome/browser/voice/speech_input_locale_config_impl.h
index b6c9cd7..4c54cd7 100644
--- a/ios/chrome/browser/voice/speech_input_locale_config_impl.h
+++ b/ios/chrome/browser/voice/speech_input_locale_config_impl.h
@@ -11,7 +11,6 @@
 #include <string>
 #include <vector>
 
-#include "base/no_destructor.h"
 #include "ios/chrome/browser/voice/speech_input_locale_config.h"
 #include "ios/chrome/browser/voice/speech_input_locale_match.h"
 #include "ios/public/provider/chrome/browser/voice/voice_search_language.h"
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 7fdc6ce..9d80374a6 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -158,6 +158,7 @@
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/util:eg_app_support+eg2",
     "//ios/chrome/browser/unified_consent",
+    "//ios/chrome/browser/variations:eg_app_support+eg2",
     "//ios/chrome/browser/web",
     "//ios/chrome/browser/web:eg_app_support+eg2",
     "//ios/chrome/browser/web:tab_id_tab_helper",
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn
index de80018..5be1396 100644
--- a/ios/chrome/test/earl_grey2/BUILD.gn
+++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -89,6 +89,7 @@
     "//ios/chrome/browser/ui/content_suggestions:eg2_tests",
     "//ios/chrome/browser/ui/default_promo:eg2_tests",
     "//ios/chrome/browser/ui/integration_tests:eg2_tests",
+    "//ios/chrome/browser/variations:eg2_tests",
   ]
   data_deps = [ ":ios_chrome_eg2tests" ]
 }
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
index e113c92..8e20368 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-038fa0befb4567e747891dcf71b9b748dbb993fb
\ No newline at end of file
+1db212a61ed182f1452bf2122a1fa50ccfd2e705
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
index db9b872..06cf152 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-3ad2abd4bbec7102f8df07a139ccd6faaf618ade
\ No newline at end of file
+c368dd864b17e1070de8dd0c47b418808e6d1093
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
index 66a8422..cf40dca 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-2753fb71c2c1eac911ef86beb40a1352d6a72d18
\ No newline at end of file
+70a16f774446387a3805d2211c788f9ee60e48df
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
index ce6f718..4b0c58b1 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-ebf5b1d0de1d4a726baff9be9fa0aff02b47c648
\ No newline at end of file
+65d08aaa214759ba9a2fa9c943ab3fb392ec8dac
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
index e798ed8..0da97d1 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-cc8c3f825cc1111130c7b0528ac076d307aea77c
\ No newline at end of file
+007a1417f54ce4e78cd463cd3677d234b981ae09
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
index 6727319..f383671 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-81651cba61fefdd26297c8643c40985960fe2a37
\ No newline at end of file
+525b47d858d4a434ff1deca092f5f2937933fe46
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
index aae2479d..aefca3b 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-ecc72b7d3a7519f2ebd8eb6d4ea723b3cc881727
\ No newline at end of file
+1d0cc18d3f8fcab2b3c71735bec92b3e889d38c1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
index ef77e474..930126f 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-b7d6122d90407d8be4e0f2cce8a21e64d9e8c345
\ No newline at end of file
+95a6d05353036397e265bc96bf5fa19d8059a7b0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
index d6527f2..1fd3eb21 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-5fce21a057fe9b266c6f21aba792adc81ab33952
\ No newline at end of file
+18100757468d10eb20005962679379073e38a930
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
index 9ab6f1c8..b4bf001 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-0f730050f554ec18fd4e826373aefc420f9aabaf
\ No newline at end of file
+c5bb9d59ae2092a85075c7062e4dfe85410da5c2
\ No newline at end of file
diff --git a/ios/web/public/js_messaging/README.md b/ios/web/public/js_messaging/README.md
index 67c3b3d..8853a7d0 100644
--- a/ios/web/public/js_messaging/README.md
+++ b/ios/web/public/js_messaging/README.md
@@ -6,6 +6,8 @@
 Chrome for iOS doesn't have access to the renderer code so many browser features
 require JavaScript in order to interact with the webpage.
 
+Slides covering this topic are available [here](https://docs.google.com/presentation/d/1HKdi7CGtNTGhMcCscpX_LVFZ8iLTtXjpSQ-980N7J38/edit?usp=sharing).
+
 ## Background
 
 It is important to first understand the following concepts in order to properly
diff --git a/ios/web_view/internal/translate/web_view_translate_client.mm b/ios/web_view/internal/translate/web_view_translate_client.mm
index f24606cc..0184b5f9 100644
--- a/ios/web_view/internal/translate/web_view_translate_client.mm
+++ b/ios/web_view/internal/translate/web_view_translate_client.mm
@@ -73,7 +73,7 @@
 
 bool WebViewTranslateClient::RequestTranslationOffer() {
   if (translate_manager_.CanManuallyTranslate()) {
-    translate_manager_.InitiateManualTranslation();
+    translate_manager_.ShowTranslateUI();
     return true;
   } else {
     return false;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 0cf94eed..ddeeeef 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -871,7 +871,7 @@
 
 // Display the playback speed button on the media controls.
 const base::Feature kPlaybackSpeedButton{"PlaybackSpeedButton",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
+                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
 bool IsVideoCaptureAcceleratedJpegDecodingEnabled() {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/media/gpu/test/image_quality_metrics.cc b/media/gpu/test/image_quality_metrics.cc
index da56c4df..40eea6d7 100644
--- a/media/gpu/test/image_quality_metrics.cc
+++ b/media/gpu/test/image_quality_metrics.cc
@@ -138,11 +138,12 @@
 double ComputeSimilarity(const VideoFrame* frame1,
                          const VideoFrame* frame2,
                          SimilarityMetrics mode) {
-  ASSERT_TRUE_OR_RETURN(frame1->IsMappable() && frame2->IsMappable(),
-                        std::numeric_limits<std::size_t>::max());
+  ASSERT_TRUE_OR_RETURN(
+      frame1->IsMappable() && frame2->IsMappable(),
+      static_cast<double>(std::numeric_limits<std::size_t>::max()));
   ASSERT_TRUE_OR_RETURN(
       frame1->visible_rect().size() == frame2->visible_rect().size(),
-      std::numeric_limits<std::size_t>::max());
+      static_cast<double>(std::numeric_limits<std::size_t>::max()));
   // Ideally, frame1->BitDepth() should be the same as frame2->BitDepth()
   // always. But in the 10 bit case, the 10 bit frame can be carried with P016LE
   // whose bit depth is regarded to be 16. This is due to a lack of NV12 10-bit
@@ -151,7 +152,7 @@
   ASSERT_TRUE_OR_RETURN(
       (frame1->BitDepth() == 8 && frame1->BitDepth() == frame2->BitDepth()) ||
           std::min(frame1->BitDepth(), frame2->BitDepth()) == 10,
-      std::numeric_limits<std::size_t>::max());
+      static_cast<double>(std::numeric_limits<std::size_t>::max()));
   const size_t bit_depth = std::min(frame1->BitDepth(), frame2->BitDepth());
   const VideoPixelFormat common_format =
       bit_depth == 8 ? PIXEL_FORMAT_I420 : PIXEL_FORMAT_YUV420P10;
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc
index e8e74e8..d08266a 100644
--- a/media/renderers/paint_canvas_video_renderer.cc
+++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -1379,6 +1379,9 @@
   if (!raster_context_provider || !raster_context_provider->GrContext())
     return false;
 
+  if (raster_context_provider->ContextCapabilities().disable_legacy_mailbox)
+    return false;
+
   // Trigger resource allocation for dst texture to back SkSurface.
   // Dst texture size should equal to video frame visible rect.
   destination_gl->BindTexture(target, texture);
diff --git a/media/test/data/test_key_system_instantiation.html b/media/test/data/test_key_system_instantiation.html
index 5d9604c..a5c65ea 100644
--- a/media/test/data/test_key_system_instantiation.html
+++ b/media/test/data/test_key_system_instantiation.html
@@ -13,12 +13,22 @@
         }
       };
 
+      function capabilitiesToString(array) {
+        var result = [];
+        array.forEach(function(v) {
+          result.push(v.contentType);
+        });
+        return '[ ' + result.join(', ') + ' ]';
+      }
+
       // Compares 2 arrays of MediaKeySystemMediaCapability, comparing only
       // |contentType|. This assumes the order is the same. Returns "success"
       // if they match, an error message if they don't.
       function verifyCapabilitiesAreEqual(actual, expected) {
         if (actual.length != expected.length)
-          return "mismatched lengths; not all capabilities are supported";
+          return 'mismatched lengths; not all capabilities are supported. Got ' +
+              capabilitiesToString(actual) + ', expected ' +
+              capabilitiesToString(expected);
         for (var i = 0; i < actual.length; i++) {
           // Only compare |contentType|. Other properties are ignored.
           if (actual[i].contentType !== expected[i].contentType)
@@ -68,7 +78,9 @@
                   return;
                 }
               } else if (allowedConfig.audioCapabilities.length > 0) {
-                setResultInTitle("audioCapabilities set when none expected");
+                setResultInTitle(
+                    'audioCapabilities set when none expected, got ' +
+                    capabilitiesToString(allowedConfig.audioCapabilities));
                 return;
               }
               if (videoCapabilities !== null) {
@@ -77,7 +89,9 @@
                                             configuration.videoCapabilities));
                 return;
               } else if (allowedConfig.videoCapabilities.length > 0) {
-                setResultInTitle("videoCapabilities set when none expected");
+                setResultInTitle(
+                    'videoCapabilities set when none expected, got ' +
+                    capabilitiesToString(allowedConfig.videoCapabilities));
                 return;
               }
               setResultInTitle("success");
diff --git a/native_client_sdk/src/libraries/nacl_io/BUILD.gn b/native_client_sdk/src/libraries/nacl_io/BUILD.gn
deleted file mode 100644
index a4a1ed40..0000000
--- a/native_client_sdk/src/libraries/nacl_io/BUILD.gn
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_nacl,
-       "These targets must only be built using the untrusted NaCl toolchains.")
-
-config("nacl_io_config") {
-  cflags = [ "-Wno-sign-compare" ]
-}
-
-config("nacl_io_include_dirs") {
-  include_dirs = [
-    "..",
-    "include",
-    "../third_party/newlib-extras",
-  ]
-}
-
-source_set("nacl_io") {
-  sources = [
-    "devfs/dev_fs.cc",
-    "devfs/dev_fs.h",
-    "devfs/jspipe_event_emitter.cc",
-    "devfs/jspipe_event_emitter.h",
-    "devfs/jspipe_node.cc",
-    "devfs/jspipe_node.h",
-    "devfs/tty_node.cc",
-    "devfs/tty_node.h",
-    "dir_node.cc",
-    "dir_node.h",
-    "event_emitter.cc",
-    "event_emitter.h",
-    "event_listener.cc",
-    "event_listener.h",
-    "fifo_char.cc",
-    "fifo_char.h",
-    "filesystem.cc",
-    "filesystem.h",
-    "fusefs/fuse_fs.cc",
-    "fusefs/fuse_fs.h",
-    "fusefs/fuse_fs_factory.cc",
-    "fusefs/fuse_fs_factory.h",
-    "getdents_helper.cc",
-    "getdents_helper.h",
-    "googledrivefs/googledrivefs.cc",
-    "googledrivefs/googledrivefs.h",
-    "googledrivefs/googledrivefs_node.cc",
-    "googledrivefs/googledrivefs_node.h",
-    "h_errno.c",
-    "hash.cc",
-    "host_resolver.cc",
-    "host_resolver.h",
-    "html5fs/html5_fs.cc",
-    "html5fs/html5_fs.h",
-    "html5fs/html5_fs_node.cc",
-    "html5fs/html5_fs_node.h",
-    "httpfs/http_fs.cc",
-    "httpfs/http_fs.h",
-    "httpfs/http_fs_node.cc",
-    "httpfs/http_fs_node.h",
-    "in6_addr.c",
-    "jsfs/js_fs.cc",
-    "jsfs/js_fs.h",
-    "jsfs/js_fs_node.cc",
-    "jsfs/js_fs_node.h",
-    "kernel_handle.cc",
-    "kernel_handle.h",
-    "kernel_intercept.cc",
-    "kernel_intercept.h",
-    "kernel_object.cc",
-    "kernel_object.h",
-    "kernel_proxy.cc",
-    "kernel_proxy.h",
-    "kernel_wrap_dummy.cc",
-    "kernel_wrap_glibc.cc",
-    "kernel_wrap_irt_ext.c",
-    "kernel_wrap_newlib.cc",
-    "kernel_wrap_win.cc",
-    "log.c",
-    "memfs/mem_fs.cc",
-    "memfs/mem_fs.h",
-    "memfs/mem_fs_node.cc",
-    "memfs/mem_fs_node.h",
-    "nacl_io.cc",
-    "nacl_io.h",
-    "node.cc",
-    "node.h",
-    "passthroughfs/passthrough_fs.cc",
-    "passthroughfs/passthrough_fs.h",
-    "passthroughfs/real_node.cc",
-    "passthroughfs/real_node.h",
-    "path.cc",
-    "pepper_interface.cc",
-    "pepper_interface.h",
-    "pepper_interface_delegate.cc",
-    "pepper_interface_delegate.h",
-    "pipe/pipe_event_emitter.cc",
-    "pipe/pipe_event_emitter.h",
-    "pipe/pipe_node.cc",
-    "pipe/pipe_node.h",
-    "real_pepper_interface.cc",
-    "real_pepper_interface.h",
-    "socket/fifo_packet.cc",
-    "socket/fifo_packet.h",
-    "socket/packet.cc",
-    "socket/packet.h",
-    "socket/socket_node.cc",
-    "socket/socket_node.h",
-    "socket/tcp_event_emitter.cc",
-    "socket/tcp_event_emitter.h",
-    "socket/tcp_node.cc",
-    "socket/tcp_node.h",
-    "socket/udp_event_emitter.cc",
-    "socket/udp_event_emitter.h",
-    "socket/udp_node.cc",
-    "socket/udp_node.h",
-    "socket/unix_event_emitter.cc",
-    "socket/unix_event_emitter.h",
-    "socket/unix_node.cc",
-    "socket/unix_node.h",
-    "stream/stream_event_emitter.cc",
-    "stream/stream_event_emitter.h",
-    "stream/stream_fs.cc",
-    "stream/stream_fs.h",
-    "stream/stream_node.cc",
-    "stream/stream_node.h",
-    "syscalls/access.c",
-    "syscalls/chown.c",
-    "syscalls/fchown.c",
-    "syscalls/fcntl.c",
-    "syscalls/ftruncate.c",
-    "syscalls/futimes.c",
-    "syscalls/getwd.c",
-    "syscalls/ioctl.c",
-    "syscalls/isatty.c",
-    "syscalls/kill.c",
-    "syscalls/killpg.c",
-    "syscalls/lchown.c",
-    "syscalls/mount.c",
-    "syscalls/pipe.c",
-    "syscalls/poll.c",
-    "syscalls/realpath.c",
-    "syscalls/select.c",
-    "syscalls/sigaction.c",
-    "syscalls/signal.c",
-    "syscalls/sigpause.c",
-    "syscalls/sigpending.c",
-    "syscalls/sigset.c",
-    "syscalls/sigsuspend.c",
-    "syscalls/socket/accept.c",
-    "syscalls/socket/bind.c",
-    "syscalls/socket/connect.c",
-    "syscalls/socket/freeaddrinfo.c",
-    "syscalls/socket/gai_strerror.c",
-    "syscalls/socket/getaddrinfo.c",
-    "syscalls/socket/gethostbyname.c",
-    "syscalls/socket/getnameinfo.c",
-    "syscalls/socket/getpeername.c",
-    "syscalls/socket/getsockname.c",
-    "syscalls/socket/getsockopt.c",
-    "syscalls/socket/herror.c",
-    "syscalls/socket/hstrerror.c",
-    "syscalls/socket/htonl.c",
-    "syscalls/socket/htons.c",
-    "syscalls/socket/inet_addr.c",
-    "syscalls/socket/inet_aton.c",
-    "syscalls/socket/inet_ntoa.c",
-    "syscalls/socket/inet_ntop.cc",
-    "syscalls/socket/inet_pton.c",
-    "syscalls/socket/listen.c",
-    "syscalls/socket/ntohl.c",
-    "syscalls/socket/ntohs.c",
-    "syscalls/socket/recv.c",
-    "syscalls/socket/recvfrom.c",
-    "syscalls/socket/recvmsg.c",
-    "syscalls/socket/send.c",
-    "syscalls/socket/sendmsg.c",
-    "syscalls/socket/sendto.c",
-    "syscalls/socket/setsockopt.c",
-    "syscalls/socket/shutdown.c",
-    "syscalls/socket/socket.c",
-    "syscalls/socket/socketpair.c",
-    "syscalls/symlink.c",
-    "syscalls/termios/cfgetispeed.c",
-    "syscalls/termios/cfgetospeed.c",
-    "syscalls/termios/cfsetispeed.c",
-    "syscalls/termios/cfsetospeed.c",
-    "syscalls/termios/cfsetspeed.c",
-    "syscalls/termios/tcdrain.c",
-    "syscalls/termios/tcflow.c",
-    "syscalls/termios/tcflush.c",
-    "syscalls/termios/tcgetattr.c",
-    "syscalls/termios/tcsendbreak.c",
-    "syscalls/termios/tcsetattr.c",
-    "syscalls/truncate.c",
-    "syscalls/umask.c",
-    "syscalls/umount.c",
-    "syscalls/uname.c",
-    "syscalls/utime.c",
-  ]
-
-  include_dirs = [ ".." ]
-  configs += [ ":nacl_io_config" ]
-
-  public_configs = [ ":nacl_io_include_dirs" ]
-}
diff --git a/net/base/net_errors.cc b/net/base/net_errors.cc
index 06ba2d9..39890a98 100644
--- a/net/base/net_errors.cc
+++ b/net/base/net_errors.cc
@@ -4,7 +4,11 @@
 
 #include "net/base/net_errors.h"
 
+#include <string>
+
 #include "base/check_op.h"
+#include "base/files/file.h"
+#include "base/logging.h"
 #include "base/notreached.h"
 #include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
 
diff --git a/net/base/net_errors.h b/net/base/net_errors.h
index d2807f5..e146fc40 100644
--- a/net/base/net_errors.h
+++ b/net/base/net_errors.h
@@ -6,7 +6,6 @@
 #define NET_BASE_NET_ERRORS_H__
 
 #include <string>
-#include <vector>
 
 #include "base/files/file.h"
 #include "base/logging.h"
diff --git a/net/quic/quic_http3_logger.cc b/net/quic/quic_http3_logger.cc
index 14d3c0b..8132bfe 100644
--- a/net/quic/quic_http3_logger.cc
+++ b/net/quic/quic_http3_logger.cc
@@ -145,15 +145,6 @@
       stream_id);
 }
 
-void QuicHttp3Logger::OnCancelPushFrameReceived(
-    const quic::CancelPushFrame& frame) {
-  if (!net_log_.IsCapturing()) {
-    return;
-  }
-  net_log_.AddEventWithIntParams(NetLogEventType::HTTP3_CANCEL_PUSH_RECEIVED,
-                                 "push_id", frame.push_id);
-}
-
 void QuicHttp3Logger::OnSettingsFrameReceived(
     const quic::SettingsFrame& frame) {
   // Increment value by one because empty SETTINGS frames are allowed,
@@ -262,42 +253,6 @@
       });
 }
 
-void QuicHttp3Logger::OnPushPromiseFrameReceived(
-    quic::QuicStreamId stream_id,
-    quic::QuicStreamId push_id,
-    quic::QuicByteCount compressed_headers_length) {
-  if (!net_log_.IsCapturing()) {
-    return;
-  }
-  net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_RECEIVED,
-                    [stream_id, push_id, compressed_headers_length] {
-                      return NetLogThreeIntParams("stream_id", stream_id,
-                                                  "push_id", push_id,
-                                                  "compressed_headers_length",
-                                                  compressed_headers_length);
-                    });
-}
-
-void QuicHttp3Logger::OnPushPromiseDecoded(quic::QuicStreamId stream_id,
-                                           quic::QuicStreamId push_id,
-                                           quic::QuicHeaderList headers) {
-  if (!net_log_.IsCapturing()) {
-    return;
-  }
-  net_log_.AddEvent(
-      NetLogEventType::HTTP3_PUSH_PROMISE_DECODED,
-      [stream_id, push_id, &headers](NetLogCaptureMode capture_mode) {
-        base::Value dict(base::Value::Type::DICTIONARY);
-        dict.SetKey("stream_id",
-                    NetLogNumberValue(static_cast<uint64_t>(stream_id)));
-        dict.SetKey("push_id",
-                    NetLogNumberValue(static_cast<uint64_t>(push_id)));
-        dict.SetKey("headers",
-                    ElideQuicHeaderListForNetLog(headers, capture_mode));
-        return dict;
-      });
-}
-
 void QuicHttp3Logger::OnUnknownFrameReceived(
     quic::QuicStreamId stream_id,
     uint64_t frame_type,
diff --git a/net/quic/quic_http3_logger.h b/net/quic/quic_http3_logger.h
index 295952a6..976d70a 100644
--- a/net/quic/quic_http3_logger.h
+++ b/net/quic/quic_http3_logger.h
@@ -30,7 +30,6 @@
   void OnPeerQpackEncoderStreamCreated(quic::QuicStreamId stream_id) override;
   void OnPeerQpackDecoderStreamCreated(quic::QuicStreamId stream_id) override;
 
-  void OnCancelPushFrameReceived(const quic::CancelPushFrame& frame) override;
   void OnSettingsFrameReceived(const quic::SettingsFrame& frame) override;
   void OnSettingsFrameResumed(const quic::SettingsFrame& frame) override;
   void OnGoAwayFrameReceived(const quic::GoAwayFrame& frame) override;
@@ -45,13 +44,6 @@
       quic::QuicByteCount compressed_headers_length) override;
   void OnHeadersDecoded(quic::QuicStreamId stream_id,
                         quic::QuicHeaderList headers) override;
-  void OnPushPromiseFrameReceived(
-      quic::QuicStreamId stream_id,
-      quic::QuicStreamId push_id,
-      quic::QuicByteCount compressed_headers_length) override;
-  void OnPushPromiseDecoded(quic::QuicStreamId stream_id,
-                            quic::QuicStreamId push_id,
-                            quic::QuicHeaderList headers) override;
 
   void OnUnknownFrameReceived(quic::QuicStreamId stream_id,
                               uint64_t frame_type,
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 086c56a2..d7bcb757 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -170,6 +170,11 @@
     return Allow();
 #endif
 
+  // V8 uses PKU (a.k.a. MPK / PKEY) for protecting code spaces.
+  if (sysno == __NR_pkey_alloc || sysno == __NR_pkey_free) {
+    return Allow();
+  }
+
   if (SyscallSets::IsClockApi(sysno)) {
     return RestrictClockID();
   }
@@ -259,8 +264,11 @@
     return RestrictMmapFlags();
 #endif
 
-  if (sysno == __NR_mprotect)
+  if (sysno == __NR_mprotect || sysno == __NR_pkey_mprotect) {
+    // pkey_mprotect is identical to mprotect except for the additional (last)
+    // parameter, which can be ignored here.
     return RestrictMprotectFlags();
+  }
 
   if (sysno == __NR_prctl)
     return RestrictPrctl();
diff --git a/sandbox/policy/linux/bpf_renderer_policy_linux.cc b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
index f38b5434..f789e92 100644
--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc
+++ b/sandbox/policy/linux/bpf_renderer_policy_linux.cc
@@ -97,9 +97,6 @@
     case __NR_sysinfo:
     case __NR_times:
     case __NR_uname:
-      // V8 uses PKU (a.k.a. MPK / PKEY) for protecting code spaces.
-    case __NR_pkey_alloc:
-    case __NR_pkey_free:
       return Allow();
     case __NR_sched_getaffinity:
     case __NR_sched_getparam:
@@ -109,10 +106,6 @@
     case __NR_prlimit64:
       // See crbug.com/662450 and setrlimit comment above.
       return RestrictPrlimit(GetPolicyPid());
-      // V8 uses PKU (a.k.a. MPK / PKEY) for protecting code spaces.
-    case __NR_pkey_mprotect:
-      // Ignore the last parameter; others are identical to mprotect.
-      return RestrictMprotectFlags();
     default:
       // Default on the content baseline policy.
       return BPFBasePolicy::EvaluateSyscall(sysno);
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory.h b/services/network/trust_tokens/trust_token_request_helper_factory.h
index 58823f9..9966260 100644
--- a/services/network/trust_tokens/trust_token_request_helper_factory.h
+++ b/services/network/trust_tokens/trust_token_request_helper_factory.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/callback.h"
-#include "base/no_destructor.h"
 #include "net/log/net_log_with_source.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/trust_tokens.mojom.h"
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 985c4a7d..c4a6d96 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -211,8 +211,6 @@
 
 #define SK_SUPPORT_LEGACY_DRAWLOOPER
 
-#define SK_SUPPORT_LEGACY_SETFILTERQUALITY
-
 #define SK_SUPPORT_LEGACY_RUNTIME_EFFECTS
 
 #define SK_SUPPORT_LEGACY_DITHER
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
index aee01d4..0c65f58 100644
--- a/skia/ext/benchmarking_canvas.cc
+++ b/skia/ext/benchmarking_canvas.cc
@@ -205,15 +205,6 @@
     val->SetString("Flags", builder.str());
   }
 
-  if (paint.getFilterQuality() != default_paint.getFilterQuality()) {
-    static const char* gFilterQualityStrings[] = {
-        "None", "Low", "Medium", "High"};
-    DCHECK_LT(static_cast<size_t>(paint.getFilterQuality()),
-              SK_ARRAY_COUNT(gFilterQualityStrings));
-    val->SetString("FilterLevel",
-                   gFilterQualityStrings[paint.getFilterQuality()]);
-  }
-
   if (paint.getColorFilter())
     val->SetKey("ColorFilter", base::Value::FromUniquePtrValue(
                                    AsValue(*paint.getColorFilter())));
diff --git a/sql/statement.cc b/sql/statement.cc
index f07460f..e69c931 100644
--- a/sql/statement.cc
+++ b/sql/statement.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/dcheck_is_on.h"
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/sequence_checker.h"
@@ -82,7 +83,6 @@
   absl::optional<base::ScopedBlockingCall> scoped_blocking_call;
   ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
-  stepped_ = true;
   int ret = sqlite3_step(ref_->stmt());
   return CheckError(ret);
 }
@@ -92,7 +92,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
-  DCHECK(!stepped_);
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << "Run() must be called exactly once";
+  run_called_ = true;
+  DCHECK(!step_called_) << "Run() must not be mixed with Step()";
+#endif  // DCHECK_IS_ON()
   return StepInternal() == SQLITE_DONE;
 }
 
@@ -101,6 +105,10 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << "Run() must not be mixed with Step()";
+  step_called_ = true;
+#endif  // DCHECK_IS_ON()
   return StepInternal() == SQLITE_ROW;
 }
 
@@ -128,7 +136,10 @@
     ref_->database()->ReleaseCacheMemoryIfNeeded(false);
 
   succeeded_ = false;
-  stepped_ = false;
+#if DCHECK_IS_ON()
+  run_called_ = false;
+  step_called_ = false;
+#endif  // DCHECK_IS_ON()
 }
 
 bool Statement::Succeeded() const {
@@ -143,7 +154,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -166,7 +182,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -181,7 +202,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -197,7 +223,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -213,7 +244,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -230,7 +266,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   DCHECK(val);
   if (!is_valid())
     return;
@@ -255,7 +296,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -296,7 +342,12 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  DCHECK(!stepped_);
+
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " must not be called after Run()";
+  DCHECK(!step_called_) << __func__ << " must not be called after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!is_valid())
     return;
 
@@ -356,6 +407,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   return static_cast<enum ColumnType>(sqlite3_column_type(ref_->stmt(), col));
 }
 
@@ -363,7 +419,7 @@
 #if !defined(OS_ANDROID)  // TODO(crbug.com/866218): Remove this conditional
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
-  return static_cast<bool>(ColumnInt(column_index));
+  return static_cast<bool>(ColumnInt64(column_index));
 }
 
 int Statement::ColumnInt(int column_index) const {
@@ -371,6 +427,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return 0;
   DCHECK_GE(column_index, 0);
@@ -385,6 +446,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return 0;
   DCHECK_GE(column_index, 0);
@@ -399,6 +465,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return 0;
   DCHECK_GE(column_index, 0);
@@ -413,6 +484,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return base::Time();
   DCHECK_GE(column_index, 0);
@@ -429,6 +505,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return std::string();
   DCHECK_GE(column_index, 0);
@@ -450,6 +531,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return std::u16string();
   DCHECK_GE(column_index, 0);
@@ -465,6 +551,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return 0;
   DCHECK_GE(column_index, 0);
@@ -479,6 +570,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return nullptr;
   DCHECK_GE(column_index, 0);
@@ -494,6 +590,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return false;
   DCHECK_GE(column_index, 0);
@@ -516,6 +617,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #endif  // OS_ANDROID
 
+#if DCHECK_IS_ON()
+  DCHECK(!run_called_) << __func__ << " can be used after Step(), not Run()";
+  DCHECK(step_called_) << __func__ << " can only be used after Step()";
+#endif  // DCHECK_IS_ON()
+
   if (!CheckValid())
     return false;
   DCHECK_GE(column_index, 0);
diff --git a/sql/statement.h b/sql/statement.h
index 23866b6..c664ab8 100644
--- a/sql/statement.h
+++ b/sql/statement.h
@@ -12,6 +12,7 @@
 
 #include "base/component_export.h"
 #include "base/containers/span.h"
+#include "base/dcheck_is_on.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string_piece_forward.h"
@@ -228,14 +229,15 @@
   // guaranteed non-null.
   scoped_refptr<Database::StatementRef> ref_;
 
-  // Set after Step() or Run() are called, reset by Reset().  Used to
-  // prevent accidental calls to API functions which would not work
-  // correctly after stepping has started.
-  bool stepped_ = false;
-
   // See Succeeded() for what this holds.
   bool succeeded_ = false;
 
+#if DCHECK_IS_ON()
+  // Used to DCHECK() that Bind*() is called before Step() or Run() are called.
+  bool step_called_ = false;
+  bool run_called_ = false;
+#endif  // DCHECK_IS_ON()
+
   SEQUENCE_CHECKER(sequence_checker_);
 };
 
diff --git a/storage/browser/quota/quota_device_info_helper.h b/storage/browser/quota/quota_device_info_helper.h
index 5a2fdd1..c55220f 100644
--- a/storage/browser/quota/quota_device_info_helper.h
+++ b/storage/browser/quota/quota_device_info_helper.h
@@ -4,7 +4,6 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "base/system/sys_info.h"
 
 #ifndef STORAGE_BROWSER_QUOTA_QUOTA_DEVICE_INFO_HELPER_H_
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc
index 13958ce..4830c83 100644
--- a/storage/browser/quota/quota_settings.cc
+++ b/storage/browser/quota/quota_settings.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/no_destructor.h"
 #include "base/rand_util.h"
 #include "base/system/sys_info.h"
 #include "base/task/post_task.h"
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 75c8cf1..5b4e87a 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -10247,7 +10247,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -10505,7 +10505,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index c329166..67b3407 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -49495,7 +49495,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49756,7 +49756,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50089,7 +50089,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50347,7 +50347,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50679,7 +50679,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50937,7 +50937,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.163"
+              "revision": "version:91.0.4472.164"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 7b7e6242..947d940 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -14056,10 +14056,344 @@
     ]
   },
   "Mac FYI Experimental Retina Release (AMD)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "angle_end2end_tests",
+          "--gtest_filter=-*Vulkan_SwiftShader*",
+          "--bot-mode"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "angle_end2end_tests",
+        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_end2end_tests/",
+        "use_isolated_scripts_api": true
+      },
+      {
+        "args": [
+          "angle_unittests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "angle_unittests",
+        "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/",
+        "use_isolated_scripts_api": true
+      },
+      {
+        "args": [
+          "--enable-gpu",
+          "--test-launcher-bot-mode",
+          "--test-launcher-jobs=1",
+          "--gtest_filter=TabCaptureApiPixelTest.EndToEnd*"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "tab_capture_end2end_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "browser_tests",
+        "test_id_prefix": "ninja://chrome/test:browser_tests/"
+      },
+      {
+        "args": [
+          "--use-cmd-decoder=passthrough",
+          "--use-gl=angle",
+          "--use-gpu-in-tests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "gl_tests_passthrough",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "gl_tests",
+        "test_id_prefix": "ninja://gpu:gl_tests/"
+      },
+      {
+        "args": [
+          "--use-cmd-decoder=validating",
+          "--use-gpu-in-tests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "gl_tests_validating",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gl_tests",
+        "test_id_prefix": "ninja://gpu:gl_tests/"
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gl_unittests",
+        "test_id_prefix": "ninja://ui/gl:gl_unittests/"
+      },
+      {
+        "args": [
+          "--use-gpu-in-tests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gles2_conform_test",
+        "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gpu_unittests",
+        "test_id_prefix": "ninja://gpu:gpu_unittests/"
+      },
+      {
+        "args": [
+          "--gtest_filter=*Detection*",
+          "--use-gpu-in-tests"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "services_unittests",
+        "test_id_prefix": "ninja://services:services_unittests/"
+      }
+    ],
     "isolated_scripts": [
       {
         "args": [
-          "noop_sleep",
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "depth_capture",
           "--show-stdout",
           "--browser=release",
           "--passthrough",
@@ -14071,7 +14405,10 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "noop_sleep_tests",
+        "name": "depth_capture_tests",
+        "resultdb": {
+          "enable": true
+        },
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -14082,7 +14419,7 @@
               "display_attached": "1",
               "gpu": "1002:6821",
               "hidpi": "1",
-              "os": "Mac-10.14.6",
+              "os": "Mac-11.4",
               "pool": "chromium.tests.gpu"
             }
           ],
@@ -14091,6 +14428,1059 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_context_lost_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_depth_capture_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_gpu_process_launch_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_hardware_accelerated_feature_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_maps_pixel_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_pixel_skia_gold_tests",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --disable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gl_renderer_screenshot_sync_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gpu_process_launch_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "hardware_accelerated_feature_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "info_collection",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
+          "--expected-vendor-id",
+          "1002",
+          "--expected-device-id",
+          "6821"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "info_collection_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_passthrough_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "mediapipe",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "mediapipe_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "mediapipe",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "mediapipe_validating_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_passthrough_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "../../tools/perf/run_benchmark",
+          "--benchmarks=rendering.desktop"
+        ],
+        "isolate_name": "rendering_representative_perf_tests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "rendering_representative_perf_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:rendering_representative_perf_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "trace_test",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_validating_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl_conformance_gl_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl_conformance_metal_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--test-filter=conformance/rendering/gl-drawelements.html"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl_conformance_swangle_passthrough_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl_conformance_validating_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "display_attached": "1",
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "Mac-11.4",
+              "pool": "chromium.tests.gpu"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.perf.calibration.json b/testing/buildbot/chromium.perf.calibration.json
index 17434cf..fe11e0ac 100644
--- a/testing/buildbot/chromium.perf.calibration.json
+++ b/testing/buildbot/chromium.perf.calibration.json
@@ -10,13 +10,13 @@
           "--upload-results",
           "--test-shard-map-filename=android-pixel2-perf-calibration_map.json"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_monochrome_64_32_bundle",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_monochrome_64_32_bundle",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_monochrome_64_32_bundle"
         ],
         "resultdb": {
           "enable": true
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 180b781..e95a3dd 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -24,13 +24,13 @@
           "--output-format=histograms",
           "--experimental-tbmv3-metrics"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_chrome",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_chrome",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_chrome"
         ],
         "resultdb": {
           "enable": true
@@ -73,13 +73,13 @@
           "--upload-results",
           "--test-shard-map-filename=android-pixel2-perf-aab-fyi_map.json"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_monochrome_bundle",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_monochrome_bundle",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_monochrome_bundle"
         ],
         "resultdb": {
           "enable": true
@@ -126,13 +126,13 @@
           "--output-format=histograms",
           "--experimental-tbmv3-metrics"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_chrome",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_chrome",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_chrome"
         ],
         "resultdb": {
           "enable": true
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 1576e97b..43d2b7d 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -11,13 +11,13 @@
           "--test-shard-map-filename=android_nexus5_perf_map.json",
           "--assert-gpu-compositing"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_chrome",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_chrome",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_chrome"
         ],
         "resultdb": {
           "enable": true
@@ -407,7 +407,7 @@
           "--upload-results",
           "--test-shard-map-filename=android-go-perf_map.json"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_chrome",
         "merge": {
           "args": [
             "--lightweight",
@@ -417,7 +417,7 @@
         },
         "name": "performance_test_suite",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_chrome"
         ],
         "resultdb": {
           "enable": true
@@ -517,7 +517,7 @@
           "--upload-results",
           "--test-shard-map-filename=android-pixel2-perf_map.json"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_monochrome_64_32_bundle",
         "merge": {
           "args": [
             "--lightweight",
@@ -525,9 +525,9 @@
           ],
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_monochrome_64_32_bundle",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_monochrome_64_32_bundle"
         ],
         "resultdb": {
           "enable": true
@@ -689,13 +689,13 @@
           "--upload-results",
           "--test-shard-map-filename=android-pixel4-perf_map.json"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_trichrome_bundle",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_trichrome_bundle",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_trichrome_bundle"
         ],
         "resultdb": {
           "enable": true
@@ -837,13 +837,13 @@
           "--test-shard-map-filename=android-pixel4a_power-perf_map.json",
           "--experimental-tbmv3-metrics"
         ],
-        "isolate_name": "performance_test_suite",
+        "isolate_name": "performance_test_suite_android_clank_chrome",
         "merge": {
           "script": "//tools/perf/process_perf_results.py"
         },
-        "name": "performance_test_suite",
+        "name": "performance_test_suite_android_clank_chrome",
         "override_compile_targets": [
-          "performance_test_suite"
+          "performance_test_suite_android_clank_chrome"
         ],
         "resultdb": {
           "enable": true
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 400e214c..8cad6dc 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1432,6 +1432,26 @@
     "label": "//chrome/test:performance_test_suite",
     "type": "generated_script",
   },
+  "performance_test_suite_android_chrome": {
+    "label": "//chrome/test:performance_test_suite_android_chrome",
+    "type": "generated_script",
+  },
+  "performance_test_suite_android_clank_chrome": {
+    "label": "//chrome/test:performance_test_suite_android_clank_chrome",
+    "type": "generated_script",
+  },
+  "performance_test_suite_android_clank_monochrome_64_32_bundle": {
+    "label": "//chrome/test:performance_test_suite_android_clank_monochrome_64_32_bundle",
+    "type": "generated_script",
+  },
+  "performance_test_suite_android_clank_monochrome_bundle": {
+    "label": "//chrome/test:performance_test_suite_android_clank_monochrome_bundle",
+    "type": "generated_script",
+  },
+  "performance_test_suite_android_clank_trichrome_bundle": {
+    "label": "//chrome/test:performance_test_suite_android_clank_trichrome_bundle",
+    "type": "generated_script",
+  },
   "performance_test_suite_eve": {
     "label": "//chrome/test:performance_test_suite_eve",
     "type": "generated_script",
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 34a5fec..4550da8 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1165,7 +1165,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R93-14052.0.0",
+        "cros_img": "atlas-release/R93-14083.0.0",
         "name": "lacros_fyi_tast_tests_ATLAS_TOT",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\")",
@@ -1176,7 +1176,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R92-13982.38.0",
+        "cros_img": "atlas-release/R92-13982.52.0",
         "name": "lacros_fyi_tast_tests_ATLAS_TOT-1",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\")",
@@ -1187,7 +1187,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R93-14052.0.0",
+        "cros_img": "eve-release/R93-14083.0.0",
         "name": "lacros_fyi_tast_tests_EVE_TOT",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\")",
@@ -1198,13 +1198,53 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R92-13982.38.0",
+        "cros_img": "eve-release/R92-13982.52.0",
         "name": "lacros_fyi_tast_tests_EVE_TOT-1",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\")",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800
+      },
+      {
+        "args": [],
+        "cros_board": "atlas",
+        "cros_img": "atlas-release/R93-14083.0.0",
+        "name": "ozone_unittests_ATLAS_TOT",
+        "swarming": {},
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
+        "timeout_sec": 10800
+      },
+      {
+        "args": [],
+        "cros_board": "atlas",
+        "cros_img": "atlas-release/R92-13982.52.0",
+        "name": "ozone_unittests_ATLAS_TOT-1",
+        "swarming": {},
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
+        "timeout_sec": 10800
+      },
+      {
+        "args": [],
+        "cros_board": "eve",
+        "cros_img": "eve-release/R93-14083.0.0",
+        "name": "ozone_unittests_EVE_TOT",
+        "swarming": {},
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
+        "timeout_sec": 10800
+      },
+      {
+        "args": [],
+        "cros_board": "eve",
+        "cros_img": "eve-release/R92-13982.52.0",
+        "name": "ozone_unittests_EVE_TOT-1",
+        "swarming": {},
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
+        "timeout_sec": 10800
       }
     ]
   },
@@ -1216,13 +1256,23 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R93-14052.0.0",
+        "cros_img": "kevin-release/R93-14083.0.0",
         "name": "lacros_fyi_tast_tests_KEVIN_TOT",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\")",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800
+      },
+      {
+        "args": [],
+        "cros_board": "kevin",
+        "cros_img": "kevin-release/R93-14083.0.0",
+        "name": "ozone_unittests_KEVIN_TOT",
+        "swarming": {},
+        "test": "ozone_unittests",
+        "test_id_prefix": "ninja://ui/ozone:ozone_unittests/",
+        "timeout_sec": 10800
       }
     ]
   }
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 3e2a105..591009e 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -823,13 +823,12 @@
     },
   },
   'mac_retina_amd_gpu_experimental': {
-    # Currently same configuration as stable version below.
     'swarming': {
       'dimensions': {
         'cpu': 'x86-64',
         'gpu': '1002:6821',
         'hidpi': '1',
-        'os': 'Mac-10.14.6',
+        'os': 'Mac-11.4',
         'pool': 'chromium.tests.gpu',
         'display_attached': '1',
       },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 3e2a161..1cbb530 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -4182,6 +4182,9 @@
         'tast_expr': '("group:mainline" && "dep:lacros")',
         'timeout_sec': 10800,
       },
+      'ozone_unittests': {
+        'timeout_sec': 10800,
+      },
     },
 
     'layout_ng_gtests': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index cd99d9e..e7a145d 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -455,7 +455,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.163',
+          'revision': 'version:91.0.4472.164',
         }
       ],
     },
@@ -527,7 +527,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.163',
+          'revision': 'version:91.0.4472.164',
         }
       ],
     },
@@ -599,7 +599,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.163',
+          'revision': 'version:91.0.4472.164',
         }
       ],
     },
@@ -631,35 +631,35 @@
   'CROS_ATLAS_TOT': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_img': 'atlas-release/R93-14052.0.0',
+      'cros_img': 'atlas-release/R93-14083.0.0',
     },
     'identifier': 'ATLAS_TOT',
   },
   'CROS_ATLAS_TOT-1': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_img': 'atlas-release/R92-13982.38.0',
+      'cros_img': 'atlas-release/R92-13982.52.0',
     },
     'identifier': 'ATLAS_TOT-1',
   },
   'CROS_EVE_TOT': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_img': 'eve-release/R93-14052.0.0',
+      'cros_img': 'eve-release/R93-14083.0.0',
     },
     'identifier': 'EVE_TOT',
   },
   'CROS_EVE_TOT-1': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_img': 'eve-release/R92-13982.38.0',
+      'cros_img': 'eve-release/R92-13982.52.0',
     },
     'identifier': 'EVE_TOT-1',
   },
   'CROS_KEVIN_TOT': {
     'skylab': {
       'cros_board': 'kevin',
-      'cros_img': 'kevin-release/R93-14052.0.0',
+      'cros_img': 'kevin-release/R93-14083.0.0',
     },
     'identifier': 'KEVIN_TOT',
   },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index f332f26..4e57e47 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4322,7 +4322,9 @@
         # driver. If it's upgraded, change these test_suites to be the same as
         # 'Mac FYI Retina Release (AMD)'.
         'test_suites': {
-          'gpu_telemetry_tests': 'gpu_noop_sleep_telemetry_test',
+          'gtest_tests': 'gpu_fyi_mac_release_gtests',
+          'gpu_telemetry_tests': 'gpu_fyi_mac_release_telemetry_tests',
+          'isolated_scripts': 'rendering_desktop_representative_perf_tests_isolated_scripts',
         },
       },
       'Mac FYI Experimental Retina Release (NVIDIA)': {
diff --git a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json
index ceabf4a..799898eb 100644
--- a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json
+++ b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json
@@ -146,7 +146,7 @@
     },
     "new_tilings": {
       "ci_095": 0.334,
-      "avg": 19.224,
+      "avg": 22.0,
       "cpu_wall_time_ratio": 0.372,
       "_comment": "Return to 16.692 after crbug.com/1225374"
     },
@@ -209,4 +209,4 @@
       "cpu_wall_time_ratio": 0.48
     }
   }
-}
\ No newline at end of file
+}
diff --git a/testing/test_env.py b/testing/test_env.py
index 9d326ef..e04afa0 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -56,8 +56,8 @@
   return out
 
 
-def get_sanitizer_env(cmd, asan, lsan, msan, tsan, cfi_diag):
-  """Returns the envirnoment flags needed for sanitizer tools."""
+def get_sanitizer_env(asan, lsan, msan, tsan, cfi_diag):
+  """Returns the environment flags needed for sanitizer tools."""
 
   extra_env = {}
 
@@ -102,13 +102,6 @@
     if asan_options:
       extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
 
-    if sys.platform == 'darwin':
-      isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
-      # This is needed because the test binary has @executable_path embedded in
-      # it that the OS tries to resolve to the cache directory and not the
-      # mapped directory.
-      extra_env['DYLD_LIBRARY_PATH'] = str(isolate_output_dir)
-
   if lsan:
     if asan or msan:
       lsan_options = []
@@ -328,7 +321,7 @@
     use_symbolization_script = (asan or msan or cfi_diag or lsan or tsan)
 
   if asan or lsan or msan or tsan or cfi_diag:
-    extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan, cfi_diag))
+    extra_env.update(get_sanitizer_env(asan, lsan, msan, tsan, cfi_diag))
 
   if lsan or tsan:
     # LSan and TSan are not sandbox-friendly.
diff --git a/testing/variations/README.md b/testing/variations/README.md
index 94179da..4349835 100644
--- a/testing/variations/README.md
+++ b/testing/variations/README.md
@@ -48,7 +48,7 @@
 > rely on the [Feature List API][FeatureListAPI] instead. Nonetheless, if a
 > study has a server-side configuration, the study `name` specified here
 > must still match the name specified in the server-side configuration; this is
-> used to implement sanity-checks on the server.
+> used to implement consistency checks on the server.
 
 ### Study Configurations
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 17fd956a..d835978 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1506,6 +1506,21 @@
             ]
         }
     ],
+    "CanvasOutOfProcessRasterization": [
+        {
+            "platforms": [
+                "mac"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "CanvasOopRasterization"
+                    ]
+                }
+            ]
+        }
+    ],
     "CctClientDataHeader": [
         {
             "platforms": [
diff --git a/third_party/android_sdk/cipd/build-tools/31.0.0.yaml b/third_party/android_sdk/cipd/build-tools/31.0.0.yaml
new file mode 100644
index 0000000..a17bf9c
--- /dev/null
+++ b/third_party/android_sdk/cipd/build-tools/31.0.0.yaml
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+package: chromium/third_party/android_sdk/public/build-tools/31.0.0
+description: build-tools Android SDK Build Tools
+root: ../../public/
+data:
+  - dir: build-tools/31.0.0
+# Some tools inspect their argv0 and don't handle CIPD's symlink structure
+# correctly. Install in copy mode so that they can find the other directories
+# relative to themselves.
+install_mode: copy
diff --git a/third_party/android_sdk/cipd/platforms/android-31.yaml b/third_party/android_sdk/cipd/platforms/android-31.yaml
new file mode 100644
index 0000000..e58f010
--- /dev/null
+++ b/third_party/android_sdk/cipd/platforms/android-31.yaml
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+package: chromium/third_party/android_sdk/public/platforms/android-31
+description: platforms Android SDK Platforms library
+root: ../../public/
+data:
+  - dir: platforms/android-31
+# Some tools inspect their argv0 and don't handle CIPD's symlink structure
+# correctly. Install in copy mode so that they can find the other directories
+# relative to themselves.
+install_mode: copy
diff --git a/third_party/android_sdk/cipd/sources/android-31.yaml b/third_party/android_sdk/cipd/sources/android-31.yaml
new file mode 100644
index 0000000..2aafde1
--- /dev/null
+++ b/third_party/android_sdk/cipd/sources/android-31.yaml
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+package: chromium/third_party/android_sdk/public/sources/android-31
+description: sources Android SDK Sources library
+root: ../../public/
+data:
+  - dir: sources/android-31
+# Some tools inspect their argv0 and don't handle CIPD's symlink structure
+# correctly. Install in copy mode so that they can find the other directories
+# relative to themselves.
+install_mode: copy
diff --git a/third_party/android_sdk/cipd/system_images/android-31/google_apis/x86_64.yaml b/third_party/android_sdk/cipd/system_images/android-31/google_apis/x86_64.yaml
new file mode 100644
index 0000000..d2f051b
--- /dev/null
+++ b/third_party/android_sdk/cipd/system_images/android-31/google_apis/x86_64.yaml
@@ -0,0 +1,9 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+package: chromium/third_party/android_sdk/public/system-images/android-31/google_apis/x86_64
+description: system_images;android-31;google_apis;x86_64
+root: ../../../../public/
+data:
+  - dir: system-images/android-31/google_apis/x86_64
diff --git a/third_party/android_sdk/cipd/system_images/android-31/google_apis_playstore/x86_64.yaml b/third_party/android_sdk/cipd/system_images/android-31/google_apis_playstore/x86_64.yaml
new file mode 100644
index 0000000..c6830f0
--- /dev/null
+++ b/third_party/android_sdk/cipd/system_images/android-31/google_apis_playstore/x86_64.yaml
@@ -0,0 +1,9 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+package: chromium/third_party/android_sdk/public/system-images/android-31/google_apis_playstore/x86_64
+description: system_images;android-31;google_apis_playstore;x86_64
+root: ../../../../public/
+data:
+  - dir: system-images/android-31/google_apis_playstore/x86_64
diff --git a/third_party/android_sdk/cipd/system_images/android-S/google_apis/x86_64.yaml b/third_party/android_sdk/cipd/system_images/android-S/google_apis/x86_64.yaml
deleted file mode 100644
index 0adf746..0000000
--- a/third_party/android_sdk/cipd/system_images/android-S/google_apis/x86_64.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-package: chromium/third_party/android_sdk/public/system-images/android-s/google_apis/x86_64
-description: system_images;android-S;google_apis;x86_64
-root: ../../../../public/
-data:
-  - dir: system-images/android-S/google_apis/x86_64
diff --git a/third_party/android_sdk/cipd/system_images/android-S/google_apis_playstore/x86_64.yaml b/third_party/android_sdk/cipd/system_images/android-S/google_apis_playstore/x86_64.yaml
deleted file mode 100644
index 53ea897..0000000
--- a/third_party/android_sdk/cipd/system_images/android-S/google_apis_playstore/x86_64.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-package: chromium/third_party/android_sdk/public/system-images/android-s/google_apis_playstore/x86_64
-description: system_images;android-S;google_apis_playstore;x86_64
-root: ../../../../public/
-data:
-  - dir: system-images/android-S/google_apis_playstore/x86_64
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 0212490b..171bae0e 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -367,6 +367,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding_layout.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_descriptor.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_descriptor.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_dict.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_dict.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_color_state_descriptor.cc",
@@ -453,8 +455,6 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_stencil_face_state.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_binding_layout.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_storage_texture_binding_layout.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain_descriptor.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain_descriptor.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_binding_layout.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_binding_layout.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_descriptor.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index a1caeba..d0f877e 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -934,6 +934,7 @@
           "//third_party/blink/renderer/modules/webgpu/gpu_buffer_binding_layout.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl",
+          "//third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl",
@@ -1006,7 +1007,6 @@
           "//third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_supported_limits.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl",
-          "//third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_texture.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_texture_binding_layout.idl",
           "//third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl",
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc
index 1eeed6c..6397c9b 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -32,7 +32,9 @@
 
 #include <algorithm>
 #include <cmath>
+#include <iterator>
 #include <memory>
+#include <vector>
 
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/animation/animation_effect.h"
@@ -72,6 +74,36 @@
 
 namespace {
 
+constexpr CSSPropertyID kCompositableProperties[] = {
+    CSSPropertyID::kOpacity,   CSSPropertyID::kBackdropFilter,
+    CSSPropertyID::kRotate,    CSSPropertyID::kScale,
+    CSSPropertyID::kTranslate, CSSPropertyID::kTransform,
+    CSSPropertyID::kFilter};
+
+const size_t kNumCompositableCSSProperties =
+    sizeof(kCompositableProperties) / sizeof(kCompositableProperties[0]);
+
+compositor_target_property::Type GetCompositedTransformType(
+    CSSPropertyID property_id) {
+  switch (property_id) {
+    case CSSPropertyID::kRotate:
+      return compositor_target_property::ROTATE;
+
+    case CSSPropertyID::kScale:
+      return compositor_target_property::SCALE;
+
+    case CSSPropertyID::kTranslate:
+      return compositor_target_property::TRANSLATE;
+
+    case CSSPropertyID::kTransform:
+      return compositor_target_property::TRANSFORM;
+
+    default:
+      NOTREACHED();
+      return compositor_target_property::TRANSFORM;
+  }
+}
+
 bool ConsiderAnimationAsIncompatible(const Animation& animation,
                                      const Animation& animation_to_add,
                                      const EffectModel& effect_to_add) {
@@ -257,7 +289,6 @@
   }
 
   PropertyHandleSet properties = keyframe_effect.Properties();
-  unsigned transform_property_count = 0;
   for (const auto& property : properties) {
     if (!property.IsCSSProperty()) {
       // None of the below reasons make any sense if |property| isn't CSS, so we
@@ -275,7 +306,6 @@
         reasons |=
             CheckCanStartTransformAnimationOnCompositorForSVG(*svg_element);
       }
-      transform_property_count++;
     }
 
     const PropertySpecificKeyframeVector& keyframes =
@@ -420,10 +450,6 @@
     reasons |= kCompositorPropertyAnimationsHaveNoEffect;
   }
 
-  // TODO: Support multiple transform property animations on the compositor
-  if (transform_property_count > 1)
-    reasons |= kMultipleTransformAnimationsOnSameTarget;
-
   if (animation_to_add &&
       HasIncompatibleAnimations(target_element, *animation_to_add, effect)) {
     reasons |= kTargetHasIncompatibleAnimations;
@@ -560,37 +586,41 @@
     const Element& target_element,
     const Animation& animation_to_add,
     const EffectModel& effect_to_add) {
-  const bool affects_opacity =
-      effect_to_add.Affects(PropertyHandle(GetCSSPropertyOpacity()));
-  const bool affects_transform = effect_to_add.IsTransformRelatedEffect();
-  const bool affects_filter =
-      effect_to_add.Affects(PropertyHandle(GetCSSPropertyFilter()));
-  const bool affects_backdrop_filter =
-      effect_to_add.Affects(PropertyHandle(GetCSSPropertyBackdropFilter()));
-
   if (!target_element.HasAnimations())
     return;
 
+  bool affects_property[kNumCompositableCSSProperties];
+  for (unsigned i = 0; i < kNumCompositableCSSProperties; i++) {
+    PropertyHandle property =
+        PropertyHandle(CSSProperty::Get(kCompositableProperties[i]));
+    affects_property[i] = effect_to_add.Affects(property);
+  }
+
   ElementAnimations* element_animations = target_element.GetElementAnimations();
   DCHECK(element_animations);
 
   for (const auto& entry : element_animations->Animations()) {
     Animation* attached_animation = entry.key;
+    const auto* effect =
+        DynamicTo<KeyframeEffect>(attached_animation->effect());
+    if (!effect || effect->EffectTarget() != target_element)
+      continue;
+
     if (!ConsiderAnimationAsIncompatible(*attached_animation, animation_to_add,
                                          effect_to_add)) {
       continue;
     }
 
-    if ((affects_opacity && attached_animation->Affects(
-                                target_element, GetCSSPropertyOpacity())) ||
-        (affects_transform &&
-         IsTransformRelatedAnimation(target_element, attached_animation)) ||
-        (affects_filter &&
-         attached_animation->Affects(target_element, GetCSSPropertyFilter())) ||
-        (affects_backdrop_filter &&
-         attached_animation->Affects(target_element,
-                                     GetCSSPropertyBackdropFilter()))) {
-      attached_animation->CancelAnimationOnCompositor();
+    for (unsigned i = 0; i < kNumCompositableCSSProperties; i++) {
+      if (!affects_property[i])
+        continue;
+
+      PropertyHandle property =
+          PropertyHandle(CSSProperty::Get(kCompositableProperties[i]));
+      if (effect->Affects(property)) {
+        attached_animation->CancelAnimationOnCompositor();
+        return;
+      }
     }
   }
 }
@@ -877,7 +907,8 @@
         FloatSize box_size = ComputedStyleUtils::ReferenceBoxForTransform(
                                  *target_element.GetLayoutObject())
                                  .Size();
-        target_property = compositor_target_property::TRANSFORM;
+        target_property =
+            GetCompositedTransformType(property.GetCSSProperty().PropertyID());
         auto transform_curve =
             std::make_unique<CompositorTransformAnimationCurve>();
         AddKeyframesToCurve(*transform_curve, values, box_size);
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 353a6c76..e0cae30 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -1117,25 +1117,6 @@
                                               animation1, *effect1) &
               CompositorAnimations::
                   kTransformRelatedPropertyCannotBeAcceleratedOnTarget);
-
-  StringKeyframeEffectModel* effect2 = CreateKeyframeEffectModel(
-      CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "translateX(-45px)",
-                              0),
-      CreateReplaceOpKeyframe(CSSPropertyID::kRotate, "none", 0),
-      CreateReplaceOpKeyframe(CSSPropertyID::kTransform, "translateX(45px)",
-                              1.0),
-      CreateReplaceOpKeyframe(CSSPropertyID::kRotate, "45deg", 1.0));
-
-  auto* keyframe_effect2 =
-      MakeGarbageCollected<KeyframeEffect>(element_.Get(), effect2, timing_);
-
-  Animation* animation2 = timeline_->Play(keyframe_effect2);
-  effect2->SnapshotAllCompositorKeyframesIfNecessary(*element_.Get(), *style,
-                                                     nullptr);
-
-  EXPECT_TRUE(CheckCanStartEffectOnCompositor(timing_, *element_.Get(),
-                                              animation2, *effect2) &
-              CompositorAnimations::kMultipleTransformAnimationsOnSameTarget);
 }
 
 TEST_P(AnimationCompositorAnimationsTest,
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.cc b/third_party/blink/renderer/core/animation/keyframe_effect.cc
index 3b1953b37..e45902d 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -335,11 +335,6 @@
         effect_target_->GetComputedStyle()->HasOffset())
       reasons |= CompositorAnimations::kTargetHasCSSOffset;
 
-    // Do not put transforms on compositor if more than one of them are defined
-    // in computed style because they need to be explicitly ordered
-    if (HasMultipleTransformProperties())
-      reasons |= CompositorAnimations::kTargetHasMultipleTransformProperties;
-
     reasons |= CompositorAnimations::CheckCanStartAnimationOnCompositor(
         SpecifiedTiming(), *effect_target_, GetAnimation(), *Model(),
         paint_artifact_compositor, animation_playback_rate,
@@ -721,28 +716,11 @@
           return true;
       }
     }
-    return HasMultipleTransformProperties();
   }
 
   return false;
 }
 
-bool KeyframeEffect::HasMultipleTransformProperties() const {
-  if (!effect_target_->GetComputedStyle())
-    return false;
-
-  unsigned transform_property_count = 0;
-  if (effect_target_->GetComputedStyle()->HasTransformOperations())
-    transform_property_count++;
-  if (effect_target_->GetComputedStyle()->Rotate())
-    transform_property_count++;
-  if (effect_target_->GetComputedStyle()->Scale())
-    transform_property_count++;
-  if (effect_target_->GetComputedStyle()->Translate())
-    transform_property_count++;
-  return transform_property_count > 1;
-}
-
 ActiveInterpolationsMap KeyframeEffect::InterpolationsForCommitStyles() {
   // If the associated animation has been removed, it needs to be temporarily
   // reintroduced to the effect stack in order to be including in the
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.h b/third_party/blink/renderer/core/animation/keyframe_effect.h
index 702db6a..710ef28 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect.h
+++ b/third_party/blink/renderer/core/animation/keyframe_effect.h
@@ -165,7 +165,6 @@
       absl::optional<AnimationTimeDelta> inherited_time,
       AnimationTimeDelta time_to_next_iteration) const override;
   bool HasIncompatibleStyle() const;
-  bool HasMultipleTransformProperties() const;
   void RestartRunningAnimationOnCompositor();
 
   Member<Element> effect_target_;
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
index 1c229edbc..569a5f7 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
@@ -499,15 +499,6 @@
   EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                   nullptr, animation_playback_rate) &
               CompositorAnimations::kTargetHasCSSOffset);
-
-  // If the target has multiple transform properties we can't composite it.
-  element->SetInlineStyleProperty(CSSPropertyID::kRotate, "90deg");
-  element->SetInlineStyleProperty(CSSPropertyID::kScale, "2 1");
-  UpdateAllLifecyclePhasesForTest();
-
-  EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
-                  nullptr, animation_playback_rate) &
-              CompositorAnimations::kTargetHasMultipleTransformProperties);
 }
 
 TEST_F(KeyframeEffectTest, TranslationTransformsPreserveAxisAlignment) {
diff --git a/third_party/blink/renderer/core/css/counter_style.cc b/third_party/blink/renderer/core/css/counter_style.cc
index 3a65c4a..ce62f9f 100644
--- a/third_party/blink/renderer/core/css/counter_style.cc
+++ b/third_party/blink/renderer/core/css/counter_style.cc
@@ -2,6 +2,31 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
+ * reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
 #include "third_party/blink/renderer/core/css/counter_style.h"
 
 #include "third_party/blink/renderer/core/css/counter_style_map.h"
@@ -12,7 +37,6 @@
 #include "third_party/blink/renderer/core/css/css_value_pair.h"
 #include "third_party/blink/renderer/core/css/style_rule_counter_style.h"
 #include "third_party/blink/renderer/core/css_value_keywords.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/platform/text/text_break_iterator.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
@@ -172,9 +196,352 @@
   return result;
 }
 
-// TODO(crbug.com/687225): After @counter-style is shipped and the legacy
-// code paths are removed, remove everything else of list_marker_text and move
-// the implementation of the special algorithms here.
+namespace list_marker_text {
+
+// TODO(xiaochengh): Reorganize these legacy implementations. Get rid of the
+// EListStyleType enum, and merge them into their callers if possible.
+
+static void ToHebrewUnder1000(int number, Vector<UChar>& letters) {
+  // FIXME: CSS3 mentions various refinements not implemented here.
+  // FIXME: Should take a look at Mozilla's HebrewToText function (in
+  // nsBulletFrame).
+  DCHECK_GE(number, 0);
+  DCHECK_LT(number, 1000);
+  int four_hundreds = number / 400;
+  for (int i = 0; i < four_hundreds; i++)
+    letters.push_front(1511 + 3);
+  number %= 400;
+  if (number / 100)
+    letters.push_front(1511 + (number / 100) - 1);
+  number %= 100;
+  if (number == 15 || number == 16) {
+    letters.push_front(1487 + 9);
+    letters.push_front(1487 + number - 9);
+  } else {
+    if (int tens = number / 10) {
+      static const UChar kHebrewTens[9] = {1497, 1499, 1500, 1502, 1504,
+                                           1505, 1506, 1508, 1510};
+      letters.push_front(kHebrewTens[tens - 1]);
+    }
+    if (int ones = number % 10)
+      letters.push_front(1487 + ones);
+  }
+}
+
+static String ToHebrew(int number) {
+  // FIXME: CSS3 mentions ways to make this work for much larger numbers.
+  DCHECK_GE(number, 0);
+  DCHECK_LE(number, 999999);
+
+  Vector<UChar> letters;
+
+  if (number == 0) {
+    static const UChar kHebrewZero[3] = {0x05E1, 0x05E4, 0x05D0};
+    letters.Append(kHebrewZero, 3);
+  } else {
+    if (number > 999) {
+      ToHebrewUnder1000(number / 1000, letters);
+      letters.push_front(kHebrewPunctuationGereshCharacter);
+      number = number % 1000;
+    }
+    ToHebrewUnder1000(number, letters);
+  }
+
+  // Since Hebrew is RTL, legacy implementation generates letters in the
+  // reversed ordering, which is actually wrong because characters in a String
+  // should always be in the logical ordering. We re-reverse it so that the
+  // output ordering is correct.
+  std::reverse(letters.begin(), letters.end());
+
+  return String(letters);
+}
+
+static int ToArmenianUnder10000(int number,
+                                bool upper,
+                                bool add_circumflex,
+                                UChar letters[9]) {
+  DCHECK_GE(number, 0);
+  DCHECK_LT(number, 10000);
+  int length = 0;
+
+  int lower_offset = upper ? 0 : 0x0030;
+
+  if (int thousands = number / 1000) {
+    if (thousands == 7) {
+      letters[length++] = 0x0552 + lower_offset;
+      if (add_circumflex)
+        letters[length++] = 0x0302;
+    } else {
+      letters[length++] = (0x054C - 1 + lower_offset) + thousands;
+      if (add_circumflex)
+        letters[length++] = 0x0302;
+    }
+  }
+
+  if (int hundreds = (number / 100) % 10) {
+    letters[length++] = (0x0543 - 1 + lower_offset) + hundreds;
+    if (add_circumflex)
+      letters[length++] = 0x0302;
+  }
+
+  if (int tens = (number / 10) % 10) {
+    letters[length++] = (0x053A - 1 + lower_offset) + tens;
+    if (add_circumflex)
+      letters[length++] = 0x0302;
+  }
+
+  if (int ones = number % 10) {
+    letters[length++] = (0x531 - 1 + lower_offset) + ones;
+    if (add_circumflex)
+      letters[length++] = 0x0302;
+  }
+
+  return length;
+}
+
+static String ToArmenian(int number, bool upper) {
+  DCHECK_GE(number, 1);
+  DCHECK_LE(number, 99999999);
+
+  const int kLettersSize = 18;  // twice what toArmenianUnder10000 needs
+  UChar letters[kLettersSize];
+
+  int length = ToArmenianUnder10000(number / 10000, upper, true, letters);
+  length +=
+      ToArmenianUnder10000(number % 10000, upper, false, letters + length);
+
+  DCHECK_LE(length, kLettersSize);
+  return String(letters, length);
+}
+
+enum CJKLang { kChinese = 1, kKorean, kJapanese };
+
+enum CJKStyle { kFormal, kInformal };
+
+// The table uses the order from the CSS3 specification:
+// first 3 group markers, then 3 digit markers, then ten digits, then negative
+// symbols.
+static String ToCJKIdeographic(int number,
+                               const UChar table[26],
+                               CJKStyle cjk_style) {
+  enum AbstractCJKChar {
+    kNoChar = 0,
+    kLang = 0,
+    // FourthGroupMarker for simplified chinese has two codepoints, to simplify
+    // the main algorithm below use two codepoints for all group markers.
+    kSecondGroupMarker = 1,
+    kThirdGroupMarker = 3,
+    kFourthGroupMarker = 5,
+    kSecondDigitMarker = 7,
+    kThirdDigitMarker,
+    kFourthDigitMarker,
+    kDigit0,
+    kDigit1,
+    kDigit2,
+    kDigit3,
+    kDigit4,
+    kDigit5,
+    kDigit6,
+    kDigit7,
+    kDigit8,
+    kDigit9,
+    kNeg1,
+    kNeg2,
+    kNeg3,
+    kNeg4,
+    kNeg5
+  };
+
+  if (number == 0)
+    return String(&table[kDigit0], 1);
+
+  const bool negative = number < 0;
+  if (negative) {
+    // Negating the most negative integer (INT_MIN) doesn't work, since it has
+    // no positive counterpart. Deal with that here, manually.
+    if (UNLIKELY(number == INT_MIN))
+      number = INT_MAX;
+    else
+      number = -number;
+  }
+
+  const int kGroupLength =
+      9;  // 4 digits, 3 digit markers, group marker of size 2.
+  const int kBufferLength = 4 * kGroupLength;
+  AbstractCJKChar buffer[kBufferLength] = {kNoChar};
+
+  for (int i = 0; i < 4; ++i) {
+    int group_value = number % 10000;
+    number /= 10000;
+
+    // Process least-significant group first, but put it in the buffer last.
+    AbstractCJKChar* group = &buffer[(3 - i) * kGroupLength];
+
+    if (group_value && i) {
+      group[8] = static_cast<AbstractCJKChar>(kSecondGroupMarker + i);
+      group[7] = static_cast<AbstractCJKChar>(kSecondGroupMarker - 1 + i);
+    }
+
+    // Put in the four digits and digit markers for any non-zero digits.
+    int digit_value = (group_value % 10);
+    bool trailing_zero = table[kLang] == kChinese && !digit_value;
+    if (digit_value) {
+      bool drop_one = table[kLang] == kKorean && cjk_style == kInformal &&
+                      digit_value == 1 && i > 0;
+      if (!drop_one)
+        group[6] = static_cast<AbstractCJKChar>(kDigit0 + (group_value % 10));
+    }
+    if (number != 0 || group_value > 9) {
+      digit_value = ((group_value / 10) % 10);
+      bool drop_one =
+          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+        group[4] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+      trailing_zero &= !digit_value;
+      if (digit_value)
+        group[5] = kSecondDigitMarker;
+    }
+    if (number != 0 || group_value > 99) {
+      digit_value = ((group_value / 100) % 10);
+      bool drop_one =
+          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+        group[2] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+      trailing_zero &= !digit_value;
+      if (digit_value)
+        group[3] = kThirdDigitMarker;
+    }
+    if (number != 0 || group_value > 999) {
+      digit_value = group_value / 1000;
+      bool drop_one =
+          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
+      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
+        group[0] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
+      if (digit_value)
+        group[1] = kFourthDigitMarker;
+    }
+
+    if (trailing_zero && i > 0) {
+      group[6] = group[7];
+      group[7] = group[8];
+      group[8] = kDigit0;
+    }
+
+    // Remove the tens digit, but leave the marker, for any group that has
+    // a value of less than 20.
+    if (table[kLang] == kChinese && cjk_style == kInformal &&
+        group_value < 20) {
+      DCHECK(group[4] == kNoChar || group[4] == kDigit0 || group[4] == kDigit1);
+      group[4] = kNoChar;
+    }
+
+    if (number == 0)
+      break;
+  }
+
+  // Convert into characters, omitting consecutive runs of Digit0 and
+  // any trailing Digit0.
+  int length = 0;
+  const int kMaxLengthForNegativeSymbols = 5;
+  UChar characters[kBufferLength + kMaxLengthForNegativeSymbols];
+  AbstractCJKChar last = kNoChar;
+  if (negative) {
+    while (UChar a = table[kNeg1 + length])
+      characters[length++] = a;
+  }
+  for (int i = 0; i < kBufferLength; ++i) {
+    AbstractCJKChar a = buffer[i];
+    if (a != kNoChar) {
+      if (a != kDigit0 || (table[kLang] == kChinese && last != kDigit0)) {
+        UChar new_char = table[a];
+        if (new_char != kNoChar) {
+          characters[length++] = table[a];
+          if (table[kLang] == kKorean &&
+              (a == kSecondGroupMarker || a == kThirdGroupMarker ||
+               a == kFourthGroupMarker))
+            characters[length++] = ' ';
+        }
+      }
+      last = a;
+    }
+  }
+  if ((table[kLang] == kChinese && last == kDigit0) ||
+      characters[length - 1] == ' ')
+    --length;
+
+  return String(characters, length);
+}
+
+String GetText(EListStyleType type, int count) {
+  switch (type) {
+    case EListStyleType::kKoreanHangulFormal: {
+      static const UChar kKoreanHangulFormalTable[26] = {
+          kKorean, 0xB9CC, 0x0000, 0xC5B5, 0x0000, 0xC870, 0x0000,
+          0xC2ED,  0xBC31, 0xCC9C, 0xC601, 0xC77C, 0xC774, 0xC0BC,
+          0xC0AC,  0xC624, 0xC721, 0xCE60, 0xD314, 0xAD6C, 0xB9C8,
+          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
+      return ToCJKIdeographic(count, kKoreanHangulFormalTable, kFormal);
+    }
+    case EListStyleType::kKoreanHanjaFormal: {
+      static const UChar kKoreanHanjaFormalTable[26] = {
+          kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+          0x62FE,  0x767E, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3,
+          0x56DB,  0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
+          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
+      return ToCJKIdeographic(count, kKoreanHanjaFormalTable, kFormal);
+    }
+    case EListStyleType::kKoreanHanjaInformal: {
+      static const UChar kKoreanHanjaInformalTable[26] = {
+          kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
+          0x5341,  0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
+          0x56DB,  0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
+          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
+      return ToCJKIdeographic(count, kKoreanHanjaInformalTable, kInformal);
+    }
+    case EListStyleType::kTradChineseInformal: {
+      static const UChar kTraditionalChineseInformalTable[22] = {
+          kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x5341,
+          0x767E,   0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
+          0x516D,   0x4E03, 0x516B, 0x4E5D, 0x8CA0, 0x0000};
+      return ToCJKIdeographic(count, kTraditionalChineseInformalTable,
+                              kInformal);
+    }
+    case EListStyleType::kSimpChineseInformal: {
+      static const UChar kSimpleChineseInformalTable[22] = {
+          kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x5341,
+          0x767E,   0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
+          0x516D,   0x4E03, 0x516B, 0x4E5D, 0x8D1F, 0x0000};
+      return ToCJKIdeographic(count, kSimpleChineseInformalTable, kInformal);
+    }
+    case EListStyleType::kTradChineseFormal: {
+      static const UChar kTraditionalChineseFormalTable[22] = {
+          kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x62FE,
+          0x4F70,   0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3, 0x8086, 0x4F0D,
+          0x9678,   0x67D2, 0x634C, 0x7396, 0x8CA0, 0x0000};
+      return ToCJKIdeographic(count, kTraditionalChineseFormalTable, kFormal);
+    }
+    case EListStyleType::kSimpChineseFormal: {
+      static const UChar kSimpleChineseFormalTable[22] = {
+          kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x62FE,
+          0x4F70,   0x4EDF, 0x96F6, 0x58F9, 0x8D30, 0x53C1, 0x8086, 0x4F0D,
+          0x9646,   0x67D2, 0x634C, 0x7396, 0x8D1F, 0x0000};
+      return ToCJKIdeographic(count, kSimpleChineseFormalTable, kFormal);
+    }
+
+    case EListStyleType::kUpperArmenian:
+      return ToArmenian(count, true);
+    case EListStyleType::kLowerArmenian:
+      return ToArmenian(count, false);
+    case EListStyleType::kHebrew:
+      return ToHebrew(count);
+
+    default:
+      NOTREACHED();
+      return "";
+  }
+}
+
+}  // namespace list_marker_text
 
 String HebrewAlgorithm(unsigned value) {
   if (value > 999999)
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index 37c1b9a..3cfc916 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -161,8 +161,12 @@
   }
   std::unique_ptr<EventTiming> eventTiming;
   LocalFrame* frame = node_->GetDocument().GetFrame();
-  if (frame && frame->DomWindow())
+  if (frame && frame->DomWindow()) {
     eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
+    // TODO(hbsong): Calculate First Input Delay for filtered events.
+    EventTiming::HandleInputDelay(frame->DomWindow(), *event_);
+  }
+
   if (event_->type() == event_type_names::kChange && event_->isTrusted() &&
       view_) {
     view_->GetLayoutShiftTracker().NotifyChangeEvent();
@@ -226,8 +230,6 @@
   }
   DispatchEventPostProcess(activation_target,
                            pre_dispatch_event_handler_result);
-  if (eventTiming)
-    eventTiming->DidDispatchEvent(*event_, node_->GetDocument());
 
   return EventTarget::GetDispatchEventResult(*event_);
 }
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc
index 5d6da26..bdebcfc 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -313,6 +313,7 @@
     bool needs_overscroll_effect_node = !MaximumScrollOffset().IsZero();
     if (needs_overscroll_effect_node && !overscroll_elasticity_effect_node_) {
       EffectPaintPropertyNode::State state;
+      state.output_clip = context.current.clip;
       state.local_transform_space = transform_parent;
       state.direct_compositing_reasons =
           CompositingReason::kActiveFilterAnimation;
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc b/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
index 4b1fa07..1f2e68e 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_performance_monitor.cc
@@ -110,7 +110,7 @@
       return kContextTypeName_WebGL;
     case CanvasRenderingContext::kContextWebgl2:
       return kContextTypeName_WebGL2;
-    case CanvasRenderingContext::kContextGPUPresent:
+    case CanvasRenderingContext::kContextWebGPU:
       return kContextTypeName_WebGPU;
     case CanvasRenderingContext::kContextImageBitmap:
       return kContextTypeName_ImageBitmap;
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
index 92ee891..f404040 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -132,9 +132,10 @@
     return kContextWebgl2;
   if (id == "bitmaprenderer")
     return kContextImageBitmap;
-  if (id == "gpupresent" &&
+  // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+  if ((id == "webgpu" || id == "gpupresent") &&
       RuntimeEnabledFeatures::WebGPUEnabled(execution_context))
-    return kContextGPUPresent;
+    return kContextWebGPU;
   return kContextTypeUnknown;
 }
 
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
index 58b5517d..1f4b07c 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -75,7 +75,7 @@
     kContextImageBitmap = 5,
     kContextXRPresent = 6,
     // WebGL2Compute used to be 7.
-    kContextGPUPresent = 8,  // WebGPU
+    kContextWebGPU = 8,  // WebGPU
     kContextTypeUnknown = 9,
     kMaxValue = kContextTypeUnknown,
   };
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 4e899fa..64bd5147 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -82,6 +82,7 @@
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
 #include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/hit_test_canvas_result.h"
 #include "third_party/blink/renderer/core/layout/layout_html_canvas.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -329,6 +330,15 @@
     return nullptr;
   }
 
+  // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+  if (type == "gpupresent") {
+    auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+        mojom::blink::ConsoleMessageSource::kRendering,
+        mojom::blink::ConsoleMessageLevel::kWarning,
+        "The context type 'gpupresent' is deprecated. Use 'webgpu' instead.");
+    GetExecutionContext()->AddConsoleMessage(console_message);
+  }
+
   // Log the aliased context type used.
   if (!context_) {
     UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.ContextType", context_type);
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 6235530..426b1113 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -48,6 +48,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
+#include "third_party/blink/renderer/core/timing/event_timing.h"
 #include "third_party/blink/renderer/platform/geometry/float_quad.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
 #include "ui/display/screen_info.h"
@@ -296,8 +297,9 @@
          mouse_event_type == event_type_names::kClick ||
          mouse_event_type == event_type_names::kAuxclick);
 
-  if (target && target->ToNode() &&
-      (!check_for_listener || target->HasEventListeners(mouse_event_type))) {
+  WebInputEventResult input_event_result = WebInputEventResult::kNotHandled;
+
+  if (target && target->ToNode()) {
     Node* target_node = target->ToNode();
     int click_count = 0;
     if (mouse_event_type == event_type_names::kMouseup ||
@@ -306,9 +308,9 @@
         mouse_event_type == event_type_names::kAuxclick) {
       click_count = click_count_;
     }
-
-    DispatchEventResult dispatch_result;
-
+    std::unique_ptr<EventTiming> event_timing;
+    bool should_dispatch =
+        !check_for_listener || target->HasEventListeners(mouse_event_type);
     if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
         (mouse_event_type == event_type_names::kContextmenu ||
          mouse_event_type == event_type_names::kClick ||
@@ -324,7 +326,12 @@
           mouse_event.FromTouch() ? MouseEvent::kFromTouch
                                   : MouseEvent::kRealOrIndistinguishable,
           mouse_event.menu_source_type);
-      dispatch_result = target->DispatchEvent(*event);
+      if (frame_ && frame_->DomWindow())
+        event_timing = EventTiming::Create(frame_->DomWindow(), *event);
+      if (should_dispatch) {
+        input_event_result = event_handling_util::ToWebInputEventResult(
+            target->DispatchEvent(*event));
+      }
     } else {
       MouseEventInit* initializer = MouseEventInit::Create();
       SetMouseEventAttributes(initializer, target_node, mouse_event_type,
@@ -335,13 +342,16 @@
           mouse_event.FromTouch() ? MouseEvent::kFromTouch
                                   : MouseEvent::kRealOrIndistinguishable,
           mouse_event.menu_source_type);
-
-      dispatch_result = target->DispatchEvent(*event);
+      if (frame_ && frame_->DomWindow())
+        event_timing = EventTiming::Create(frame_->DomWindow(), *event);
+      if (should_dispatch) {
+        input_event_result = event_handling_util::ToWebInputEventResult(
+            target->DispatchEvent(*event));
+      }
     }
-
-    return event_handling_util::ToWebInputEventResult(dispatch_result);
   }
-  return WebInputEventResult::kNotHandled;
+
+  return input_event_result;
 }
 
 WebInputEventResult MouseEventManager::SetMousePositionAndDispatchMouseEvent(
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager.cc b/third_party/blink/renderer/core/input/pointer_event_manager.cc
index 8fb0b9fa..f83226ce 100644
--- a/third_party/blink/renderer/core/input/pointer_event_manager.cc
+++ b/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -183,14 +183,9 @@
   bool should_filter = ShouldFilterEvent(pointer_event);
   // We are about to dispatch this event. It has to be trusted at this point.
   pointer_event->SetTrusted(true);
-
-  if (frame_ && frame_->DomWindow()) {
-    WindowPerformance* performance =
-        DOMWindowPerformance::performance(*(frame_->DomWindow()));
-    if (performance && EventTiming::IsEventTypeForEventTiming(*pointer_event)) {
-      performance->eventCounts()->Add(event_type);
-    }
-  }
+  std::unique_ptr<EventTiming> event_timing;
+  if (frame_ && frame_->DomWindow())
+    event_timing = EventTiming::Create(frame_->DomWindow(), *pointer_event);
 
   if (should_filter &&
       !HasPointerEventListener(frame_->GetEventHandlerRegistry()))
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni
index 3c0ad01..d3af747 100644
--- a/third_party/blink/renderer/core/layout/build.gni
+++ b/third_party/blink/renderer/core/layout/build.gni
@@ -260,8 +260,6 @@
   "line/word_measurement.h",
   "list_marker.cc",
   "list_marker.h",
-  "list_marker_text.cc",
-  "list_marker_text.h",
   "map_coordinates_flags.h",
   "min_max_sizes.cc",
   "min_max_sizes.h",
diff --git a/third_party/blink/renderer/core/layout/layout_counter.cc b/third_party/blink/renderer/core/layout/layout_counter.cc
index 75b23b2..41fb30a 100644
--- a/third_party/blink/renderer/core/layout/layout_counter.cc
+++ b/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -37,7 +37,6 @@
 #include "third_party/blink/renderer/core/layout/counter_node.h"
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.cc b/third_party/blink/renderer/core/layout/layout_list_marker.cc
index 5384103..06be8cb 100644
--- a/third_party/blink/renderer/core/layout/layout_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/layout_list_marker.cc
@@ -31,7 +31,6 @@
 #include "third_party/blink/renderer/core/layout/layout_analyzer.h"
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/core/paint/list_marker_painter.h"
 #include "third_party/blink/renderer/core/style/list_style_type_data.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
diff --git a/third_party/blink/renderer/core/layout/list_marker.cc b/third_party/blink/renderer/core/layout/list_marker.cc
index 0fd24949..2bd4119 100644
--- a/third_party/blink/renderer/core/layout/list_marker.cc
+++ b/third_party/blink/renderer/core/layout/list_marker.cc
@@ -11,7 +11,6 @@
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_list_marker_image.h"
 #include "third_party/blink/renderer/core/layout/layout_outside_list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
diff --git a/third_party/blink/renderer/core/layout/list_marker_text.cc b/third_party/blink/renderer/core/layout/list_marker_text.cc
deleted file mode 100644
index be15c865..0000000
--- a/third_party/blink/renderer/core/layout/list_marker_text.cc
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
- * reserved.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
- * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
-
-#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-namespace list_marker_text {
-
-enum SequenceType { kNumericSequence, kAlphabeticSequence };
-
-static String ToRoman(int number, bool upper) {
-  // FIXME: CSS3 describes how to make this work for much larger numbers,
-  // using overbars and special characters. It also specifies the characters
-  // in the range U+2160 to U+217F instead of standard ASCII ones.
-  DCHECK_GE(number, 1);
-  DCHECK_LE(number, 3999);
-
-  // Big enough to store largest roman number less than 3999 which
-  // is 3888 (MMMDCCCLXXXVIII)
-  const int kLettersSize = 15;
-  LChar letters[kLettersSize];
-
-  int length = 0;
-  const LChar kLdigits[] = {'i', 'v', 'x', 'l', 'c', 'd', 'm'};
-  const LChar kUdigits[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
-  const LChar* digits = upper ? kUdigits : kLdigits;
-  int d = 0;
-  do {
-    int num = number % 10;
-    if (num % 5 < 4)
-      for (int i = num % 5; i > 0; i--)
-        letters[kLettersSize - ++length] = digits[d];
-    if (num >= 4 && num <= 8)
-      letters[kLettersSize - ++length] = digits[d + 1];
-    if (num == 9)
-      letters[kLettersSize - ++length] = digits[d + 2];
-    if (num % 5 == 4)
-      letters[kLettersSize - ++length] = digits[d];
-    number /= 10;
-    d += 2;
-  } while (number);
-
-  DCHECK_LE(length, kLettersSize);
-  return String(&letters[kLettersSize - length], length);
-}
-
-// The typedef is needed because taking sizeof(number) in the const expression
-// below doesn't work with some compilers. This is likely the case because of
-// the template.
-typedef int numberType;
-
-template <typename CharacterType>
-static inline String ToAlphabeticOrNumeric(numberType number,
-                                           const CharacterType* sequence,
-                                           unsigned sequence_size,
-                                           SequenceType type) {
-  DCHECK_GE(sequence_size, 2u);
-
-  // Binary is the worst case; requires one character per bit plus a minus sign.
-  const int kLettersSize = sizeof(numberType) * 8 + 1;
-
-  CharacterType letters[kLettersSize];
-
-  bool is_negative_number = false;
-  unsigned number_shadow = number;
-  if (type == kAlphabeticSequence) {
-    DCHECK_GT(number, 0);
-    --number_shadow;
-  } else if (number < 0) {
-    number_shadow = -number;
-    is_negative_number = true;
-  }
-  letters[kLettersSize - 1] = sequence[number_shadow % sequence_size];
-  int length = 1;
-
-  if (type == kAlphabeticSequence) {
-    while ((number_shadow /= sequence_size) > 0) {
-      --number_shadow;
-      letters[kLettersSize - ++length] =
-          sequence[number_shadow % sequence_size];
-    }
-  } else {
-    while ((number_shadow /= sequence_size) > 0)
-      letters[kLettersSize - ++length] =
-          sequence[number_shadow % sequence_size];
-  }
-  if (is_negative_number)
-    letters[kLettersSize - ++length] = kHyphenMinusCharacter;
-
-  DCHECK_LE(length, kLettersSize);
-  return String(&letters[kLettersSize - length], length);
-}
-
-template <typename CharacterType>
-static String ToAlphabetic(int number,
-                           const CharacterType* alphabet,
-                           unsigned alphabet_size) {
-  return ToAlphabeticOrNumeric(number, alphabet, alphabet_size,
-                               kAlphabeticSequence);
-}
-
-template <typename CharacterType>
-static String ToNumeric(int number,
-                        const CharacterType* numerals,
-                        unsigned numerals_size) {
-  return ToAlphabeticOrNumeric(number, numerals, numerals_size,
-                               kNumericSequence);
-}
-
-template <typename CharacterType, size_t size>
-static inline String ToAlphabetic(int number,
-                                  const CharacterType (&alphabet)[size]) {
-  return ToAlphabetic(number, alphabet, size);
-}
-
-template <typename CharacterType, size_t size>
-static inline String ToNumeric(int number,
-                               const CharacterType (&alphabet)[size]) {
-  return ToNumeric(number, alphabet, size);
-}
-
-static void ToHebrewUnder1000(int number, Vector<UChar>& letters) {
-  // FIXME: CSS3 mentions various refinements not implemented here.
-  // FIXME: Should take a look at Mozilla's HebrewToText function (in
-  // nsBulletFrame).
-  DCHECK_GE(number, 0);
-  DCHECK_LT(number, 1000);
-  int four_hundreds = number / 400;
-  for (int i = 0; i < four_hundreds; i++)
-    letters.push_front(1511 + 3);
-  number %= 400;
-  if (number / 100)
-    letters.push_front(1511 + (number / 100) - 1);
-  number %= 100;
-  if (number == 15 || number == 16) {
-    letters.push_front(1487 + 9);
-    letters.push_front(1487 + number - 9);
-  } else {
-    if (int tens = number / 10) {
-      static const UChar kHebrewTens[9] = {1497, 1499, 1500, 1502, 1504,
-                                           1505, 1506, 1508, 1510};
-      letters.push_front(kHebrewTens[tens - 1]);
-    }
-    if (int ones = number % 10)
-      letters.push_front(1487 + ones);
-  }
-}
-
-static String ToHebrew(int number) {
-  // FIXME: CSS3 mentions ways to make this work for much larger numbers.
-  DCHECK_GE(number, 0);
-  DCHECK_LE(number, 999999);
-
-  Vector<UChar> letters;
-
-  if (number == 0) {
-    static const UChar kHebrewZero[3] = {0x05E1, 0x05E4, 0x05D0};
-    letters.Append(kHebrewZero, 3);
-  } else {
-    if (number > 999) {
-      ToHebrewUnder1000(number / 1000, letters);
-      letters.push_front(kHebrewPunctuationGereshCharacter);
-      number = number % 1000;
-    }
-    ToHebrewUnder1000(number, letters);
-  }
-
-  // Since Hebrew is RTL, legacy implementation generates letters in the
-  // reversed ordering, which is actually wrong because characters in a String
-  // should always be in the logical ordering. We re-reverse it so that the
-  // output ordering is correct.
-  std::reverse(letters.begin(), letters.end());
-
-  return String(letters);
-}
-
-static int ToArmenianUnder10000(int number,
-                                bool upper,
-                                bool add_circumflex,
-                                UChar letters[9]) {
-  DCHECK_GE(number, 0);
-  DCHECK_LT(number, 10000);
-  int length = 0;
-
-  int lower_offset = upper ? 0 : 0x0030;
-
-  if (int thousands = number / 1000) {
-    if (thousands == 7) {
-      letters[length++] = 0x0552 + lower_offset;
-      if (add_circumflex)
-        letters[length++] = 0x0302;
-    } else {
-      letters[length++] = (0x054C - 1 + lower_offset) + thousands;
-      if (add_circumflex)
-        letters[length++] = 0x0302;
-    }
-  }
-
-  if (int hundreds = (number / 100) % 10) {
-    letters[length++] = (0x0543 - 1 + lower_offset) + hundreds;
-    if (add_circumflex)
-      letters[length++] = 0x0302;
-  }
-
-  if (int tens = (number / 10) % 10) {
-    letters[length++] = (0x053A - 1 + lower_offset) + tens;
-    if (add_circumflex)
-      letters[length++] = 0x0302;
-  }
-
-  if (int ones = number % 10) {
-    letters[length++] = (0x531 - 1 + lower_offset) + ones;
-    if (add_circumflex)
-      letters[length++] = 0x0302;
-  }
-
-  return length;
-}
-
-static String ToArmenian(int number, bool upper) {
-  DCHECK_GE(number, 1);
-  DCHECK_LE(number, 99999999);
-
-  const int kLettersSize = 18;  // twice what toArmenianUnder10000 needs
-  UChar letters[kLettersSize];
-
-  int length = ToArmenianUnder10000(number / 10000, upper, true, letters);
-  length +=
-      ToArmenianUnder10000(number % 10000, upper, false, letters + length);
-
-  DCHECK_LE(length, kLettersSize);
-  return String(letters, length);
-}
-
-static String ToGeorgian(int number) {
-  DCHECK_GE(number, 1);
-  DCHECK_LE(number, 19999);
-
-  const int kLettersSize = 5;
-  UChar letters[kLettersSize];
-
-  int length = 0;
-
-  if (number > 9999)
-    letters[length++] = 0x10F5;
-
-  if (int thousands = (number / 1000) % 10) {
-    static const UChar kGeorgianThousands[9] = {
-        0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0};
-    letters[length++] = kGeorgianThousands[thousands - 1];
-  }
-
-  if (int hundreds = (number / 100) % 10) {
-    static const UChar kGeorgianHundreds[9] = {
-        0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8};
-    letters[length++] = kGeorgianHundreds[hundreds - 1];
-  }
-
-  if (int tens = (number / 10) % 10) {
-    static const UChar kGeorgianTens[9] = {
-        0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF};
-    letters[length++] = kGeorgianTens[tens - 1];
-  }
-
-  if (int ones = number % 10) {
-    static const UChar kGeorgianOnes[9] = {
-        0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7};
-    letters[length++] = kGeorgianOnes[ones - 1];
-  }
-
-  DCHECK_LE(length, kLettersSize);
-  return String(letters, length);
-}
-
-enum CJKLang { kChinese = 1, kKorean, kJapanese };
-
-enum CJKStyle { kFormal, kInformal };
-
-// The table uses the order from the CSS3 specification:
-// first 3 group markers, then 3 digit markers, then ten digits, then negative
-// symbols.
-static String ToCJKIdeographic(int number,
-                               const UChar table[26],
-                               CJKStyle cjk_style) {
-  enum AbstractCJKChar {
-    kNoChar = 0,
-    kLang = 0,
-    // FourthGroupMarker for simplified chinese has two codepoints, to simplify
-    // the main algorithm below use two codepoints for all group markers.
-    kSecondGroupMarker = 1,
-    kThirdGroupMarker = 3,
-    kFourthGroupMarker = 5,
-    kSecondDigitMarker = 7,
-    kThirdDigitMarker,
-    kFourthDigitMarker,
-    kDigit0,
-    kDigit1,
-    kDigit2,
-    kDigit3,
-    kDigit4,
-    kDigit5,
-    kDigit6,
-    kDigit7,
-    kDigit8,
-    kDigit9,
-    kNeg1,
-    kNeg2,
-    kNeg3,
-    kNeg4,
-    kNeg5
-  };
-
-  if (number == 0)
-    return String(&table[kDigit0], 1);
-
-  const bool negative = number < 0;
-  if (negative) {
-    // Negating the most negative integer (INT_MIN) doesn't work, since it has
-    // no positive counterpart. Deal with that here, manually.
-    if (UNLIKELY(number == INT_MIN))
-      number = INT_MAX;
-    else
-      number = -number;
-  }
-
-  const int kGroupLength =
-      9;  // 4 digits, 3 digit markers, group marker of size 2.
-  const int kBufferLength = 4 * kGroupLength;
-  AbstractCJKChar buffer[kBufferLength] = {kNoChar};
-
-  for (int i = 0; i < 4; ++i) {
-    int group_value = number % 10000;
-    number /= 10000;
-
-    // Process least-significant group first, but put it in the buffer last.
-    AbstractCJKChar* group = &buffer[(3 - i) * kGroupLength];
-
-    if (group_value && i) {
-      group[8] = static_cast<AbstractCJKChar>(kSecondGroupMarker + i);
-      group[7] = static_cast<AbstractCJKChar>(kSecondGroupMarker - 1 + i);
-    }
-
-    // Put in the four digits and digit markers for any non-zero digits.
-    int digit_value = (group_value % 10);
-    bool trailing_zero = table[kLang] == kChinese && !digit_value;
-    if (digit_value) {
-      bool drop_one = table[kLang] == kKorean && cjk_style == kInformal &&
-                      digit_value == 1 && i > 0;
-      if (!drop_one)
-        group[6] = static_cast<AbstractCJKChar>(kDigit0 + (group_value % 10));
-    }
-    if (number != 0 || group_value > 9) {
-      digit_value = ((group_value / 10) % 10);
-      bool drop_one =
-          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
-      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
-        group[4] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
-      trailing_zero &= !digit_value;
-      if (digit_value)
-        group[5] = kSecondDigitMarker;
-    }
-    if (number != 0 || group_value > 99) {
-      digit_value = ((group_value / 100) % 10);
-      bool drop_one =
-          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
-      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
-        group[2] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
-      trailing_zero &= !digit_value;
-      if (digit_value)
-        group[3] = kThirdDigitMarker;
-    }
-    if (number != 0 || group_value > 999) {
-      digit_value = group_value / 1000;
-      bool drop_one =
-          table[kLang] == kKorean && cjk_style == kInformal && digit_value == 1;
-      if ((digit_value && !drop_one) || (!digit_value && !trailing_zero))
-        group[0] = static_cast<AbstractCJKChar>(kDigit0 + digit_value);
-      if (digit_value)
-        group[1] = kFourthDigitMarker;
-    }
-
-    if (trailing_zero && i > 0) {
-      group[6] = group[7];
-      group[7] = group[8];
-      group[8] = kDigit0;
-    }
-
-    // Remove the tens digit, but leave the marker, for any group that has
-    // a value of less than 20.
-    if (table[kLang] == kChinese && cjk_style == kInformal &&
-        group_value < 20) {
-      DCHECK(group[4] == kNoChar || group[4] == kDigit0 || group[4] == kDigit1);
-      group[4] = kNoChar;
-    }
-
-    if (number == 0)
-      break;
-  }
-
-  // Convert into characters, omitting consecutive runs of Digit0 and
-  // any trailing Digit0.
-  int length = 0;
-  const int kMaxLengthForNegativeSymbols = 5;
-  UChar characters[kBufferLength + kMaxLengthForNegativeSymbols];
-  AbstractCJKChar last = kNoChar;
-  if (negative) {
-    while (UChar a = table[kNeg1 + length])
-      characters[length++] = a;
-  }
-  for (int i = 0; i < kBufferLength; ++i) {
-    AbstractCJKChar a = buffer[i];
-    if (a != kNoChar) {
-      if (a != kDigit0 || (table[kLang] == kChinese && last != kDigit0)) {
-        UChar new_char = table[a];
-        if (new_char != kNoChar) {
-          characters[length++] = table[a];
-          if (table[kLang] == kKorean &&
-              (a == kSecondGroupMarker || a == kThirdGroupMarker ||
-               a == kFourthGroupMarker))
-            characters[length++] = ' ';
-        }
-      }
-      last = a;
-    }
-  }
-  if ((table[kLang] == kChinese && last == kDigit0) ||
-      characters[length - 1] == ' ')
-    --length;
-
-  return String(characters, length);
-}
-
-static EListStyleType EffectiveListMarkerType(EListStyleType type, int count) {
-  // Note, the following switch statement has been explicitly grouped
-  // by list-style-type ordinal range.
-  switch (type) {
-    case EListStyleType::kArabicIndic:
-    case EListStyleType::kBengali:
-    case EListStyleType::kCambodian:
-    case EListStyleType::kCircle:
-    case EListStyleType::kDecimalLeadingZero:
-    case EListStyleType::kDecimal:
-    case EListStyleType::kDevanagari:
-    case EListStyleType::kDisc:
-    case EListStyleType::kDisclosureClosed:
-    case EListStyleType::kDisclosureOpen:
-    case EListStyleType::kGujarati:
-    case EListStyleType::kGurmukhi:
-    case EListStyleType::kKannada:
-    case EListStyleType::kKhmer:
-    case EListStyleType::kLao:
-    case EListStyleType::kMalayalam:
-    case EListStyleType::kMongolian:
-    case EListStyleType::kMyanmar:
-    case EListStyleType::kNone:
-    case EListStyleType::kOriya:
-    case EListStyleType::kPersian:
-    case EListStyleType::kSquare:
-    case EListStyleType::kTelugu:
-    case EListStyleType::kThai:
-    case EListStyleType::kTibetan:
-    case EListStyleType::kUrdu:
-    case EListStyleType::kKoreanHangulFormal:
-    case EListStyleType::kKoreanHanjaFormal:
-    case EListStyleType::kKoreanHanjaInformal:
-    case EListStyleType::kCjkIdeographic:
-    case EListStyleType::kSimpChineseFormal:
-    case EListStyleType::kSimpChineseInformal:
-    case EListStyleType::kTradChineseFormal:
-    case EListStyleType::kTradChineseInformal:
-      return type;  // Can represent all ordinals.
-    case EListStyleType::kArmenian:
-    case EListStyleType::kLowerArmenian:
-    case EListStyleType::kUpperArmenian:
-      return (count < 1 || count > 99999999) ? EListStyleType::kDecimal : type;
-    case EListStyleType::kGeorgian:
-      return (count < 1 || count > 19999) ? EListStyleType::kDecimal : type;
-    case EListStyleType::kHebrew:
-      return (count < 0 || count > 999999) ? EListStyleType::kDecimal : type;
-    case EListStyleType::kLowerRoman:
-    case EListStyleType::kUpperRoman:
-      return (count < 1 || count > 3999) ? EListStyleType::kDecimal : type;
-    case EListStyleType::kCjkEarthlyBranch:
-    case EListStyleType::kCjkHeavenlyStem:
-    case EListStyleType::kEthiopicHalehameAm:
-    case EListStyleType::kEthiopicHalehame:
-    case EListStyleType::kEthiopicHalehameTiEr:
-    case EListStyleType::kEthiopicHalehameTiEt:
-    case EListStyleType::kHangul:
-    case EListStyleType::kHangulConsonant:
-    case EListStyleType::kHiragana:
-    case EListStyleType::kHiraganaIroha:
-    case EListStyleType::kKatakana:
-    case EListStyleType::kKatakanaIroha:
-    case EListStyleType::kLowerAlpha:
-    case EListStyleType::kLowerGreek:
-    case EListStyleType::kLowerLatin:
-    case EListStyleType::kUpperAlpha:
-    case EListStyleType::kUpperLatin:
-      return (count < 1) ? EListStyleType::kDecimal : type;
-    case EListStyleType::kString:
-      NOTREACHED();
-      break;
-  }
-
-  NOTREACHED();
-  return type;
-}
-
-UChar Suffix(EListStyleType type, int count) {
-  // If the list-style-type cannot represent |count| because it's outside its
-  // ordinal range then we fall back to some list style that can represent
-  // |count|.
-  EListStyleType effective_type = EffectiveListMarkerType(type, count);
-
-  // Note, the following switch statement has been explicitly
-  // grouped by list-style-type suffix.
-  switch (effective_type) {
-    case EListStyleType::kCircle:
-    case EListStyleType::kDisc:
-    case EListStyleType::kDisclosureClosed:
-    case EListStyleType::kDisclosureOpen:
-    case EListStyleType::kNone:
-    case EListStyleType::kSquare:
-      return ' ';
-    case EListStyleType::kEthiopicHalehame:
-    case EListStyleType::kEthiopicHalehameAm:
-    case EListStyleType::kEthiopicHalehameTiEr:
-    case EListStyleType::kEthiopicHalehameTiEt:
-      return kEthiopicPrefaceColonCharacter;
-    case EListStyleType::kArmenian:
-    case EListStyleType::kArabicIndic:
-    case EListStyleType::kBengali:
-    case EListStyleType::kCambodian:
-    case EListStyleType::kCjkIdeographic:
-    case EListStyleType::kCjkEarthlyBranch:
-    case EListStyleType::kCjkHeavenlyStem:
-    case EListStyleType::kDecimalLeadingZero:
-    case EListStyleType::kDecimal:
-    case EListStyleType::kDevanagari:
-    case EListStyleType::kGeorgian:
-    case EListStyleType::kGujarati:
-    case EListStyleType::kGurmukhi:
-    case EListStyleType::kHangul:
-    case EListStyleType::kHangulConsonant:
-    case EListStyleType::kHebrew:
-    case EListStyleType::kHiragana:
-    case EListStyleType::kHiraganaIroha:
-    case EListStyleType::kKannada:
-    case EListStyleType::kKatakana:
-    case EListStyleType::kKatakanaIroha:
-    case EListStyleType::kKhmer:
-    case EListStyleType::kLao:
-    case EListStyleType::kLowerAlpha:
-    case EListStyleType::kLowerArmenian:
-    case EListStyleType::kLowerGreek:
-    case EListStyleType::kLowerLatin:
-    case EListStyleType::kLowerRoman:
-    case EListStyleType::kMalayalam:
-    case EListStyleType::kMongolian:
-    case EListStyleType::kMyanmar:
-    case EListStyleType::kOriya:
-    case EListStyleType::kPersian:
-    case EListStyleType::kTelugu:
-    case EListStyleType::kThai:
-    case EListStyleType::kTibetan:
-    case EListStyleType::kUpperAlpha:
-    case EListStyleType::kUpperArmenian:
-    case EListStyleType::kUpperLatin:
-    case EListStyleType::kUpperRoman:
-    case EListStyleType::kUrdu:
-      return '.';
-    case EListStyleType::kSimpChineseFormal:
-    case EListStyleType::kSimpChineseInformal:
-    case EListStyleType::kTradChineseFormal:
-    case EListStyleType::kTradChineseInformal:
-    case EListStyleType::kKoreanHangulFormal:
-    case EListStyleType::kKoreanHanjaFormal:
-    case EListStyleType::kKoreanHanjaInformal:
-      return 0x3001;
-    case EListStyleType::kString:
-      NOTREACHED();
-      break;
-  }
-
-  NOTREACHED();
-  return '.';
-}
-
-String GetText(EListStyleType type, int count) {
-  // If the list-style-type, say hebrew, cannot represent |count| because it's
-  // outside its ordinal range then we fallback to some list style that can
-  // represent |count|.
-  switch (EffectiveListMarkerType(type, count)) {
-    case EListStyleType::kNone:
-      return "";
-
-    // We use the same characters for text security.
-    // See LayoutText::setInternalString.
-    case EListStyleType::kCircle:
-      return String(&kWhiteBulletCharacter, 1);
-    case EListStyleType::kDisc:
-      return String(&kBulletCharacter, 1);
-
-    // TODO(layout-dev): Text for disclosure-* should not depend on physical
-    // shape?
-    case EListStyleType::kDisclosureClosed:
-      return String(&kBlackRightPointingSmallTriangle, 1);
-    case EListStyleType::kDisclosureOpen:
-      return String(&kBlackDownPointingSmallTriangle, 1);
-
-    case EListStyleType::kSquare:
-      // The CSS 2.1 test suite uses U+25EE BLACK MEDIUM SMALL SQUARE
-      // instead, but I think this looks better.
-      return String(&kBlackSquareCharacter, 1);
-
-    case EListStyleType::kDecimal:
-      return String::Number(count);
-    case EListStyleType::kDecimalLeadingZero:
-      if (count < -9 || count > 9)
-        return String::Number(count);
-      if (count < 0)
-        return "-0" + String::Number(-count);  // -01 to -09
-      return "0" + String::Number(count);      // 00 to 09
-
-    case EListStyleType::kArabicIndic: {
-      static const UChar kArabicIndicNumerals[10] = {
-          0x0660, 0x0661, 0x0662, 0x0663, 0x0664,
-          0x0665, 0x0666, 0x0667, 0x0668, 0x0669};
-      return ToNumeric(count, kArabicIndicNumerals);
-    }
-    case EListStyleType::kBengali: {
-      static const UChar kBengaliNumerals[10] = {0x09E6, 0x09E7, 0x09E8, 0x09E9,
-                                                 0x09EA, 0x09EB, 0x09EC, 0x09ED,
-                                                 0x09EE, 0x09EF};
-      return ToNumeric(count, kBengaliNumerals);
-    }
-    case EListStyleType::kCambodian:
-    case EListStyleType::kKhmer: {
-      static const UChar kKhmerNumerals[10] = {0x17E0, 0x17E1, 0x17E2, 0x17E3,
-                                               0x17E4, 0x17E5, 0x17E6, 0x17E7,
-                                               0x17E8, 0x17E9};
-      return ToNumeric(count, kKhmerNumerals);
-    }
-    case EListStyleType::kDevanagari: {
-      static const UChar kDevanagariNumerals[10] = {
-          0x0966, 0x0967, 0x0968, 0x0969, 0x096A,
-          0x096B, 0x096C, 0x096D, 0x096E, 0x096F};
-      return ToNumeric(count, kDevanagariNumerals);
-    }
-    case EListStyleType::kGujarati: {
-      static const UChar kGujaratiNumerals[10] = {
-          0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA,
-          0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF};
-      return ToNumeric(count, kGujaratiNumerals);
-    }
-    case EListStyleType::kGurmukhi: {
-      static const UChar kGurmukhiNumerals[10] = {
-          0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A,
-          0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F};
-      return ToNumeric(count, kGurmukhiNumerals);
-    }
-    case EListStyleType::kKannada: {
-      static const UChar kKannadaNumerals[10] = {0x0CE6, 0x0CE7, 0x0CE8, 0x0CE9,
-                                                 0x0CEA, 0x0CEB, 0x0CEC, 0x0CED,
-                                                 0x0CEE, 0x0CEF};
-      return ToNumeric(count, kKannadaNumerals);
-    }
-    case EListStyleType::kLao: {
-      static const UChar kLaoNumerals[10] = {0x0ED0, 0x0ED1, 0x0ED2, 0x0ED3,
-                                             0x0ED4, 0x0ED5, 0x0ED6, 0x0ED7,
-                                             0x0ED8, 0x0ED9};
-      return ToNumeric(count, kLaoNumerals);
-    }
-    case EListStyleType::kMalayalam: {
-      static const UChar kMalayalamNumerals[10] = {
-          0x0D66, 0x0D67, 0x0D68, 0x0D69, 0x0D6A,
-          0x0D6B, 0x0D6C, 0x0D6D, 0x0D6E, 0x0D6F};
-      return ToNumeric(count, kMalayalamNumerals);
-    }
-    case EListStyleType::kMongolian: {
-      static const UChar kMongolianNumerals[10] = {
-          0x1810, 0x1811, 0x1812, 0x1813, 0x1814,
-          0x1815, 0x1816, 0x1817, 0x1818, 0x1819};
-      return ToNumeric(count, kMongolianNumerals);
-    }
-    case EListStyleType::kMyanmar: {
-      static const UChar kMyanmarNumerals[10] = {0x1040, 0x1041, 0x1042, 0x1043,
-                                                 0x1044, 0x1045, 0x1046, 0x1047,
-                                                 0x1048, 0x1049};
-      return ToNumeric(count, kMyanmarNumerals);
-    }
-    case EListStyleType::kOriya: {
-      static const UChar kOriyaNumerals[10] = {0x0B66, 0x0B67, 0x0B68, 0x0B69,
-                                               0x0B6A, 0x0B6B, 0x0B6C, 0x0B6D,
-                                               0x0B6E, 0x0B6F};
-      return ToNumeric(count, kOriyaNumerals);
-    }
-    case EListStyleType::kPersian:
-    case EListStyleType::kUrdu: {
-      static const UChar kUrduNumerals[10] = {0x06F0, 0x06F1, 0x06F2, 0x06F3,
-                                              0x06F4, 0x06F5, 0x06F6, 0x06F7,
-                                              0x06F8, 0x06F9};
-      return ToNumeric(count, kUrduNumerals);
-    }
-    case EListStyleType::kTelugu: {
-      static const UChar kTeluguNumerals[10] = {0x0C66, 0x0C67, 0x0C68, 0x0C69,
-                                                0x0C6A, 0x0C6B, 0x0C6C, 0x0C6D,
-                                                0x0C6E, 0x0C6F};
-      return ToNumeric(count, kTeluguNumerals);
-    }
-    case EListStyleType::kTibetan: {
-      static const UChar kTibetanNumerals[10] = {0x0F20, 0x0F21, 0x0F22, 0x0F23,
-                                                 0x0F24, 0x0F25, 0x0F26, 0x0F27,
-                                                 0x0F28, 0x0F29};
-      return ToNumeric(count, kTibetanNumerals);
-    }
-    case EListStyleType::kThai: {
-      static const UChar kThaiNumerals[10] = {0x0E50, 0x0E51, 0x0E52, 0x0E53,
-                                              0x0E54, 0x0E55, 0x0E56, 0x0E57,
-                                              0x0E58, 0x0E59};
-      return ToNumeric(count, kThaiNumerals);
-    }
-
-    case EListStyleType::kLowerAlpha:
-    case EListStyleType::kLowerLatin: {
-      static const LChar kLowerLatinAlphabet[26] = {
-          'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-          'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
-      return ToAlphabetic(count, kLowerLatinAlphabet);
-    }
-    case EListStyleType::kUpperAlpha:
-    case EListStyleType::kUpperLatin: {
-      static const LChar kUpperLatinAlphabet[26] = {
-          'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-          'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
-      return ToAlphabetic(count, kUpperLatinAlphabet);
-    }
-    case EListStyleType::kLowerGreek: {
-      static const UChar kLowerGreekAlphabet[24] = {
-          0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
-          0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
-          0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9};
-      return ToAlphabetic(count, kLowerGreekAlphabet);
-    }
-
-    case EListStyleType::kHiragana: {
-      // FIXME: This table comes from the CSS3 draft, and is probably
-      // incorrect, given the comments in that draft.
-      static const UChar kHiraganaAlphabet[48] = {
-          0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F,
-          0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, 0x305F,
-          0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D,
-          0x306E, 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, 0x307E, 0x307F,
-          0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x308A,
-          0x308B, 0x308C, 0x308D, 0x308F, 0x3090, 0x3091, 0x3092, 0x3093};
-      return ToAlphabetic(count, kHiraganaAlphabet);
-    }
-    case EListStyleType::kHiraganaIroha: {
-      // FIXME: This table comes from the CSS3 draft, and is probably
-      // incorrect, given the comments in that draft.
-      static const UChar kHiraganaIrohaAlphabet[47] = {
-          0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068, 0x3061,
-          0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B, 0x3088, 0x305F,
-          0x308C, 0x305D, 0x3064, 0x306D, 0x306A, 0x3089, 0x3080, 0x3046,
-          0x3090, 0x306E, 0x304A, 0x304F, 0x3084, 0x307E, 0x3051, 0x3075,
-          0x3053, 0x3048, 0x3066, 0x3042, 0x3055, 0x304D, 0x3086, 0x3081,
-          0x307F, 0x3057, 0x3091, 0x3072, 0x3082, 0x305B, 0x3059};
-      return ToAlphabetic(count, kHiraganaIrohaAlphabet);
-    }
-    case EListStyleType::kKatakana: {
-      // FIXME: This table comes from the CSS3 draft, and is probably
-      // incorrect, given the comments in that draft.
-      static const UChar kKatakanaAlphabet[48] = {
-          0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF,
-          0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, 0x30BF,
-          0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD,
-          0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, 0x30DF,
-          0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA,
-          0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x30F2, 0x30F3};
-      return ToAlphabetic(count, kKatakanaAlphabet);
-    }
-    case EListStyleType::kKatakanaIroha: {
-      // FIXME: This table comes from the CSS3 draft, and is probably
-      // incorrect, given the comments in that draft.
-      static const UChar kKatakanaIrohaAlphabet[47] = {
-          0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8, 0x30C1,
-          0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, 0x30BF,
-          0x30EC, 0x30BD, 0x30C4, 0x30CD, 0x30CA, 0x30E9, 0x30E0, 0x30A6,
-          0x30F0, 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, 0x30B1, 0x30D5,
-          0x30B3, 0x30A8, 0x30C6, 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1,
-          0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x30B9};
-      return ToAlphabetic(count, kKatakanaIrohaAlphabet);
-    }
-
-    case EListStyleType::kCjkEarthlyBranch: {
-      static const UChar kCjkEarthlyBranchAlphabet[12] = {
-          0x5B50, 0x4E11, 0x5BC5, 0x536F, 0x8FB0, 0x5DF3,
-          0x5348, 0x672A, 0x7533, 0x9149, 0x620C, 0x4EA5};
-      return ToAlphabetic(count, kCjkEarthlyBranchAlphabet);
-    }
-    case EListStyleType::kCjkHeavenlyStem: {
-      static const UChar kCjkHeavenlyStemAlphabet[10] = {
-          0x7532, 0x4E59, 0x4E19, 0x4E01, 0x620A,
-          0x5DF1, 0x5E9A, 0x8F9B, 0x58EC, 0x7678};
-      return ToAlphabetic(count, kCjkHeavenlyStemAlphabet);
-    }
-    case EListStyleType::kHangulConsonant: {
-      static const UChar kHangulConsonantAlphabet[14] = {
-          0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142, 0x3145,
-          0x3147, 0x3148, 0x314A, 0x314B, 0x314C, 0x314D, 0x314E};
-      return ToAlphabetic(count, kHangulConsonantAlphabet);
-    }
-    case EListStyleType::kHangul: {
-      static const UChar kHangulAlphabet[14] = {
-          0xAC00, 0xB098, 0xB2E4, 0xB77C, 0xB9C8, 0xBC14, 0xC0AC,
-          0xC544, 0xC790, 0xCC28, 0xCE74, 0xD0C0, 0xD30C, 0xD558};
-      return ToAlphabetic(count, kHangulAlphabet);
-    }
-    case EListStyleType::kEthiopicHalehame: {
-      static const UChar kEthiopicHalehameGezAlphabet[26] = {
-          0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
-          0x1240, 0x1260, 0x1270, 0x1280, 0x1290, 0x12A0, 0x12A8,
-          0x12C8, 0x12D0, 0x12D8, 0x12E8, 0x12F0, 0x1308, 0x1320,
-          0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
-      return ToAlphabetic(count, kEthiopicHalehameGezAlphabet);
-    }
-    case EListStyleType::kEthiopicHalehameAm: {
-      static const UChar kEthiopicHalehameAmAlphabet[33] = {
-          0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
-          0x1238, 0x1240, 0x1260, 0x1270, 0x1278, 0x1280, 0x1290,
-          0x1298, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0, 0x12D8,
-          0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320, 0x1328,
-          0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
-      return ToAlphabetic(count, kEthiopicHalehameAmAlphabet);
-    }
-    case EListStyleType::kEthiopicHalehameTiEr: {
-      static const UChar kEthiopicHalehameTiErAlphabet[31] = {
-          0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240,
-          0x1250, 0x1260, 0x1270, 0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8,
-          0x12B8, 0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300,
-          0x1308, 0x1320, 0x1328, 0x1330, 0x1338, 0x1348, 0x1350};
-      return ToAlphabetic(count, kEthiopicHalehameTiErAlphabet);
-    }
-    case EListStyleType::kEthiopicHalehameTiEt: {
-      static const UChar kEthiopicHalehameTiEtAlphabet[34] = {
-          0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230,
-          0x1238, 0x1240, 0x1250, 0x1260, 0x1270, 0x1278, 0x1280,
-          0x1290, 0x1298, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0,
-          0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320,
-          0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350};
-      return ToAlphabetic(count, kEthiopicHalehameTiEtAlphabet);
-    }
-    case EListStyleType::kKoreanHangulFormal: {
-      static const UChar kKoreanHangulFormalTable[26] = {
-          kKorean, 0xB9CC, 0x0000, 0xC5B5, 0x0000, 0xC870, 0x0000,
-          0xC2ED,  0xBC31, 0xCC9C, 0xC601, 0xC77C, 0xC774, 0xC0BC,
-          0xC0AC,  0xC624, 0xC721, 0xCE60, 0xD314, 0xAD6C, 0xB9C8,
-          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
-      return ToCJKIdeographic(count, kKoreanHangulFormalTable, kFormal);
-    }
-    case EListStyleType::kKoreanHanjaFormal: {
-      static const UChar kKoreanHanjaFormalTable[26] = {
-          kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
-          0x62FE,  0x767E, 0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3,
-          0x56DB,  0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
-          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
-      return ToCJKIdeographic(count, kKoreanHanjaFormalTable, kFormal);
-    }
-    case EListStyleType::kKoreanHanjaInformal: {
-      static const UChar kKoreanHanjaInformalTable[26] = {
-          kKorean, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000,
-          0x5341,  0x767E, 0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09,
-          0x56DB,  0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D, 0xB9C8,
-          0xC774,  0xB108, 0xC2A4, 0x0020, 0x0000};
-      return ToCJKIdeographic(count, kKoreanHanjaInformalTable, kInformal);
-    }
-    case EListStyleType::kCjkIdeographic:
-    case EListStyleType::kTradChineseInformal: {
-      static const UChar kTraditionalChineseInformalTable[22] = {
-          kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x5341,
-          0x767E,   0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
-          0x516D,   0x4E03, 0x516B, 0x4E5D, 0x8CA0, 0x0000};
-      return ToCJKIdeographic(count, kTraditionalChineseInformalTable,
-                              kInformal);
-    }
-    case EListStyleType::kSimpChineseInformal: {
-      static const UChar kSimpleChineseInformalTable[22] = {
-          kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x5341,
-          0x767E,   0x5343, 0x96F6, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, 0x4E94,
-          0x516D,   0x4E03, 0x516B, 0x4E5D, 0x8D1F, 0x0000};
-      return ToCJKIdeographic(count, kSimpleChineseInformalTable, kInformal);
-    }
-    case EListStyleType::kTradChineseFormal: {
-      static const UChar kTraditionalChineseFormalTable[22] = {
-          kChinese, 0x842C, 0x0000, 0x5104, 0x0000, 0x5146, 0x0000, 0x62FE,
-          0x4F70,   0x4EDF, 0x96F6, 0x58F9, 0x8CB3, 0x53C3, 0x8086, 0x4F0D,
-          0x9678,   0x67D2, 0x634C, 0x7396, 0x8CA0, 0x0000};
-      return ToCJKIdeographic(count, kTraditionalChineseFormalTable, kFormal);
-    }
-    case EListStyleType::kSimpChineseFormal: {
-      static const UChar kSimpleChineseFormalTable[22] = {
-          kChinese, 0x4E07, 0x0000, 0x4EBF, 0x0000, 0x4E07, 0x4EBF, 0x62FE,
-          0x4F70,   0x4EDF, 0x96F6, 0x58F9, 0x8D30, 0x53C1, 0x8086, 0x4F0D,
-          0x9646,   0x67D2, 0x634C, 0x7396, 0x8D1F, 0x0000};
-      return ToCJKIdeographic(count, kSimpleChineseFormalTable, kFormal);
-    }
-
-    case EListStyleType::kLowerRoman:
-      return ToRoman(count, false);
-    case EListStyleType::kUpperRoman:
-      return ToRoman(count, true);
-
-    case EListStyleType::kArmenian:
-    case EListStyleType::kUpperArmenian:
-      // CSS3 says "armenian" means "lower-armenian".
-      // But the CSS2.1 test suite contains uppercase test results for
-      // "armenian", so we'll match the test suite.
-      return ToArmenian(count, true);
-    case EListStyleType::kLowerArmenian:
-      return ToArmenian(count, false);
-    case EListStyleType::kGeorgian:
-      return ToGeorgian(count);
-    case EListStyleType::kHebrew:
-      return ToHebrew(count);
-
-    case EListStyleType::kString:
-      NOTREACHED();
-      break;
-  }
-
-  NOTREACHED();
-  return "";
-}
-
-}  // namespace list_marker_text
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/list_marker_text.h b/third_party/blink/renderer/core/layout/list_marker_text.h
deleted file mode 100644
index ea030c8..0000000
--- a/third_party/blink/renderer/core/layout/list_marker_text.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc.
-                 All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LIST_MARKER_TEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LIST_MARKER_TEXT_H_
-
-#include "third_party/blink/renderer/core/style/computed_style_constants.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-// Utility routines for working with lists. Encapsulates complex
-// language-specific logic including fallback to alternate languages when
-// counter values cannot be represented in a particular language.
-namespace list_marker_text {
-
-// Returns the suffix character, such as '.', for the given list type and
-// item count number.
-UChar Suffix(EListStyleType, int count);
-
-// Returns the text, such as arabic or roman numerals, for the given list
-// type and item count number. Does not include any suffix character.
-String GetText(EListStyleType, int count);
-
-}  // namespace list_marker_text
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LIST_MARKER_TEXT_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index afb139d..cca4d7d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -77,16 +77,16 @@
 bool BlockLengthUnresolvable(
     const NGConstraintSpace& constraint_space,
     const Length& length,
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+    const LayoutUnit* override_percentage_resolution_size) {
   if (length.IsAuto() || length.IsMinContent() || length.IsMaxContent() ||
       length.IsMinIntrinsic() || length.IsFitContent() || length.IsNone())
     return true;
   if (length.IsPercentOrCalc()) {
-    LayoutUnit percentage_resolution_block_size =
-        opt_percentage_resolution_block_size_for_min_max
-            ? *opt_percentage_resolution_block_size_for_min_max
+    const LayoutUnit percentage_resolution_size =
+        override_percentage_resolution_size
+            ? *override_percentage_resolution_size
             : constraint_space.PercentageResolutionBlockSize();
-    return percentage_resolution_block_size == kIndefiniteSize;
+    return percentage_resolution_size == kIndefiniteSize;
   }
 
   if (length.IsFillAvailable())
@@ -175,7 +175,7 @@
     const Length& length,
     LayoutUnit intrinsic_size,
     LayoutUnit available_block_size_adjustment,
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+    const LayoutUnit* override_percentage_resolution_size) {
   DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());
 
   switch (length.GetType()) {
@@ -193,8 +193,8 @@
     case Length::kFixed:
     case Length::kCalculated: {
       const LayoutUnit percentage_resolution_size =
-          opt_percentage_resolution_block_size_for_min_max
-              ? *opt_percentage_resolution_block_size_for_min_max
+          override_percentage_resolution_size
+              ? *override_percentage_resolution_size
               : constraint_space.PercentageResolutionBlockSize();
       DCHECK(length.IsFixed() || percentage_resolution_size != kIndefiniteSize);
       LayoutUnit value =
@@ -597,17 +597,14 @@
     const NGConstraintSpace& constraint_space,
     const ComputedStyle& style,
     const NGBoxStrut& border_padding,
-    LayoutUnit available_block_size_adjustment,
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+    LayoutUnit available_block_size_adjustment) {
   MinMaxSizes sizes = {
       ResolveMinBlockLength(constraint_space, style, border_padding,
                             style.LogicalMinHeight(),
-                            available_block_size_adjustment,
-                            opt_percentage_resolution_block_size_for_min_max),
+                            available_block_size_adjustment),
       ResolveMaxBlockLength(constraint_space, style, border_padding,
                             style.LogicalMaxHeight(),
-                            available_block_size_adjustment,
-                            opt_percentage_resolution_block_size_for_min_max)};
+                            available_block_size_adjustment)};
   sizes.max_size = std::max(sizes.max_size, sizes.min_size);
   return sizes;
 }
@@ -662,12 +659,9 @@
     const NGBoxStrut& border_padding,
     LayoutUnit intrinsic_size,
     absl::optional<LayoutUnit> inline_size,
-    LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr) {
+    LayoutUnit available_block_size_adjustment = LayoutUnit()) {
   MinMaxSizes min_max = ComputeMinMaxBlockSizes(
-      space, style, border_padding, available_block_size_adjustment,
-      opt_percentage_resolution_block_size_for_min_max);
+      space, style, border_padding, available_block_size_adjustment);
 
   // Scrollable percentage-sized children of table cells (sometimes) are sized
   // to their min-size.
@@ -684,9 +678,7 @@
         logical_height.IsAuto() &&
         space.BlockAutoBehavior() == NGAutoBehavior::kStretchExplicit &&
         space.AvailableSize().block_size != kIndefiniteSize;
-    if (BlockLengthUnresolvable(
-            space, logical_height,
-            opt_percentage_resolution_block_size_for_min_max) &&
+    if (BlockLengthUnresolvable(space, logical_height) &&
         !has_explicit_stretch) {
       extent = BlockSizeFromAspectRatio(
           border_padding, style.LogicalAspectRatio(),
@@ -716,10 +708,9 @@
 
     // TODO(cbiesinger): Audit callers of ResolveMainBlockLength to see whether
     // they need to respect aspect ratio.
-    extent = ResolveMainBlockLength(
-        space, style, border_padding, logical_height, intrinsic_size,
-        available_block_size_adjustment,
-        opt_percentage_resolution_block_size_for_min_max);
+    extent =
+        ResolveMainBlockLength(space, style, border_padding, logical_height,
+                               intrinsic_size, available_block_size_adjustment);
   }
 
   if (extent == kIndefiniteSize) {
@@ -953,9 +944,13 @@
         size += ComputeDefaultNaturalSize(node).inline_size;
     } else {
       // Stretch to the available-size if it is definite.
-      size = ResolveMainInlineLength<absl::optional<MinMaxSizes>>(
-          space, style, border_padding, absl::nullopt, Length::FillAvailable(),
-          available_inline_size_adjustment);
+      size = ResolveMainInlineLength(
+          space, style, border_padding,
+          [](MinMaxSizesType) -> MinMaxSizesResult {
+            NOTREACHED();
+            return MinMaxSizesResult();
+          },
+          Length::FillAvailable(), available_inline_size_adjustment);
     }
 
     // If stretch-fit applies we must have an aspect-ratio.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
index 8f87c06..1659c63 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -58,8 +58,7 @@
 CORE_EXPORT bool BlockLengthUnresolvable(
     const NGConstraintSpace&,
     const Length&,
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr);
+    const LayoutUnit* override_percentage_resolution_size = nullptr);
 
 // Resolve means translate a Length to a LayoutUnit.
 //  - |NGConstraintSpace| the information given by the parent, e.g. the
@@ -88,8 +87,7 @@
     const Length&,
     LayoutUnit intrinsic_size,
     LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr);
+    const LayoutUnit* override_percentage_resolution_size = nullptr);
 
 // In this file the template parameter MinMaxSizesFunc should have the
 // following form:
@@ -126,23 +124,6 @@
                                      available_inline_size_adjustment);
 }
 
-template <>
-inline LayoutUnit ResolveMinInlineLength<absl::optional<MinMaxSizes>>(
-    const NGConstraintSpace& constraint_space,
-    const ComputedStyle& style,
-    const NGBoxStrut& border_padding,
-    const absl::optional<MinMaxSizes>& min_max_sizes,
-    const Length& length,
-    LayoutUnit available_inline_size_adjustment) {
-  if (LIKELY(length.IsAuto() ||
-             InlineLengthUnresolvable(constraint_space, length)))
-    return border_padding.InlineSum();
-
-  return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length,
-                                     available_inline_size_adjustment);
-}
-
 // Used for resolving max inline lengths, (|ComputedStyle::MaxLogicalWidth|).
 template <typename MinMaxSizesFunc>
 inline LayoutUnit ResolveMaxInlineLength(
@@ -169,23 +150,6 @@
                                      available_inline_size_adjustment);
 }
 
-template <>
-inline LayoutUnit ResolveMaxInlineLength<absl::optional<MinMaxSizes>>(
-    const NGConstraintSpace& constraint_space,
-    const ComputedStyle& style,
-    const NGBoxStrut& border_padding,
-    const absl::optional<MinMaxSizes>& min_max_sizes,
-    const Length& length,
-    LayoutUnit available_inline_size_adjustment) {
-  if (LIKELY(length.IsNone() ||
-             InlineLengthUnresolvable(constraint_space, length)))
-    return LayoutUnit::Max();
-
-  return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length,
-                                     available_inline_size_adjustment);
-}
-
 // Used for resolving main inline lengths, (|ComputedStyle::LogicalWidth|).
 template <typename MinMaxSizesFunc>
 inline LayoutUnit ResolveMainInlineLength(
@@ -209,20 +173,6 @@
                                      available_inline_size_adjustment);
 }
 
-template <>
-inline LayoutUnit ResolveMainInlineLength<absl::optional<MinMaxSizes>>(
-    const NGConstraintSpace& constraint_space,
-    const ComputedStyle& style,
-    const NGBoxStrut& border_padding,
-    const absl::optional<MinMaxSizes>& min_max_sizes,
-    const Length& length,
-    LayoutUnit available_inline_size_adjustment) {
-  DCHECK(!length.IsAuto());
-  return ResolveInlineLengthInternal(constraint_space, style, border_padding,
-                                     min_max_sizes, length,
-                                     available_inline_size_adjustment);
-}
-
 // Used for resolving min block lengths, (|ComputedStyle::MinLogicalHeight|).
 inline LayoutUnit ResolveMinBlockLength(
     const NGConstraintSpace& constraint_space,
@@ -230,17 +180,14 @@
     const NGBoxStrut& border_padding,
     const Length& length,
     LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr) {
-  if (LIKELY(BlockLengthUnresolvable(
-          constraint_space, length,
-          opt_percentage_resolution_block_size_for_min_max)))
+    const LayoutUnit* override_percentage_resolution_size = nullptr) {
+  if (LIKELY(BlockLengthUnresolvable(constraint_space, length,
+                                     override_percentage_resolution_size)))
     return border_padding.BlockSum();
 
   return ResolveBlockLengthInternal(
       constraint_space, style, border_padding, length, kIndefiniteSize,
-      available_block_size_adjustment,
-      opt_percentage_resolution_block_size_for_min_max);
+      available_block_size_adjustment, override_percentage_resolution_size);
 }
 
 // Used for resolving max block lengths, (|ComputedStyle::MaxLogicalHeight|).
@@ -250,17 +197,14 @@
     const NGBoxStrut& border_padding,
     const Length& length,
     LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr) {
-  if (LIKELY(BlockLengthUnresolvable(
-          constraint_space, length,
-          opt_percentage_resolution_block_size_for_min_max)))
+    const LayoutUnit* override_percentage_resolution_size = nullptr) {
+  if (LIKELY(BlockLengthUnresolvable(constraint_space, length,
+                                     override_percentage_resolution_size)))
     return LayoutUnit::Max();
 
   return ResolveBlockLengthInternal(
       constraint_space, style, border_padding, length, kIndefiniteSize,
-      available_block_size_adjustment,
-      opt_percentage_resolution_block_size_for_min_max);
+      available_block_size_adjustment, override_percentage_resolution_size);
 }
 
 // Used for resolving main block lengths, (|ComputedStyle::LogicalHeight|).
@@ -271,19 +215,16 @@
     const Length& length,
     LayoutUnit intrinsic_size,
     LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr) {
+    const LayoutUnit* override_percentage_resolution_size = nullptr) {
   DCHECK(!length.IsAuto());
   if (UNLIKELY((length.IsPercentOrCalc() || length.IsFillAvailable()) &&
-               BlockLengthUnresolvable(
-                   constraint_space, length,
-                   opt_percentage_resolution_block_size_for_min_max)))
+               BlockLengthUnresolvable(constraint_space, length,
+                                       override_percentage_resolution_size)))
     return intrinsic_size;
 
   return ResolveBlockLengthInternal(
       constraint_space, style, border_padding, length, intrinsic_size,
-      available_block_size_adjustment,
-      opt_percentage_resolution_block_size_for_min_max);
+      available_block_size_adjustment, override_percentage_resolution_size);
 }
 
 template <typename IntrinsicBlockSizeFunc>
@@ -293,24 +234,19 @@
     const NGBoxStrut& border_padding,
     const Length& length,
     const IntrinsicBlockSizeFunc& intrinsic_block_size_func,
-    LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr) {
+    LayoutUnit available_block_size_adjustment = LayoutUnit()) {
   DCHECK(!length.IsAuto());
   if (UNLIKELY((length.IsPercentOrCalc() || length.IsFillAvailable()) &&
-               BlockLengthUnresolvable(
-                   constraint_space, length,
-                   opt_percentage_resolution_block_size_for_min_max)))
+               BlockLengthUnresolvable(constraint_space, length)))
     return intrinsic_block_size_func();
 
   LayoutUnit intrinsic_block_size = kIndefiniteSize;
   if (length.IsContentOrIntrinsic())
     intrinsic_block_size = intrinsic_block_size_func();
 
-  return ResolveBlockLengthInternal(
-      constraint_space, style, border_padding, length, intrinsic_block_size,
-      available_block_size_adjustment,
-      opt_percentage_resolution_block_size_for_min_max);
+  return ResolveBlockLengthInternal(constraint_space, style, border_padding,
+                                    length, intrinsic_block_size,
+                                    available_block_size_adjustment);
 }
 
 // For the given |child|, computes the min and max content contribution
@@ -354,9 +290,7 @@
     const NGConstraintSpace&,
     const ComputedStyle&,
     const NGBoxStrut& border_padding,
-    LayoutUnit available_block_size_adjustment = LayoutUnit(),
-    const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
-        nullptr);
+    LayoutUnit available_block_size_adjustment = LayoutUnit());
 
 MinMaxSizes ComputeTransferredMinMaxInlineSizes(
     const LogicalSize& ratio,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
index 43d42d79..b759ca46 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
@@ -51,8 +51,12 @@
     NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
                                 ComputePadding(constraint_space, *style_);
 
-    return ::blink::ResolveMainInlineLength(constraint_space, *style_,
-                                            border_padding, sizes, length);
+    return ::blink::ResolveMainInlineLength(
+        constraint_space, *style_, border_padding,
+        [&](MinMaxSizesType) -> MinMaxSizesResult {
+          return {*sizes, /* depends_on_block_constraints */ false};
+        },
+        length);
   }
 
   LayoutUnit ResolveMinInlineLength(
@@ -62,8 +66,12 @@
     NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
                                 ComputePadding(constraint_space, *style_);
 
-    return ::blink::ResolveMinInlineLength(constraint_space, *style_,
-                                           border_padding, sizes, length);
+    return ::blink::ResolveMinInlineLength(
+        constraint_space, *style_, border_padding,
+        [&](MinMaxSizesType) -> MinMaxSizesResult {
+          return {*sizes, /* depends_on_block_constraints */ false};
+        },
+        length);
   }
 
   LayoutUnit ResolveMaxInlineLength(
@@ -73,8 +81,12 @@
     NGBoxStrut border_padding = ComputeBordersForTest(*style_) +
                                 ComputePadding(constraint_space, *style_);
 
-    return ::blink::ResolveMaxInlineLength(constraint_space, *style_,
-                                           border_padding, sizes, length);
+    return ::blink::ResolveMaxInlineLength(
+        constraint_space, *style_, border_padding,
+        [&](MinMaxSizesType) -> MinMaxSizesResult {
+          return {*sizes, /* depends_on_block_constraints */ false};
+        },
+        length);
   }
 
   LayoutUnit ResolveMainBlockLength(const Length& length,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index af8b8d4..e778bb16 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -483,13 +483,11 @@
   for (const auto& descendant :
        builder->oof_positioned_fragmentainer_descendants_) {
     // The static position should remain relative to the containing block.
-    PhysicalSize containing_block_size = size;
+    PhysicalSize containing_block_size =
+        descendant.containing_block.fragment
+            ? descendant.containing_block.fragment->Size()
+            : size;
     WritingDirectionMode writing_direction = builder->GetWritingDirection();
-    if (descendant.containing_block.fragment) {
-      containing_block_size = descendant.containing_block.fragment->Size();
-      writing_direction =
-          descendant.containing_block.fragment->Style().GetWritingDirection();
-    }
     const WritingModeConverter converter(writing_direction,
                                          containing_block_size);
 
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index 0bd71bd..d63f7651 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/html/canvas/image_data.h"
 #include "third_party/blink/renderer/core/html/canvas/ukm_parameters.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
 #include "third_party/blink/renderer/platform/bindings/microtask.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
@@ -302,6 +303,15 @@
     return nullptr;
   }
 
+  // TODO(crbug.com/1229274): Remove 'gpupresent' type after deprecation period.
+  if (id == "gpupresent") {
+    auto* console_message = MakeGarbageCollected<ConsoleMessage>(
+        mojom::blink::ConsoleMessageSource::kRendering,
+        mojom::blink::ConsoleMessageLevel::kWarning,
+        "The context type 'gpupresent' is deprecated. Use 'webgpu' instead.");
+    execution_context->AddConsoleMessage(console_message);
+  }
+
   if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
     if (attributes.color_space != kSRGBCanvasColorSpaceName ||
         attributes.pixel_format != kUint8CanvasPixelFormatName) {
diff --git a/third_party/blink/renderer/core/paint/list_marker_painter.cc b/third_party/blink/renderer/core/paint/list_marker_painter.cc
index b269733..f8695af 100644
--- a/third_party/blink/renderer/core/paint/list_marker_painter.cc
+++ b/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/core/layout/layout_list_item.h"
 #include "third_party/blink/renderer/core/layout/layout_list_marker.h"
 #include "third_party/blink/renderer/core/layout/list_marker.h"
-#include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
 #include "third_party/blink/renderer/core/paint/box_painter.h"
 #include "third_party/blink/renderer/core/paint/highlight_painting_utils.h"
diff --git a/third_party/blink/renderer/core/timing/build.gni b/third_party/blink/renderer/core/timing/build.gni
index e19ead1..c39d5d3 100644
--- a/third_party/blink/renderer/core/timing/build.gni
+++ b/third_party/blink/renderer/core/timing/build.gni
@@ -61,6 +61,8 @@
   "profiler_group.h",
   "background_tracing_helper.cc",
   "background_tracing_helper.h",
+  "responsiveness_metrics.cc",
+  "responsiveness_metrics.h",
   "task_attribution_timing.cc",
   "task_attribution_timing.h",
   "time_clamper.cc",
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc
index e142e275..7332f28e 100644
--- a/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -49,13 +49,31 @@
 }  // namespace
 
 EventTiming::EventTiming(base::TimeTicks processing_start,
-                         base::TimeTicks event_timestamp,
                          WindowPerformance* performance,
-                         bool should_log_event)
+                         const Event& event)
     : processing_start_(processing_start),
-      event_timestamp_(event_timestamp),
       performance_(performance),
-      should_log_event_(should_log_event) {}
+      event_(&event) {
+  performance_->SetCurrentEventTimingEvent(&event);
+}
+
+// static
+void EventTiming::HandleInputDelay(LocalDOMWindow* window, const Event& event) {
+  auto* pointer_event = DynamicTo<PointerEvent>(&event);
+  base::TimeTicks event_timestamp =
+      pointer_event ? pointer_event->OldestPlatformTimeStamp()
+                    : event.PlatformTimeStamp();
+
+  base::TimeTicks processing_start = Now();
+  if (ShouldLogEvent(event) && event.isTrusted()) {
+    InteractiveDetector* interactive_detector =
+        InteractiveDetector::From(*window->document());
+    if (interactive_detector) {
+      interactive_detector->HandleForInputDelay(event, event_timestamp,
+                                                processing_start);
+    }
+  }
+}
 
 // static
 bool EventTiming::IsEventTypeForEventTiming(const Event& event) {
@@ -81,7 +99,16 @@
 std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
                                                  const Event& event) {
   auto* performance = DOMWindowPerformance::performance(*window);
-  if (!performance || !IsEventTypeForEventTiming(event))
+  if (!performance || !event.isTrusted() ||
+      (!IsEventTypeForEventTiming(event) &&
+       event.type() != event_type_names::kPointermove))
+    return nullptr;
+
+  // Most events track their performance in EventDispatcher::Dispatch but
+  // some event types which can be filtered are tracked at the point
+  // where they may be filtered. This condition check ensures we don't create
+  // two EventTiming objects for the same Event.
+  if (performance->GetCurrentEventTimingEvent() == &event)
     return nullptr;
 
   bool should_report_for_event_timing = ShouldReportForEventTiming(performance);
@@ -90,39 +117,38 @@
   if (!should_report_for_event_timing && !should_log_event)
     return nullptr;
 
-  auto* pointer_event = DynamicTo<PointerEvent>(&event);
-  base::TimeTicks event_timestamp =
-      pointer_event ? pointer_event->OldestPlatformTimeStamp()
-                    : event.PlatformTimeStamp();
-
   base::TimeTicks processing_start = Now();
-
-  if (should_log_event) {
-    InteractiveDetector* interactive_detector =
-        InteractiveDetector::From(*window->document());
-    if (interactive_detector) {
-      interactive_detector->HandleForInputDelay(event, event_timestamp,
-                                                processing_start);
-    }
-  }
-
   return should_report_for_event_timing
-             ? std::make_unique<EventTiming>(processing_start, event_timestamp,
-                                             performance, should_log_event)
+             ? std::make_unique<EventTiming>(processing_start, performance,
+                                             event)
              : nullptr;
 }
 
-void EventTiming::DidDispatchEvent(const Event& event, Document& document) {
-  Node* target = event.target() ? event.target()->ToNode() : nullptr;
-  base::TimeTicks processing_end = Now();
-  performance_->RegisterEventTiming(event.type(), event_timestamp_,
-                                    processing_start_, processing_end,
-                                    event.cancelable(), target);
-}
-
 // static
 void EventTiming::SetTickClockForTesting(const base::TickClock* clock) {
   g_clock_for_testing = clock;
 }
 
+EventTiming::~EventTiming() {
+  absl::optional<int> key_code = absl::nullopt;
+  if (event_->IsKeyboardEvent())
+    key_code = DynamicTo<KeyboardEvent>(event_.Get())->keyCode();
+
+  absl::optional<PointerId> pointer_id = absl::nullopt;
+  const PointerEvent* pointer_event = DynamicTo<PointerEvent>(event_.Get());
+  if (pointer_event)
+    pointer_id = pointer_event->pointerId();
+
+  base::TimeTicks event_timestamp =
+      pointer_event ? pointer_event->OldestPlatformTimeStamp()
+                    : event_->PlatformTimeStamp();
+
+  // Register Event Timing for the event.
+  performance_->RegisterEventTiming(
+      event_->type(), event_timestamp, processing_start_, Now(),
+      event_->cancelable(),
+      event_->target() ? event_->target()->ToNode() : nullptr, key_code,
+      pointer_id);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/event_timing.h b/third_party/blink/renderer/core/timing/event_timing.h
index e22c4eee..59a8627 100644
--- a/third_party/blink/renderer/core/timing/event_timing.h
+++ b/third_party/blink/renderer/core/timing/event_timing.h
@@ -26,18 +26,19 @@
   // Processes an event that will be dispatched. Notifies the
   // InteractiveDetector if it needs to be logged into input delay histograms.
   // Returns an object only if the event is relevant for the EventTiming API.
+  // This object should be constructed before the event is dispatched and
+  // destructed after dispatch so that we can calculate the input delay and
+  // other latency values correctly.
   static std::unique_ptr<EventTiming> Create(LocalDOMWindow*, const Event&);
 
   explicit EventTiming(base::TimeTicks processing_start,
-                       base::TimeTicks event_timestamp,
                        WindowPerformance* performance,
-                       bool should_log);
+                       const Event& event);
+  ~EventTiming();
   EventTiming(const EventTiming&) = delete;
   EventTiming& operator=(const EventTiming&) = delete;
 
-  // Notifies the Performance object that the event has been dispatched.
-  void DidDispatchEvent(const Event&, Document& document);
-
+  static void HandleInputDelay(LocalDOMWindow* window, const Event& event);
   // The caller owns the |clock| which must outlive the EventTiming.
   static void SetTickClockForTesting(const base::TickClock* clock);
 
@@ -52,7 +53,7 @@
 
   Persistent<WindowPerformance> performance_;
 
-  bool should_log_event_;
+  Persistent<const Event> event_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/responsiveness_metrics.cc b/third_party/blink/renderer/core/timing/responsiveness_metrics.cc
new file mode 100644
index 0000000..f2eb5b9
--- /dev/null
+++ b/third_party/blink/renderer/core/timing/responsiveness_metrics.cc
@@ -0,0 +1,213 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
+
+#include "services/metrics/public/cpp/ukm_builders.h"
+
+namespace blink {
+
+namespace {
+// Minimum potentially generated value for UKM sampling.
+const uint32_t MinValueForSampling = 1;
+// Maximum potentially generated value for UKM sampling.
+const uint32_t MaxValueForSampling = 100;
+// UKM sampling rate. The sampling strategy is 1/N.
+const uint32_t UkmSamplingRate = 10;
+
+bool IsSorted(WTF::Vector<ResponsivenessMetrics::EventTimestamps> timestamps) {
+  for (WTF::wtf_size_t i = 1; i < timestamps.size(); ++i) {
+    if (timestamps[i].start_time < timestamps[i - 1].start_time)
+      return false;
+  }
+  return true;
+}
+
+base::TimeDelta MaxEventDuration(
+    WTF::Vector<ResponsivenessMetrics::EventTimestamps> timestamps) {
+  base::TimeDelta max_duration =
+      timestamps[0].end_time - timestamps[0].start_time;
+  for (WTF::wtf_size_t i = 1; i < timestamps.size(); ++i) {
+    max_duration = std::max(max_duration,
+                            timestamps[i].end_time - timestamps[i].start_time);
+  }
+  return max_duration;
+}
+
+base::TimeDelta TotalEventDuration(
+    // timestamps is sorted by the start_time of EventTimestamps.
+    WTF::Vector<ResponsivenessMetrics::EventTimestamps> timestamps) {
+  DCHECK(IsSorted(timestamps));
+  base::TimeDelta total_duration =
+      timestamps[0].end_time - timestamps[0].start_time;
+  base::TimeTicks current_end_time = timestamps[0].end_time;
+  for (WTF::wtf_size_t i = 1; i < timestamps.size(); ++i) {
+    total_duration += timestamps[i].end_time - timestamps[i].start_time;
+    if (timestamps[i].start_time < current_end_time) {
+      total_duration -= std::min(current_end_time, timestamps[i].end_time) -
+                        timestamps[i].start_time;
+    }
+    current_end_time = std::max(current_end_time, timestamps[i].end_time);
+  }
+  return total_duration;
+}
+}  // namespace
+
+ResponsivenessMetrics::ResponsivenessMetrics()
+    : generator_(std::mt19937(static_cast<uint32_t>(time(NULL)))),
+      distribution_(
+          std::uniform_int_distribution<uint32_t>(MinValueForSampling,
+                                                  MaxValueForSampling)) {}
+
+ResponsivenessMetrics::~ResponsivenessMetrics() = default;
+
+void ResponsivenessMetrics::RecordUserInteractionUKM(
+    LocalDOMWindow* window,
+    UserInteractionType interaction_type,
+    base::TimeDelta max_event_duration,
+    base::TimeDelta total_event_duration) {
+  if (!window)
+    return;
+  if (!ukm_recorder_)
+    ukm_recorder_ = window->UkmRecorder();
+  ukm::SourceId source_id = window->UkmSourceID();
+
+  if (!sampling_ || distribution_(generator_) <= UkmSamplingRate) {
+    ukm::builders::Responsiveness_UserInteraction(source_id)
+        .SetInteractionType(static_cast<int>(interaction_type))
+        .SetMaxEventDuration(max_event_duration.InMilliseconds())
+        .SetTotalEventDuration(total_event_duration.InMilliseconds())
+        .Record(ukm_recorder_);
+  }
+}
+
+void ResponsivenessMetrics::NotifyPotentialDrag() {
+  is_drag_ = pending_pointer_down_timestamps_.has_value() &&
+             !pending_pointer_up_timestamps_.has_value();
+}
+
+void ResponsivenessMetrics::RecordPerInteractionLatency(
+    LocalDOMWindow* window,
+    const AtomicString& event_type,
+    absl::optional<int> key_code,
+    absl::optional<PointerId> pointer_id,
+    EventTimestamps event_timestamps) {
+  // Keyboard interactions.
+  if (key_code.has_value()) {
+    RecordKeyboardInteractions(window, event_type, key_code.value(),
+                               event_timestamps);
+  }
+  // Tap(Click) or Drag.
+  if (pointer_id.has_value()) {
+    RecordTapOrClickOrDrag(window, event_type, event_timestamps);
+  }
+}
+
+void ResponsivenessMetrics::FlushPendingInteraction(LocalDOMWindow* window) {
+  // For tap delay, the click can be dropped. We will measure the latency
+  // without any click data.
+  if (pending_pointer_down_timestamps_.has_value() &&
+      pending_pointer_up_timestamps_.has_value()) {
+    WTF::Vector<EventTimestamps> timestamps;
+    // Insertion order matters for latency computation.
+    timestamps.push_back(pending_pointer_down_timestamps_.value());
+    timestamps.push_back(pending_pointer_up_timestamps_.value());
+    RecordUserInteractionUKM(window,
+                             is_drag_ ? UserInteractionType::kDrag
+                                      : UserInteractionType::kTapOrClick,
+                             MaxEventDuration(timestamps),
+                             TotalEventDuration(timestamps));
+  }
+  ResetPendingPointers();
+}
+
+void ResponsivenessMetrics::ResetPendingPointers() {
+  is_drag_ = false;
+  pending_pointer_down_timestamps_.reset();
+  pending_pointer_up_timestamps_.reset();
+}
+
+// For multi-finger touch, we record the innermost pair of pointerdown and
+// pointerup.
+// TODO(hbsong): Record one interaction per pointer id.
+void ResponsivenessMetrics::RecordTapOrClickOrDrag(
+    LocalDOMWindow* window,
+    const AtomicString& event_type,
+    EventTimestamps event_timestamps) {
+  if (event_type == event_type_names::kPointercancel) {
+    pending_pointer_down_timestamps_.reset();
+  } else if (event_type == event_type_names::kPointerdown) {
+    FlushPendingInteraction(window);
+    pending_pointer_down_timestamps_ = event_timestamps;
+  } else if (event_type == event_type_names::kPointerup &&
+             pending_pointer_down_timestamps_.has_value() &&
+             !pending_pointer_up_timestamps_.has_value()) {
+    pending_pointer_up_timestamps_ = event_timestamps;
+  } else if (event_type == event_type_names::kClick) {
+    WTF::Vector<EventTimestamps> timestamps;
+    // Insertion order matters for latency computation.
+    if (pending_pointer_down_timestamps_.has_value()) {
+      timestamps.push_back(pending_pointer_down_timestamps_.value());
+    }
+    if (pending_pointer_up_timestamps_.has_value()) {
+      timestamps.push_back(pending_pointer_up_timestamps_.value());
+    }
+    timestamps.push_back(event_timestamps);
+    RecordUserInteractionUKM(window,
+                             is_drag_ ? UserInteractionType::kDrag
+                                      : UserInteractionType::kTapOrClick,
+                             MaxEventDuration(timestamps),
+                             TotalEventDuration(timestamps));
+    ResetPendingPointers();
+  }
+}
+
+void ResponsivenessMetrics::RecordKeyboardInteractions(
+    LocalDOMWindow* window,
+    const AtomicString& event_type,
+    int key_code,
+    EventTimestamps event_timestamps) {
+  if (event_type == event_type_names::kKeydown) {
+    if (key_down_timestamps_map_.find(key_code) !=
+        key_down_timestamps_map_.end()) {
+      // Found a previous key_down with the same keycode, which means a key is
+      // being held down. We regard the duration of the keydown as an
+      // interaction level latency.
+      EventTimestamps key_down_timestamps =
+          key_down_timestamps_map_.at(key_code);
+      base::TimeDelta event_duration =
+          key_down_timestamps.end_time - key_down_timestamps.start_time;
+      RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+                               event_duration, event_duration);
+    }
+    key_down_timestamps_map_[key_code] = event_timestamps;
+  } else if (event_type == event_type_names::kKeyup) {
+    if (key_down_timestamps_map_.find(key_code) !=
+        key_down_timestamps_map_.end()) {
+      // Found a previous key_down with the same keycode as keyup.
+      // We calculate the interaction latency based on the durations of keydown
+      // and keyup.
+      EventTimestamps key_down_timestamps =
+          key_down_timestamps_map_.at(key_code);
+      WTF::Vector<EventTimestamps> timestamps;
+      // Insertion order matters for latency computation.
+      timestamps.push_back(key_down_timestamps);
+      timestamps.push_back(event_timestamps);
+      RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+                               MaxEventDuration(timestamps),
+                               TotalEventDuration(timestamps));
+      // Remove the stale keydown.
+      key_down_timestamps_map_.erase(key_code);
+    } else {
+      // Can't find a corresponding keydown. We regard the duration of the keyup
+      // as an interaction latency.
+      base::TimeDelta event_duration =
+          event_timestamps.end_time - event_timestamps.start_time;
+      RecordUserInteractionUKM(window, UserInteractionType::kKeyboard,
+                               event_duration, event_duration);
+    }
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/responsiveness_metrics.h b/third_party/blink/renderer/core/timing/responsiveness_metrics.h
new file mode 100644
index 0000000..dd683f2
--- /dev/null
+++ b/third_party/blink/renderer/core/timing/responsiveness_metrics.h
@@ -0,0 +1,93 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
+
+#include <algorithm>
+#include <random>
+#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+
+namespace blink {
+
+// Enum class for user interaction types. It's used in UKM and should not be
+// changed.
+enum class UserInteractionType { kKeyboard = 0, kTapOrClick = 1, kDrag = 2 };
+
+class ResponsivenessMetrics {
+ public:
+  ResponsivenessMetrics();
+  ~ResponsivenessMetrics();
+
+  // Timestamps for input events.
+  struct EventTimestamps {
+    // The event creation time.
+    base::TimeTicks start_time;
+    // The time when the first display update caused by the input event was
+    // performed.
+    base::TimeTicks end_time;
+  };
+
+  // Track ongoing user interactions and calculate the latency when an
+  // interaction is completed. The latency data for each interaction will be
+  // recored in UKM.
+  void RecordPerInteractionLatency(LocalDOMWindow* window,
+                                   const AtomicString& event_type,
+                                   absl::optional<int> key_code,
+                                   absl::optional<PointerId> pointer_id,
+                                   EventTimestamps event_timestamps);
+  // Useful for testing.
+  void SetUkmRecorder(ukm::UkmRecorder* ukm_recorder) {
+    ukm_recorder_ = ukm_recorder;
+  }
+
+  // Stop UKM sampling for testing.
+  void StopUkmSamplingForTesting() { sampling_ = false; }
+
+  // The use might be dragging. The function will be called whenever we have a
+  // pointermove.
+  void NotifyPotentialDrag();
+
+ private:
+  // Record UKM for user interaction latencies.
+  void RecordUserInteractionUKM(LocalDOMWindow* window,
+                                UserInteractionType interaction_type,
+                                base::TimeDelta max_event_duration,
+                                base::TimeDelta total_devent_duration);
+
+  void RecordKeyboardInteractions(LocalDOMWindow* window,
+                                  const AtomicString& event_type,
+                                  int key_code,
+                                  EventTimestamps event_timestamps);
+
+  // Might not be accurate for multi-fingers touch.
+  void RecordTapOrClickOrDrag(LocalDOMWindow* window,
+                              const AtomicString& event_type,
+                              EventTimestamps event_timestamps);
+  // Flush the latency data for pending tap or drag.
+  void FlushPendingInteraction(LocalDOMWindow* window);
+
+  // Reset the latency data for pointer events.
+  void ResetPendingPointers();
+
+  // Variables for per-interaction latencies.
+  std::map<int, EventTimestamps> key_down_timestamps_map_;
+
+  absl::optional<EventTimestamps> pending_pointer_up_timestamps_;
+  absl::optional<EventTimestamps> pending_pointer_down_timestamps_;
+  bool is_drag_ = false;
+  ukm::UkmRecorder* ukm_recorder_;
+
+  // Varibales for UKM sampling.
+  std::mt19937 generator_;
+  std::uniform_int_distribution<uint32_t> distribution_;
+  // Whether to perform UKM sampling.
+  bool sampling_ = true;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_RESPONSIVENESS_METRICS_H_
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc
index 5aef1ad..90427a4 100644
--- a/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -41,6 +41,8 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/qualified_name.h"
+#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
@@ -56,6 +58,7 @@
 #include "third_party/blink/renderer/core/timing/performance_event_timing.h"
 #include "third_party/blink/renderer/core/timing/performance_observer.h"
 #include "third_party/blink/renderer/core/timing/performance_timing.h"
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
 #include "third_party/blink/renderer/core/timing/visibility_state_entry.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -171,6 +174,10 @@
   }
 }
 
+void WindowPerformance::EventData::Trace(Visitor* visitor) const {
+  visitor->Trace(event_timing_);
+}
+
 WindowPerformance::~WindowPerformance() = default;
 
 ExecutionContext* WindowPerformance::GetExecutionContext() const {
@@ -239,11 +246,12 @@
 }
 
 void WindowPerformance::Trace(Visitor* visitor) const {
-  visitor->Trace(event_timings_);
+  visitor->Trace(events_data_);
   visitor->Trace(first_pointer_down_event_timing_);
   visitor->Trace(event_counts_);
   visitor->Trace(navigation_);
   visitor->Trace(timing_);
+  visitor->Trace(current_event_);
   Performance::Trace(visitor);
   PerformanceMonitor::Client::Trace(visitor);
   ExecutionContextClient::Trace(visitor);
@@ -344,43 +352,35 @@
   }
 }
 
-void WindowPerformance::RegisterEventTiming(const AtomicString& event_type,
-                                            base::TimeTicks start_time,
-                                            base::TimeTicks processing_start,
-                                            base::TimeTicks processing_end,
-                                            bool cancelable,
-                                            Node* target) {
+void WindowPerformance::RegisterEventTiming(
+    const AtomicString& event_type,
+    base::TimeTicks start_time,
+    base::TimeTicks processing_start,
+    base::TimeTicks processing_end,
+    bool cancelable,
+    Node* target,
+    absl::optional<int> key_code,
+    absl::optional<PointerId> pointer_id) {
   // |start_time| could be null in some tests that inject input.
   DCHECK(!processing_start.is_null());
   DCHECK(!processing_end.is_null());
   DCHECK_GE(processing_end, processing_start);
   if (!DomWindow())
     return;
-
-  // Count non-pointerevent Events. Avoid double counting pointerevents
-  // because we count them in pointer_event_manager.cc. Note click, auxclick and
-  // contextmenu are PointerEvent but the dispatch process of them are different
-  // from other PointerEvent.
-  if (event_type != event_type_names::kPointerover &&
-      event_type != event_type_names::kPointerenter &&
-      event_type != event_type_names::kPointerdown &&
-      event_type != event_type_names::kPointerup &&
-      event_type != event_type_names::kPointercancel &&
-      event_type != event_type_names::kPointerout &&
-      event_type != event_type_names::kPointerleave &&
-      event_type != event_type_names::kGotpointercapture &&
-      event_type != event_type_names::kLostpointercapture) {
-    eventCounts()->Add(event_type);
+  if (event_type == event_type_names::kPointermove) {
+    NotifyPotentialDrag();
+    SetCurrentEventTimingEvent(nullptr);
+    return;
   }
-
+  eventCounts()->Add(event_type);
   PerformanceEventTiming* entry = PerformanceEventTiming::Create(
       event_type, MonotonicTimeToDOMHighResTimeStamp(start_time),
       MonotonicTimeToDOMHighResTimeStamp(processing_start),
       MonotonicTimeToDOMHighResTimeStamp(processing_end), cancelable, target);
   // Add |entry| to the end of the queue along with the frame index at which is
   // is being queued to know when to queue a presentation promise for it.
-  event_timings_.push_back(entry);
-  event_frames_.push_back(frame_index_);
+  events_data_.push_back(
+      EventData::Create(entry, frame_index_, start_time, key_code, pointer_id));
   bool should_queue_presentation_promise = false;
   // If there are no pending presentation promises, we should queue one. This
   // ensures that |event_timings_| are processed even if the Blink lifecycle
@@ -402,16 +402,16 @@
     last_registered_frame_index_ = frame_index_;
     ++pending_presentation_promise_count_;
   }
+  SetCurrentEventTimingEvent(nullptr);
 }
 
-void WindowPerformance::ReportEventTimings(uint64_t frame_index,
-                                           WebSwapResult result,
-                                           base::TimeTicks timestamp) {
+void WindowPerformance::ReportEventTimings(
+    uint64_t frame_index,
+    WebSwapResult result,
+    base::TimeTicks presentation_timestamp) {
   DCHECK(pending_presentation_promise_count_);
   --pending_presentation_promise_count_;
-  // |event_timings_| and |event_frames_| should always have the same size.
-  DCHECK(event_timings_.size() == event_frames_.size());
-  if (event_timings_.IsEmpty())
+  if (events_data_.IsEmpty())
     return;
 
   if (!DomWindow())
@@ -420,19 +420,27 @@
       InteractiveDetector::From(*(DomWindow()->document()));
   bool event_timing_enabled =
       RuntimeEnabledFeatures::EventTimingEnabled(GetExecutionContext());
-  DOMHighResTimeStamp end_time = MonotonicTimeToDOMHighResTimeStamp(timestamp);
-  while (!event_timings_.IsEmpty()) {
-    PerformanceEventTiming* entry = event_timings_.front();
-    uint64_t entry_frame_index = event_frames_.front();
+  DOMHighResTimeStamp end_time =
+      MonotonicTimeToDOMHighResTimeStamp(presentation_timestamp);
+  while (!events_data_.IsEmpty()) {
+    auto event_data = events_data_.front();
+    PerformanceEventTiming* entry = event_data->GetEventTiming();
+    uint64_t entry_frame_index = event_data->GetFrameIndex();
+    base::TimeTicks event_timestamp = event_data->GetEventTimestamp();
+    absl::optional<int> key_code = event_data->GetKeyCode();
+    absl::optional<PointerId> pointer_id = event_data->GetPointerId();
     // If the entry was queued at a frame index that is larger than
     // |frame_index|, then we've reached the end of the entries that we can
     // process during this callback.
     if (entry_frame_index > frame_index)
       break;
 
-    event_timings_.pop_front();
-    event_frames_.pop_front();
+    events_data_.pop_front();
 
+    ResponsivenessMetrics::EventTimestamps event_timestamps = {
+        event_timestamp, presentation_timestamp};
+    responsiveness_metrics_.RecordPerInteractionLatency(
+        DomWindow(), entry->name(), key_code, pointer_id, event_timestamps);
     int duration_in_ms = std::round((end_time - entry->startTime()) / 8) * 8;
     base::TimeDelta input_delay = base::TimeDelta::FromMillisecondsD(
         entry->processingStart() - entry->startTime());
@@ -586,4 +594,8 @@
   ++frame_index_;
 }
 
+void WindowPerformance::NotifyPotentialDrag() {
+  responsiveness_metrics_.NotifyPotentialDrag();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/window_performance.h b/third_party/blink/renderer/core/timing/window_performance.h
index 44bac04..93d1f69 100644
--- a/third_party/blink/renderer/core/timing/window_performance.h
+++ b/third_party/blink/renderer/core/timing/window_performance.h
@@ -35,14 +35,17 @@
 #include "base/rand_util.h"
 #include "third_party/blink/public/web/web_swap_result.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/frame/performance_monitor.h"
 #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
 #include "third_party/blink/renderer/core/timing/event_counts.h"
+#include "third_party/blink/renderer/core/timing/event_timing.h"
 #include "third_party/blink/renderer/core/timing/memory_info.h"
 #include "third_party/blink/renderer/core/timing/performance.h"
 #include "third_party/blink/renderer/core/timing/performance_navigation.h"
 #include "third_party/blink/renderer/core/timing/performance_timing.h"
+#include "third_party/blink/renderer/core/timing/responsiveness_metrics.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 
 namespace blink {
@@ -55,6 +58,52 @@
                                             public PageVisibilityObserver {
   friend class WindowPerformanceTest;
 
+  class EventData : public GarbageCollected<EventData> {
+   public:
+    EventData(PerformanceEventTiming* event_timing,
+              uint64_t frame,
+              base::TimeTicks event_timestamp,
+              absl::optional<int> key_code,
+              absl::optional<PointerId> pointer_id)
+        : event_timing_(event_timing),
+          frame_(frame),
+          event_timestamp_(event_timestamp),
+          key_code_(key_code),
+          pointer_id_(pointer_id) {}
+
+    static EventData* Create(PerformanceEventTiming* event_timing,
+                             uint64_t frame,
+                             base::TimeTicks event_timestamp,
+                             absl::optional<int> key_code,
+                             absl::optional<PointerId> pointer_id) {
+      return MakeGarbageCollected<EventData>(
+          event_timing, frame, event_timestamp, key_code, pointer_id);
+    }
+    ~EventData() = default;
+    void Trace(Visitor*) const;
+    PerformanceEventTiming* GetEventTiming() { return event_timing_; }
+    uint64_t GetFrameIndex() { return frame_; }
+    base::TimeTicks GetEventTimestamp() { return event_timestamp_; }
+    absl::optional<int> GetKeyCode() { return key_code_; }
+    absl::optional<PointerId> GetPointerId() { return pointer_id_; }
+
+   private:
+    // Event PerformanceEventTiming entry that has not been sent to observers
+    // yet: the event dispatch has been completed but the presentation promise
+    // used to determine |duration| has not yet been resolved.
+    Member<PerformanceEventTiming> event_timing_;
+    // Frame index in which the entry in |event_timing_| were added.
+    uint64_t frame_;
+    // The event creation timestamp.
+    base::TimeTicks event_timestamp_;
+    // Keycode for the event. If the event is not a keyboard event, the keycode
+    // wouldn't be set.
+    absl::optional<int> key_code_;
+    // PointerId for the event. If the event is not a pointer event, the
+    // PointerId wouldn't be set.
+    absl::optional<PointerId> pointer_id_;
+  };
+
  public:
   explicit WindowPerformance(LocalDOMWindow*);
   ~WindowPerformance() override;
@@ -78,7 +127,9 @@
                            base::TimeTicks processing_start,
                            base::TimeTicks processing_end,
                            bool cancelable,
-                           Node*);
+                           Node*,
+                           absl::optional<int> key_code,
+                           absl::optional<PointerId> pointer_id);
 
   void OnPaintFinished();
 
@@ -107,6 +158,17 @@
 
   void Trace(Visitor*) const override;
 
+  ResponsivenessMetrics& GetResponsivenessMetrics() {
+    return responsiveness_metrics_;
+  }
+
+  void NotifyPotentialDrag();
+
+  void SetCurrentEventTimingEvent(const Event* event) {
+    current_event_ = event;
+  }
+  const Event* GetCurrentEventTimingEvent() { return current_event_; }
+
  private:
   PerformanceNavigationTiming* CreateNavigationTimingInstance() override;
 
@@ -123,11 +185,12 @@
 
   void BuildJSONValue(V8ObjectBuilder&) const override;
 
-  // Method called once presentation promise is resolved. It will add all event
-  // timings that have not been added since the last presentation promise.
+  // Method called once presentation promise for a frame is resolved. It will
+  // add all event timings that have not been added since the last presentation
+  // promise.
   void ReportEventTimings(uint64_t frame_index,
                           WebSwapResult result,
-                          base::TimeTicks timestamp);
+                          base::TimeTicks presentation_timestamp);
 
   void DispatchFirstInputTiming(PerformanceEventTiming* entry);
 
@@ -138,19 +201,10 @@
   uint64_t last_registered_frame_index_ = 0;
   // Number of pending presentation promises.
   uint16_t pending_presentation_promise_count_ = 0;
-  // PerformanceEventTiming entries that have not been sent to observers yet:
-  // the event dispatch has been completed but the presentation promise used to
-  // determine |duration| has not yet been resolved. It is handled as a queue:
-  // FIFO.
-  HeapDeque<Member<PerformanceEventTiming>> event_timings_;
-  // Entries corresponding to frame indices in which the entries in
-  // |event_timings_| were added. This could be combined with |event_timings_|
-  // into a single deque, but PerformanceEventTiming is GarbageCollected so it
-  // would need to be a HeapDeque. HeapDeque does not allow std::pair as its
-  // type, so we would have to add a new wrapper GarbageCollected class that
-  // contains the PerformanceEventTiming object as well as the frame index. This
-  // is more work than having two separate deques.
-  Deque<uint64_t> event_frames_;
+  // Store all event timing and latency related data, including
+  // PerformanceEventTiming, frame_index, keycode and pointerId. We use the data
+  // to calculate events latencies.
+  HeapDeque<Member<EventData>> events_data_;
   Member<PerformanceEventTiming> first_pointer_down_event_timing_;
   Member<EventCounts> event_counts_;
   mutable Member<PerformanceNavigation> navigation_;
@@ -158,6 +212,11 @@
   absl::optional<base::TimeDelta> pending_pointer_down_input_delay_;
   absl::optional<base::TimeDelta> pending_pointer_down_processing_time_;
   absl::optional<base::TimeDelta> pending_pointer_down_time_to_next_paint_;
+
+  // Calculate responsiveness metrics and record UKM for them.
+  ResponsivenessMetrics responsiveness_metrics_;
+  // The event we are currently processing.
+  WeakMember<const Event> current_event_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc
index 08438ad2..1c7aef54 100644
--- a/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/core/timing/window_performance.h"
 
 #include "base/test/test_mock_time_task_runner.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -29,6 +31,10 @@
   return base::TimeTicks() + base::TimeDelta::FromSeconds(500);
 }
 
+base::TimeTicks GetTimeStamp(int64_t time) {
+  return GetTimeOrigin() + base::TimeDelta::FromMilliseconds(time);
+}
+
 }  // namespace
 
 class WindowPerformanceTest : public testing::Test {
@@ -89,6 +95,8 @@
     performance_->SetClocksForTesting(test_task_runner_->GetMockClock(),
                                       test_task_runner_->GetMockTickClock());
     performance_->time_origin_ = GetTimeOrigin();
+    // Stop UKM sampling for testing.
+    performance_->GetResponsivenessMetrics().StopUkmSamplingForTesting();
   }
 
   ScriptState* GetScriptState() const {
@@ -246,7 +254,7 @@
   base::TimeTicks processing_end =
       GetTimeOrigin() + base::TimeDelta::FromSecondsD(3.8);
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   base::TimeTicks swap_time =
       GetTimeOrigin() + base::TimeDelta::FromSecondsD(6.0);
   SimulateSwapPromise(swap_time);
@@ -258,7 +266,7 @@
       ->GetTiming()
       .MarkLoadEventStart();
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, true, nullptr);
+                                    processing_end, true, nullptr, 4, 4);
   SimulateSwapPromise(swap_time);
   EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
 
@@ -266,7 +274,7 @@
   GetFrame()->DetachDocument();
   EXPECT_FALSE(page_holder_->GetFrame().Loader().GetDocumentLoader());
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   SimulateSwapPromise(swap_time);
   EXPECT_EQ(3u, performance_->getBufferedEntriesByType("event").size());
 }
@@ -280,12 +288,12 @@
   base::TimeTicks processing_end =
       processing_start + base::TimeDelta::FromMilliseconds(10);
   performance_->RegisterEventTiming("mousedown", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
 
   base::TimeTicks start_time2 =
       start_time + base::TimeDelta::FromMicroseconds(200);
   performance_->RegisterEventTiming("click", start_time2, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
 
   // The swap time is 100.1 ms after |start_time| but only 99.9 ms after
   // |start_time2|.
@@ -308,24 +316,24 @@
   base::TimeTicks processing_end =
       GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1002);
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   base::TimeTicks short_swap_time =
       GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1003);
   SimulateSwapPromise(short_swap_time);
   EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
 
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, true, nullptr);
+                                    processing_end, true, nullptr, 4, 4);
   base::TimeTicks long_swap_time =
       GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2000);
   SimulateSwapPromise(long_swap_time);
   EXPECT_EQ(1u, performance_->getBufferedEntriesByType("event").size());
 
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, true, nullptr);
+                                    processing_end, true, nullptr, 4, 4);
   SimulateSwapPromise(short_swap_time);
   performance_->RegisterEventTiming("click", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   SimulateSwapPromise(long_swap_time);
   EXPECT_EQ(2u, performance_->getBufferedEntriesByType("event").size());
 }
@@ -344,7 +352,7 @@
     base::TimeTicks processing_end =
         start_time + base::TimeDelta::FromMilliseconds(200);
     performance_->RegisterEventTiming("click", start_time, processing_start,
-                                      processing_end, false, nullptr);
+                                      processing_end, false, nullptr, 4, 4);
     EXPECT_EQ(0u, performance_->getBufferedEntriesByType("event").size());
   }
   base::TimeTicks swap_time =
@@ -366,7 +374,8 @@
     performance_->RegisterEventTiming(
         input.event_type, GetTimeOrigin(),
         GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
-        GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
+        GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr,
+        4, 4);
     SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
     PerformanceEntryVector firstInputs =
         performance_->getEntriesByType("first-input");
@@ -384,7 +393,8 @@
     performance_->RegisterEventTiming(
         event, GetTimeOrigin(),
         GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1),
-        GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr);
+        GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2), false, nullptr,
+        4, 4);
     SimulateSwapPromise(GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3));
   }
   ASSERT_EQ(1u, performance_->getEntriesByType("first-input").size());
@@ -394,19 +404,16 @@
 
 // Test that pointerdown followed by pointerup works as a 'firstInput'.
 TEST_F(WindowPerformanceTest, FirstPointerUp) {
-  base::TimeTicks start_time = GetTimeOrigin();
-  base::TimeTicks processing_start =
-      GetTimeOrigin() + base::TimeDelta::FromMilliseconds(1);
-  base::TimeTicks processing_end =
-      GetTimeOrigin() + base::TimeDelta::FromMilliseconds(2);
-  base::TimeTicks swap_time =
-      GetTimeOrigin() + base::TimeDelta::FromMilliseconds(3);
+  base::TimeTicks start_time = GetTimeStamp(0);
+  base::TimeTicks processing_start = GetTimeStamp(1);
+  base::TimeTicks processing_end = GetTimeStamp(2);
+  base::TimeTicks swap_time = GetTimeStamp(3);
   performance_->RegisterEventTiming("pointerdown", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   SimulateSwapPromise(swap_time);
   EXPECT_EQ(0u, performance_->getEntriesByType("first-input").size());
   performance_->RegisterEventTiming("pointerup", start_time, processing_start,
-                                    processing_end, false, nullptr);
+                                    processing_end, false, nullptr, 4, 4);
   SimulateSwapPromise(swap_time);
   EXPECT_EQ(1u, performance_->getEntriesByType("first-input").size());
   // The name of the entry should be "pointerdown".
@@ -414,4 +421,442 @@
       1u, performance_->getEntriesByName("pointerdown", "first-input").size());
 }
 
+TEST_F(WindowPerformanceTest, OneKeyboardInteraction) {
+  base::TimeTicks keydown_timestamp = GetTimeStamp(0);
+  // Keydown
+  base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+  base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+  base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = absl::nullopt;
+  absl::optional<int> key_code = 2;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+  // Keyup
+  base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+  base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+  base::TimeTicks swap_time_keyup = GetTimeStamp(10);
+  performance_->RegisterEventTiming(
+      "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+      false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keyup);
+
+  // Check UKM recording.
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder.GetMergedEntriesByName(
+          ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(1u, merged_entries.size());
+  for (const auto& kv : merged_entries) {
+    const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+        7);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+        10);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+  }
+}
+
+TEST_F(WindowPerformanceTest, HoldingDownAKey) {
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  auto entries = test_ukm_recorder.GetEntriesByName(
+      ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(0u, entries.size());
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  // First Keydown
+  base::TimeTicks keydown_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+  base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+  base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = absl::nullopt;
+  absl::optional<int> key_code = 2;
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+
+  // Second Keydown
+  keydown_timestamp = GetTimeStamp(1);
+  processing_start_keydown = GetTimeStamp(2);
+  processing_end_keydown = GetTimeStamp(3);
+  swap_time_keydown = GetTimeStamp(7);
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+
+  // Third Keydown
+  keydown_timestamp = GetTimeStamp(2);
+  processing_start_keydown = GetTimeStamp(3);
+  processing_end_keydown = GetTimeStamp(5);
+  swap_time_keydown = GetTimeStamp(9);
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+
+  // Keyup
+  base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+  base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+  base::TimeTicks swap_time_keyup = GetTimeStamp(13);
+  performance_->RegisterEventTiming(
+      "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+      false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keyup);
+
+  // Check UKM recording.
+  entries = test_ukm_recorder.GetEntriesByName(
+      ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(3u, entries.size());
+  std::vector<std::pair<int, int>> expected_durations;
+  expected_durations.emplace_back(std::make_pair(5, 5));
+  expected_durations.emplace_back(std::make_pair(6, 6));
+  expected_durations.emplace_back(std::make_pair(10, 11));
+  for (std::size_t i = 0; i < entries.size(); ++i) {
+    auto* entry = entries[i];
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+        expected_durations[i].first);
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+        expected_durations[i].second);
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+  }
+}
+
+TEST_F(WindowPerformanceTest, PressMultipleKeys) {
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  auto entries = test_ukm_recorder.GetEntriesByName(
+      ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(0u, entries.size());
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  // Press the first key.
+  base::TimeTicks keydown_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+  base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+  base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = absl::nullopt;
+  absl::optional<int> first_key_code = 2;
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, first_key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+
+  // Press the second key.
+  processing_start_keydown = GetTimeStamp(2);
+  processing_end_keydown = GetTimeStamp(3);
+  swap_time_keydown = GetTimeStamp(7);
+  absl::optional<int> second_key_code = 4;
+  performance_->RegisterEventTiming(
+      "keydown", keydown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, second_key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+
+  // Release the first key.
+  base::TimeTicks keyup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+  base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+  base::TimeTicks swap_time_keyup = GetTimeStamp(13);
+  performance_->RegisterEventTiming(
+      "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+      false, nullptr, first_key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keyup);
+
+  // Release the second key.
+  keyup_timestamp = GetTimeStamp(5);
+  processing_start_keyup = GetTimeStamp(5);
+  processing_end_keyup = GetTimeStamp(6);
+  swap_time_keyup = GetTimeStamp(20);
+  performance_->RegisterEventTiming(
+      "keyup", keyup_timestamp, processing_start_keyup, processing_end_keyup,
+      false, nullptr, second_key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keyup);
+
+  // Check UKM recording.
+  entries = test_ukm_recorder.GetEntriesByName(
+      ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(2u, entries.size());
+  std::vector<std::pair<int, int>> expected_durations;
+  expected_durations.emplace_back(std::make_pair(10, 13));
+  expected_durations.emplace_back(std::make_pair(15, 20));
+  for (std::size_t i = 0; i < entries.size(); ++i) {
+    auto* entry = entries[i];
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+        expected_durations[i].first);
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+        expected_durations[i].second);
+    test_ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 0);
+  }
+}
+
+TEST_F(WindowPerformanceTest, TapOrClick) {
+  // Pointerdown
+  base::TimeTicks pointerdwon_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+  base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+  base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = 4;
+  absl::optional<int> key_code = absl::nullopt;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdwon_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerdown);
+  // Pointerup
+  base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+  base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+  base::TimeTicks swap_time_pointerup = GetTimeStamp(10);
+  performance_->RegisterEventTiming(
+      "pointerup", pointerup_timestamp, processing_start_pointerup,
+      processing_end_pointerup, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerup);
+  // Click
+  base::TimeTicks click_timestamp = GetTimeStamp(13);
+  base::TimeTicks processing_start_click = GetTimeStamp(15);
+  base::TimeTicks processing_end_click = GetTimeStamp(16);
+  base::TimeTicks swap_time_click = GetTimeStamp(20);
+  performance_->RegisterEventTiming(
+      "click", click_timestamp, processing_start_click, processing_end_click,
+      false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_click);
+
+  // Check UKM recording.
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder.GetMergedEntriesByName(
+          ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(1u, merged_entries.size());
+  for (const auto& kv : merged_entries) {
+    const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+        7);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+        17);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 1);
+  }
+}
+
+TEST_F(WindowPerformanceTest, Drag) {
+  // Pointerdown
+  base::TimeTicks pointerdwon_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+  base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+  base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = 4;
+  absl::optional<int> key_code = absl::nullopt;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdwon_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerdown);
+  // Notify drag.
+  performance_->NotifyPotentialDrag();
+  // Pointerup
+  base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+  base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+  base::TimeTicks swap_time_pointerup = GetTimeStamp(10);
+  performance_->RegisterEventTiming(
+      "pointerup", pointerup_timestamp, processing_start_pointerup,
+      processing_end_pointerup, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerup);
+  // Click
+  base::TimeTicks click_timestamp = GetTimeStamp(13);
+  base::TimeTicks processing_start_click = GetTimeStamp(15);
+  base::TimeTicks processing_end_click = GetTimeStamp(16);
+  base::TimeTicks swap_time_click = GetTimeStamp(20);
+  performance_->RegisterEventTiming(
+      "click", click_timestamp, processing_start_click, processing_end_click,
+      false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_click);
+
+  // Check UKM recording.
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder.GetMergedEntriesByName(
+          ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(1u, merged_entries.size());
+  for (const auto& kv : merged_entries) {
+    const ukm::mojom::UkmEntry* ukm_entry = kv.second.get();
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName,
+        7);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+        17);
+    test_ukm_recorder.ExpectEntryMetric(
+        ukm_entry,
+        ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 2);
+  }
+}
+
+TEST_F(WindowPerformanceTest, Scroll) {
+  // Pointerdown
+  base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_keydown = GetTimeStamp(1);
+  base::TimeTicks processing_end_keydown = GetTimeStamp(2);
+  base::TimeTicks swap_time_keydown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = 5;
+  absl::optional<int> key_code = absl::nullopt;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdown_timestamp, processing_start_keydown,
+      processing_end_keydown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keydown);
+  // Pointercancel
+  base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_keyup = GetTimeStamp(5);
+  base::TimeTicks processing_end_keyup = GetTimeStamp(6);
+  base::TimeTicks swap_time_keyup = GetTimeStamp(10);
+  performance_->RegisterEventTiming(
+      "pointercancel", pointerup_timestamp, processing_start_keyup,
+      processing_end_keyup, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_keyup);
+
+  // Check UKM recording.
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder.GetMergedEntriesByName(
+          ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(0u, merged_entries.size());
+}
+
+TEST_F(WindowPerformanceTest, TouchesWithoutClick) {
+  base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+  // First Pointerdown
+  base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+  base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+  base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id = 4;
+  absl::optional<int> key_code = absl::nullopt;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerdown);
+
+  // Second Pointerdown
+  pointerdown_timestamp = GetTimeStamp(6);
+  processing_start_pointerdown = GetTimeStamp(7);
+  processing_end_pointerdown = GetTimeStamp(8);
+  swap_time_pointerdown = GetTimeStamp(15);
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id);
+  SimulateSwapPromise(swap_time_pointerdown);
+
+  // Check UKM recording.
+  std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
+      test_ukm_recorder.GetMergedEntriesByName(
+          ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(0u, merged_entries.size());
+}
+
+// For multi-touch, we only record the innermost pair of pointerdown and
+// pointerup.
+// TODO(hbsong): Record each touch by pointer_id separately.
+TEST_F(WindowPerformanceTest, MultiTouch) {
+  // First Pointerdown
+  base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
+  base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
+  base::TimeTicks processing_end_pointerdown = GetTimeStamp(2);
+  base::TimeTicks swap_time_pointerdown = GetTimeStamp(5);
+  absl::optional<PointerId> pointer_id_1 = 4;
+  absl::optional<int> key_code = absl::nullopt;
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id_1);
+  SimulateSwapPromise(swap_time_pointerdown);
+  // Second Pointerdown
+  pointerdown_timestamp = GetTimeOrigin();
+  processing_start_pointerdown = GetTimeStamp(1);
+  processing_end_pointerdown = GetTimeStamp(2);
+  swap_time_pointerdown = GetTimeStamp(6);
+  absl::optional<PointerId> pointer_id_2 = 6;
+  performance_->GetResponsivenessMetrics().SetUkmRecorder(&test_ukm_recorder);
+  performance_->RegisterEventTiming(
+      "pointerdown", pointerdown_timestamp, processing_start_pointerdown,
+      processing_end_pointerdown, false, nullptr, key_code, pointer_id_2);
+  SimulateSwapPromise(swap_time_pointerdown);
+
+  // First Pointerup
+  base::TimeTicks pointerup_timestamp = GetTimeStamp(3);
+  base::TimeTicks processing_start_pointerup = GetTimeStamp(5);
+  base::TimeTicks processing_end_pointerup = GetTimeStamp(6);
+  base::TimeTicks swap_time_pointerup = GetTimeStamp(9);
+  performance_->RegisterEventTiming(
+      "pointerup", pointerup_timestamp, processing_start_pointerup,
+      processing_end_pointerup, false, nullptr, key_code, pointer_id_2);
+  SimulateSwapPromise(swap_time_pointerup);
+
+  // Second Pointerup
+  pointerup_timestamp = GetTimeStamp(5);
+  processing_start_pointerup = GetTimeStamp(6);
+  processing_end_pointerup = GetTimeStamp(7);
+  swap_time_pointerup = GetTimeStamp(13);
+  performance_->RegisterEventTiming(
+      "pointerup", pointerup_timestamp, processing_start_pointerup,
+      processing_end_pointerup, false, nullptr, key_code, pointer_id_1);
+  SimulateSwapPromise(swap_time_pointerup);
+
+  // Click
+  base::TimeTicks click_timestamp = GetTimeStamp(13);
+  base::TimeTicks processing_start_click = GetTimeStamp(15);
+  base::TimeTicks processing_end_click = GetTimeStamp(16);
+  base::TimeTicks swap_time_click = GetTimeStamp(20);
+  performance_->RegisterEventTiming(
+      "click", click_timestamp, processing_start_click, processing_end_click,
+      false, nullptr, key_code, pointer_id_2);
+  SimulateSwapPromise(swap_time_click);
+
+  // Check UKM recording.
+  auto entries = test_ukm_recorder.GetEntriesByName(
+      ukm::builders::Responsiveness_UserInteraction::kEntryName);
+  EXPECT_EQ(1u, entries.size());
+  auto* entry = entries[0];
+  test_ukm_recorder.ExpectEntryMetric(
+      entry,
+      ukm::builders::Responsiveness_UserInteraction::kMaxEventDurationName, 7);
+  test_ukm_recorder.ExpectEntryMetric(
+      entry,
+      ukm::builders::Responsiveness_UserInteraction::kTotalEventDurationName,
+      16);
+  test_ukm_recorder.ExpectEntryMetric(
+      entry,
+      ukm::builders::Responsiveness_UserInteraction::kInteractionTypeName, 1);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
index 264d6d9..d5b69556 100644
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
@@ -68,20 +68,19 @@
 ScriptPromise FrameQueueUnderlyingSource<NativeFrameType>::Start(
     ScriptState* script_state) {
   DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
-  if (!StartFrameDelivery()) {
-    // There is only one way in which this can fail for now. Perhaps
-    // implementations should return their own failure messages.
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        DOMException::Create(
-            "Invalid track",
-            DOMException::GetErrorName(DOMExceptionCode::kInvalidStateError)));
-  }
-  if (is_pending_close_) {
-    realm_task_runner_->PostTask(
-        FROM_HERE,
-        WTF::Bind(&FrameQueueUnderlyingSource<NativeFrameType>::Close,
-                  WrapWeakPersistent(this)));
+  if (is_closed_) {
+    // This was intended to be closed before Start() was called.
+    CloseController();
+  } else {
+    if (!StartFrameDelivery()) {
+      // There is only one way in which this can fail for now. Perhaps
+      // implementations should return their own failure messages.
+      return ScriptPromise::RejectWithDOMException(
+          script_state,
+          DOMException::Create("Invalid track",
+                               DOMException::GetErrorName(
+                                   DOMExceptionCode::kInvalidStateError)));
+    }
   }
 
   return ScriptPromise::CastUndefined(script_state);
@@ -105,8 +104,8 @@
 template <typename NativeFrameType>
 void FrameQueueUnderlyingSource<NativeFrameType>::ContextDestroyed() {
   DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
+  Close();
   UnderlyingSourceBase::ContextDestroyed();
-  frame_queue_handle_.Invalidate();
 }
 
 template <typename NativeFrameType>
@@ -121,16 +120,11 @@
   if (is_closed_)
     return;
 
-  // The source has not started. Postpone close until it starts.
-  if (!Controller()) {
-    is_pending_close_ = true;
-    return;
-  }
-
-  StopFrameDelivery();
-  CloseController();
-  frame_queue_handle_.Invalidate();
   is_closed_ = true;
+  if (Controller()) {
+    StopFrameDelivery();
+    CloseController();
+  }
   {
     MutexLocker locker(mutex_);
     num_pending_pulls_ = 0;
@@ -143,6 +137,7 @@
     }
     transferred_source_.Clear();
   }
+  frame_queue_handle_.Invalidate();
 }
 
 template <typename NativeFrameType>
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
index 43479b3..e0d0fd1 100644
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
@@ -49,10 +49,7 @@
   // Must be called on |realm_task_runner_|.
   void Close();
 
-  bool IsClosed() {
-    DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
-    return is_closed_;
-  }
+  bool IsClosed() { return is_closed_; }
 
   // Start or stop the delivery of frames via QueueFrame().
   // Must be called on |realm_task_runner_|.
@@ -97,7 +94,6 @@
   ScriptWrappable* MakeBlinkFrame(NativeFrameType media_frame);
 
   bool is_closed_ = false;
-  bool is_pending_close_ = false;
 
   // Main task runner for the window or worker context this source runs on.
   const scoped_refptr<base::SequencedTaskRunner> realm_task_runner_;
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
index 262495a8..73ec0c3 100644
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source_test.cc
@@ -213,4 +213,36 @@
   blink::WebHeap::CollectAllGarbageForTesting();
 }
 
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, CloseOnContextDestroyed) {
+  MediaStreamVideoTrackUnderlyingSource* source = nullptr;
+  {
+    V8TestingScope v8_scope;
+    ScriptState* script_state = v8_scope.GetScriptState();
+    auto* track = CreateTrack(v8_scope.GetExecutionContext());
+    source = CreateSource(script_state, track, 0u);
+    EXPECT_FALSE(source->IsClosed());
+    // Create a stream so that |source| starts.
+    auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+        v8_scope.GetScriptState(), source, 0);
+    EXPECT_FALSE(source->IsClosed());
+    EXPECT_FALSE(stream->IsClosed());
+  }
+  EXPECT_TRUE(source->IsClosed());
+}
+
+TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, CloseBeforeStart) {
+  V8TestingScope v8_scope;
+  ScriptState* script_state = v8_scope.GetScriptState();
+  auto* track = CreateTrack(v8_scope.GetExecutionContext());
+  auto* source = CreateSource(script_state, track, 0u);
+  EXPECT_FALSE(source->IsClosed());
+  source->Close();
+  EXPECT_TRUE(source->IsClosed());
+  // Create a stream so that the start method of |source| runs.
+  auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+      v8_scope.GetScriptState(), source, 0);
+  EXPECT_TRUE(source->IsClosed());
+  EXPECT_TRUE(stream->IsClosed());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
index dc6ef68..ccddd05 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -707,9 +707,14 @@
           client_data_buffer, attestation_buffer, credential->transports,
           authenticator_data, public_key_der, credential->public_key_algo);
 
-  resolver->Resolve(MakeGarbageCollected<PaymentCredential>(
-      credential->info->id, raw_id, authenticator_response,
-      AuthenticationExtensionsClientOutputs::Create()));
+  resolver->Resolve(
+      RuntimeEnabledFeatures::SecurePaymentConfirmationAPIV2Enabled()
+          ? MakeGarbageCollected<PublicKeyCredential>(
+                credential->info->id, raw_id, authenticator_response,
+                AuthenticationExtensionsClientOutputs::Create())
+          : MakeGarbageCollected<PaymentCredential>(
+                credential->info->id, raw_id, authenticator_response,
+                AuthenticationExtensionsClientOutputs::Create()));
 }
 
 void OnPaymentCredentialCreationFailure(
diff --git a/third_party/blink/renderer/modules/csspaint/README.md b/third_party/blink/renderer/modules/csspaint/README.md
index 26a07ad..4198246 100644
--- a/third_party/blink/renderer/modules/csspaint/README.md
+++ b/third_party/blink/renderer/modules/csspaint/README.md
@@ -11,11 +11,12 @@
 ## Workflow
 
 Historically the CSS Paint API (PaintWorklet) implementation ran on the main
-thread, but is currently being optimized to run on the compositor thread. We
-will use an example to show the workflow of both cases.
+thread. It has been optimized to run on the compositor thread. We will use an
+example to show the workflow of both cases.
 
 Here is a simple example of using PaintWorklet to draw something on the screen.
 
+``` html
 <style>
 #demo {
   background-image: paint(foo);
@@ -23,7 +24,7 @@
   height: 200px;
 }
 </style>
-<script>
+<script id="code" type="text/worklet">
 registerPaint('foo', class {
   paint(ctx, size) {
     ctx.fillStyle = 'green';
@@ -31,21 +32,48 @@
   }
 });
 </script>
+<script>
+var code = document.getElementById('code').textContent;
+var blob = new Blob([code], {type : 'text/javascript'});
+CSS.paintWorklet.addModule(URL.createObjectURL(blob));
+</script>
+```
 
 In our implementation, there is one [PaintWorklet](paint_worklet.h) instance
-created from the frame. There are two
-[PaintWorkletGlobalScope](paint_worklet_global_scope.h) created to enforce
-stateless. The number of global scopes can be arbitrary, and our implementation
-chose two.
+created from the frame.
 
-During `PaintWorkletGlobalScope#registerPaint`, the Javascript inside the paint
+### Main thread workflow
+
+Let's start with the two web-exposed APIs and dive into the main thread
+workflow. Specifically the two APIs are `addModule` and `registerPaint`.
+
+When `addModule` is executed, `Worklet::addModule` is called. There are two
+[PaintWorkletGlobalScope](paint_worklet_global_scope.h) created, and the
+[PaintWorkletGlobalScopeProxy](paint_worklet_global_scope_proxy.h) serves as the
+proxy when other classes need to communicate with PaintWorkletGlobalScope. We
+create two PaintWorkletGlobalScope to enforce stateless. The number of global
+scopes can be arbitrary as long as it is >= 2, and we chose two in our
+implementation.
+
+`registerPaint` is executed on each PaintWorkletGlobalScope. When the
+`PaintWorkletGlobalScope::registerPaint` is called, it creates a
+[CSSPaintDefinition](css_paint_definition.h) and PaintWorkletGlobalScope owns
+it. Besides that, it creates
+[DocumentPaintDefinition](document_paint_definition.h) which is owned by
+PaintWorklet. It then registers the CSSPaintDefinition to the
+DocumentPaintDefinition.
+
+Below is a diagram that shows what happens when `addModule` and `registerPaint`
+are called:
+
+![addModule and registerPaint call](images/addModule_registerPaint.png)
+
+During `PaintWorkletGlobalScope::registerPaint`, the Javascript inside the paint
 function is turned into a V8 paint callback. We randomly choose one of the two
 global scopes to execute the callback. The execution of the callback
 produces a PaintRecord, which contains a set of skia draw commands. The V8 paint
 callback is executed on a shared V8 isolate.
 
-### Main thread workflow
-
 During the main thread paint, the `PaintWorklet::Paint` is called, which
 executes the V8 paint callback synchronously. A PaintRecord is produced and
 passed to the compositor thread to raster.
@@ -53,6 +81,10 @@
 When animation is involved, the main thread animation system updates the value
 of the animated properties, which are used by the `PaintWorklet::Paint`.
 
+Below is a diagram that shows what happens when `PaintWorklet::Paint` is called.
+
+![PaintWorklet::Paint](images/PaintWorklet_Paint.png)
+
 ### Off main thread workflow
 
 Let's see how it works without animations.
diff --git a/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png b/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
new file mode 100644
index 0000000..1dc7fb43
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
Binary files differ
diff --git a/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot b/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot
new file mode 100644
index 0000000..e44bbca
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot
@@ -0,0 +1,7 @@
+// dot -Tpng third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png.dot > third_party/blink/renderer/modules/csspaint/images/PaintWorklet_Paint.png
+// When making modifications run the above command to regenerate the diagram
+
+digraph {
+  label = "Workflow of main thread paint worklet";
+  "CSSPaintImageGeneratorImpl\::Paint" -> "PaintWorklet\::Paint" -> FindAvaiableGlobalScope -> FindDefinition -> "CSSPaintDefinition\::Paint";
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png b/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
new file mode 100644
index 0000000..d1a48367
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
Binary files differ
diff --git a/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot b/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot
new file mode 100644
index 0000000..05cbf81
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot
@@ -0,0 +1,9 @@
+// dot -Tpng third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png.dot > third_party/blink/renderer/modules/csspaint/images/addModule_registerPaint.png
+// When making modifications run the above command to regenerate the diagram
+
+digraph {
+  label = "Workflow of addModule and registerPaint";
+  addModule -> CreateGlobalScope;
+  registerPaint -> "Create CSSPaintDefinition";
+  registerPaint -> RegisterCSSPaintDefinition -> "Create DocumentPaintDefinition";
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 3405045..5d95271f 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -178,7 +178,7 @@
   } else {
     uma_code = static_cast<DataChannelSctpErrorCode>(*code);
   }
-  base::UmaHistogramEnumeration("WebRTC.DataChannelSctpError", uma_code);
+  base::UmaHistogramEnumeration("WebRTC.DataChannelSctpErrorCode", uma_code);
 }
 
 void SendOnSignalingThread(
diff --git a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
index 64df3c3..c5c25cb 100644
--- a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
+++ b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.cc
@@ -85,18 +85,13 @@
 Sanitizer::Sanitizer(ExecutionContext* execution_context,
                      const SanitizerConfig* config) {
   // The spec treats an absent config as the default. We'll handle this by
-  // normalizing this here to make sure the config_dictionary_ is nullptr
-  // in these cases, while the config_ will be a copy of the default config.
+  // checking for this an empty dictionary and representing it as nullptr.
   if (ConfigIsEmpty(config)) {
     config = nullptr;
-  }
-
-  config_ = SanitizerConfigImpl::From(config);
-  config_dictionary_ = SanitizerConfigCopy(config);
-  if (!config_dictionary_) {
     UseCounter::Count(execution_context,
                       WebFeature::kSanitizerAPIDefaultConfiguration);
   }
+  config_ = SanitizerConfigImpl::From(config);
 }
 
 Sanitizer::~Sanitizer() = default;
@@ -135,7 +130,7 @@
                                 const String& local_name,
                                 const String& markup,
                                 ExceptionState& exception_state) {
-  if (baseline_drop_elements_.Contains(local_name.UpperASCII()))
+  if (baseline_drop_elements_.Contains(local_name.LowerASCII()))
     return nullptr;
   LocalDOMWindow* window = LocalDOMWindow::From(script_state);
   Element* element = window->document()->CreateElementForBinding(
@@ -216,7 +211,7 @@
         // TODO(crbug.com/1126936): Review the sanitising algorithm for
         // non-HTMLs.
         // 1. Let |name| be |element|'s tag name.
-        String name = node->nodeName().UpperASCII();
+        String name = node->nodeName().LowerASCII();
 
         // 2. Detect whether current element is a custom element or not.
         bool is_custom_element =
@@ -387,18 +382,15 @@
 }
 
 SanitizerConfig* Sanitizer::getConfiguration() const {
-  return SanitizerConfigCopy(config_dictionary_
-                                 ? config_dictionary_.Get()
-                                 : SanitizerConfigImpl::defaultConfig());
+  return SanitizerConfigImpl::ToAPI(config_);
 }
 
 SanitizerConfig* Sanitizer::getDefaultConfiguration() {
-  return SanitizerConfigCopy(SanitizerConfigImpl::defaultConfig());
+  return SanitizerConfigCopy(SanitizerConfigImpl::DefaultConfig());
 }
 
 void Sanitizer::Trace(Visitor* visitor) const {
   ScriptWrappable::Trace(visitor);
-  visitor->Trace(config_dictionary_);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
index 688dda89..4676649 100644
--- a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
+++ b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.h
@@ -74,14 +74,13 @@
   void DoSanitizing(ContainerNode*, LocalDOMWindow*, ExceptionState&);
 
   SanitizerConfigImpl config_;
-  Member<const SanitizerConfig> config_dictionary_;
 
   // TODO(lyf): make it all-oilpan.
   const Vector<String> kVectorStar = Vector<String>({"*"});
   const HashSet<String> baseline_drop_elements_ = {
-      "APPLET",   "BASE",    "EMBED",    "IFRAME", "NOEMBED",
-      "NOFRAMES", "NOLAYER", "NOSCRIPT", "OBJECT", "FRAME",
-      "FRAMESET", "PARAM",   "SCRIPT"};
+      "applet",   "base",    "embed",    "iframe", "noembed",
+      "noframes", "nolayer", "noscript", "object", "frame",
+      "frameset", "param",   "script"};
   const HashMap<String, Vector<String>> baseline_drop_attributes_ = {
       {"onabort", kVectorStar},
       {"onafterprint", kVectorStar},
diff --git a/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc b/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
index de0e422f..e7f568b 100644
--- a/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
+++ b/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.cc
@@ -261,7 +261,7 @@
 void ElementFormatter(HashSet<String>& element_set,
                       const Vector<String>& elements) {
   for (const String& s : elements) {
-    element_set.insert(s.UpperASCII());
+    element_set.insert(s.LowerASCII());
   }
 }
 
@@ -275,7 +275,7 @@
     } else {
       Vector<String> elements;
       for (const String& s : pair.second) {
-        elements.push_back(s.UpperASCII());
+        elements.push_back(s.LowerASCII());
       }
       attr_map.insert(lower_attr, elements);
     }
@@ -312,6 +312,21 @@
   return config_;
 }
 
+Vector<String> Copy(const HashSet<String>& set) {
+  Vector<String> result;
+  std::copy(std::cbegin(set), std::cend(set), std::back_inserter(result));
+  return result;
+}
+
+Vector<std::pair<String, Vector<String>>> Copy(
+    const HashMap<String, Vector<String>>& map) {
+  Vector<std::pair<String, Vector<String>>> result;
+  for (const auto& item : map) {
+    result.push_back(std::make_pair(item.key, item.value));
+  }
+  return result;
+}
+
 }  // anonymous namespace
 
 // Create a SanitizerConfigImpl from a SanitizerConfig.
@@ -331,17 +346,17 @@
       config->hasAllowCustomElements() && config->allowCustomElements();
   impl.allow_comments_ = config->hasAllowComments() && config->allowComments();
 
-  // Format dropElements to uppercase.
+  // Format dropElements to lower case.
   if (config->hasDropElements()) {
     ElementFormatter(impl.drop_elements_, config->dropElements());
   }
 
-  // Format blockElements to uppercase.
+  // Format blockElements to lower case.
   if (config->hasBlockElements()) {
     ElementFormatter(impl.block_elements_, config->blockElements());
   }
 
-  // Format allowElements to uppercase.
+  // Format allowElements to lower case.
   if (config->hasAllowElements()) {
     ElementFormatter(impl.allow_elements_, config->allowElements());
   } else {
@@ -360,10 +375,42 @@
     impl.allow_attributes_ = GetDefaultConfigImpl().allow_attributes_;
   }
 
+  impl.had_allow_elements_ = config->hasAllowElements();
+  impl.had_allow_attributes_ = config->hasAllowAttributes();
+  impl.had_allow_custom_elements_ = config->hasAllowCustomElements();
+
   return impl;
 }
 
-SanitizerConfig* SanitizerConfigImpl::defaultConfig() {
+SanitizerConfig* SanitizerConfigImpl::ToAPI(const SanitizerConfigImpl& impl) {
+  SanitizerConfig* config = SanitizerConfig::Create();
+
+  if (impl.had_allow_elements_) {
+    config->setAllowElements(Copy(impl.allow_elements_));
+  }
+
+  if (!impl.drop_elements_.IsEmpty()) {
+    config->setDropElements(Copy(impl.drop_elements_));
+  }
+
+  if (!impl.block_elements_.IsEmpty()) {
+    config->setBlockElements(Copy(impl.block_elements_));
+  }
+
+  if (impl.had_allow_attributes_) {
+    config->setAllowAttributes(Copy(impl.allow_attributes_));
+  }
+
+  if (!impl.drop_attributes_.IsEmpty()) {
+    config->setDropAttributes(Copy(impl.drop_attributes_));
+  }
+
+  if (impl.had_allow_custom_elements_)
+    config->setAllowCustomElements(impl.allow_custom_elements_);
+  return config;
+}
+
+SanitizerConfig* SanitizerConfigImpl::DefaultConfig() {
   return GetDefaultConfig();
 }
 
diff --git a/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h b/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
index 4ef86d9..274295d 100644
--- a/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
+++ b/third_party/blink/renderer/modules/sanitizer_api/sanitizer_config_impl.h
@@ -32,11 +32,22 @@
   bool allow_custom_elements_;
   bool allow_comments_;
 
+  // These members store whether the original SanitizerConfig had the
+  // corresponding members set or not. This only serves to reconstruct the
+  // SanitizerConfig* in the ToAPI method.
+  bool had_allow_elements_;
+  bool had_allow_attributes_;
+  bool had_allow_custom_elements_;
+
   // Create a SantizerConfigImpl from a SanitizerConfig.
   // Will use the default config if it received nullptr.
   static SanitizerConfigImpl From(const SanitizerConfig*);
 
-  static SanitizerConfig* defaultConfig();
+  // Create an IDL SanitizerConfig from this impl, for use in the config()
+  // accessor.
+  static SanitizerConfig* ToAPI(const SanitizerConfigImpl&);
+
+  static SanitizerConfig* DefaultConfig();
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl
similarity index 85%
rename from third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
rename to third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl
index ef7774f5..b9709c1 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_configuration.idl
@@ -4,7 +4,7 @@
 
 // https://gpuweb.github.io/gpuweb/
 
-dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
+dictionary GPUCanvasConfiguration : GPUObjectDescriptorBase {
     required GPUDevice device;
     required GPUTextureFormat format;
     GPUTextureUsageFlags usage = 16;  // GPUTextureUsage.RENDER_ATTACHMENT
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
index b90182e..481c5da 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -6,7 +6,7 @@
 
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_swap_chain_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_canvas_configuration.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpucanvascontext_imagebitmaprenderingcontext_offscreencanvasrenderingcontext2d_webgl2renderingcontext_webglrenderingcontext.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
@@ -31,7 +31,7 @@
 
 CanvasRenderingContext::ContextType GPUCanvasContext::Factory::GetContextType()
     const {
-  return CanvasRenderingContext::kContextGPUPresent;
+  return CanvasRenderingContext::kContextWebGPU;
 }
 
 GPUCanvasContext::GPUCanvasContext(
@@ -53,7 +53,7 @@
 
 // CanvasRenderingContext implementation
 CanvasRenderingContext::ContextType GPUCanvasContext::GetContextType() const {
-  return CanvasRenderingContext::kContextGPUPresent;
+  return CanvasRenderingContext::kContextWebGPU;
 }
 
 V8RenderingContext* GPUCanvasContext::AsV8RenderingContext() {
@@ -165,7 +165,7 @@
       static_cast<HTMLCanvasElement*>(Host()));
 }
 
-void GPUCanvasContext::configure(const GPUSwapChainDescriptor* descriptor,
+void GPUCanvasContext::configure(const GPUCanvasConfiguration* descriptor,
                                  ExceptionState& exception_state) {
   ConfigureInternal(descriptor, exception_state);
 }
@@ -207,7 +207,7 @@
 
 // gpu_canvas_context.idl (Deprecated)
 GPUSwapChain* GPUCanvasContext::configureSwapChain(
-    const GPUSwapChainDescriptor* descriptor,
+    const GPUCanvasConfiguration* descriptor,
     ExceptionState& exception_state) {
   descriptor->device()->AddConsoleWarning(
       "configureSwapChain() is deprecated. Use configure() instead and call "
@@ -229,7 +229,7 @@
 }
 
 void GPUCanvasContext::ConfigureInternal(
-    const GPUSwapChainDescriptor* descriptor,
+    const GPUCanvasConfiguration* descriptor,
     ExceptionState& exception_state,
     bool deprecated_resize_behavior) {
   DCHECK(descriptor);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
index fd0783d..44252c2 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -15,8 +15,8 @@
 namespace blink {
 
 class GPUAdapter;
+class GPUCanvasConfiguration;
 class GPUSwapChain;
-class GPUSwapChainDescriptor;
 class GPUTexture;
 class V8UnionHTMLCanvasElementOrOffscreenCanvas;
 
@@ -79,13 +79,13 @@
   // gpu_presentation_context.idl
   V8UnionHTMLCanvasElementOrOffscreenCanvas* getHTMLOrOffscreenCanvas() const;
 
-  void configure(const GPUSwapChainDescriptor* descriptor, ExceptionState&);
+  void configure(const GPUCanvasConfiguration* descriptor, ExceptionState&);
   void unconfigure();
   String getPreferredFormat(const GPUAdapter* adapter);
   GPUTexture* getCurrentTexture(ExceptionState&);
 
   // gpu_canvas_context.idl (Deprecated)
-  GPUSwapChain* configureSwapChain(const GPUSwapChainDescriptor* descriptor,
+  GPUSwapChain* configureSwapChain(const GPUCanvasConfiguration* descriptor,
                                    ExceptionState&);
   String getSwapChainPreferredFormat(ExecutionContext* execution_context,
                                      GPUAdapter* adapter);
@@ -93,7 +93,7 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(GPUCanvasContext);
 
-  void ConfigureInternal(const GPUSwapChainDescriptor* descriptor,
+  void ConfigureInternal(const GPUCanvasConfiguration* descriptor,
                          ExceptionState&,
                          bool deprecated_resize_behavior = false);
 
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
index 02bc214..ec55b1c 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
@@ -11,11 +11,11 @@
     [ImplementedAs=getHTMLOrOffscreenCanvas] readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;
 
     GPUTextureFormat getPreferredFormat(GPUAdapter adapter);
-    [RaisesException] void configure(GPUSwapChainDescriptor descriptor);
+    [RaisesException] void configure(GPUCanvasConfiguration descriptor);
     void unconfigure();
     [RaisesException] GPUTexture getCurrentTexture();
 
     // Deprecated
-    [RaisesException] GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor);
+    [RaisesException] GPUSwapChain configureSwapChain(GPUCanvasConfiguration descriptor);
     [CallWith=ExecutionContext] GPUTextureFormat getSwapChainPreferredFormat(GPUAdapter adapter);
 };
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
index d3c97e5..5f8f488 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_params.cc
@@ -50,8 +50,7 @@
 }
 
 SkSurfaceProps CanvasResourceParams::GetSkSurfaceProps() const {
-  bool can_use_lcd_text = (alpha_type_ == kOpaque_SkAlphaType);
-  return skia::LegacyDisplayGlobals::ComputeSurfaceProps(can_use_lcd_text);
+  return skia::LegacyDisplayGlobals::ComputeSurfaceProps(CanUseLcdText());
 }
 
 uint8_t CanvasResourceParams::BytesPerPixel() const {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_params.h b/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
index 53b39b29..42550e5 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_params.h
@@ -53,6 +53,10 @@
   sk_sp<SkColorSpace> GetSkColorSpace() const;
   SkAlphaType GetSkAlphaType() const { return alpha_type_; }
   SkSurfaceProps GetSkSurfaceProps() const;
+  bool CanUseLcdText() const {
+    // LCD text is safe when canvas is guaranteed not to be semi-transparent.
+    return alpha_type_ == kOpaque_SkAlphaType;
+  }
 
   // Gpu memory buffer parameters
   gfx::BufferFormat GetBufferFormat() const;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 265df0d..542840f 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -1421,7 +1421,7 @@
 
   ri->BeginRasterCHROMIUM(
       background_color, needs_clear, /*msaa_sample_count=*/0,
-      /*can_use_lcd_text=*/false, ColorParams().GetStorageGfxColorSpace(),
+      ColorParams().CanUseLcdText(), ColorParams().GetStorageGfxColorSpace(),
       mailbox.name);
 
   ri->RasterCHROMIUM(list.get(), GetOrCreateCanvasImageProvider(), size,
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index 2108a4fb..d499b0e 100644
--- a/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -271,22 +271,6 @@
   return flags_string.ToString();
 }
 
-String FilterQualityName(SkFilterQuality filter_quality) {
-  switch (filter_quality) {
-    case kNone_SkFilterQuality:
-      return "None";
-    case kLow_SkFilterQuality:
-      return "Low";
-    case kMedium_SkFilterQuality:
-      return "Medium";
-    case kHigh_SkFilterQuality:
-      return "High";
-    default:
-      NOTREACHED();
-      return "?";
-  };
-}
-
 String StrokeCapName(SkPaint::Cap cap) {
   switch (cap) {
     case SkPaint::kButt_Cap:
@@ -335,8 +319,6 @@
   paint_item->SetDouble("strokeWidth", paint.getStrokeWidth());
   paint_item->SetDouble("strokeMiter", paint.getStrokeMiter());
   paint_item->SetString("flags", StringForSkPaintFlags(paint));
-  paint_item->SetString("filterLevel",
-                        FilterQualityName(paint.getFilterQuality()));
   paint_item->SetString("strokeCap", StrokeCapName(paint.getStrokeCap()));
   paint_item->SetString("strokeJoin", StrokeJoinName(paint.getStrokeJoin()));
   paint_item->SetString("styleName", StyleName(paint.getStyle()));
@@ -361,6 +343,41 @@
   };
 }
 
+String FilterModeName(SkFilterMode fm) {
+  switch (fm) {
+    case SkFilterMode::kNearest:
+      return "kNearest";
+    case SkFilterMode::kLinear:
+      return "kLinear";
+  }
+  return "not reachable";
+}
+
+String MipmapModeName(SkMipmapMode mm) {
+  switch (mm) {
+    case SkMipmapMode::kNone:
+      return "kNone";
+    case SkMipmapMode::kNearest:
+      return "kNearest";
+    case SkMipmapMode::kLinear:
+      return "kLinear";
+  }
+  return "not reachable";
+}
+
+std::unique_ptr<JSONObject> ObjectForSkSamplingOptions(
+    const SkSamplingOptions& sampling) {
+  auto sampling_item = std::make_unique<JSONObject>();
+  if (sampling.useCubic) {
+    sampling_item->SetDouble("B", sampling.cubic.B);
+    sampling_item->SetDouble("C", sampling.cubic.C);
+  } else {
+    sampling_item->SetString("filter", FilterModeName(sampling.filter));
+    sampling_item->SetString("mipmap", MipmapModeName(sampling.mipmap));
+  }
+  return sampling_item;
+}
+
 }  // namespace
 
 class AutoLogger
@@ -458,6 +475,7 @@
   JSONObject* params = logger.LogItemWithParams("drawImage");
   params->SetDouble("left", left);
   params->SetDouble("top", top);
+  params->SetObject("sampling", ObjectForSkSamplingOptions(sampling));
   params->SetObject("image", ObjectForSkImage(image));
   if (paint)
     params->SetObject("paint", ObjectForSkPaint(*paint));
@@ -475,6 +493,7 @@
   params->SetObject("image", ObjectForSkImage(image));
   params->SetObject("src", ObjectForSkRect(src));
   params->SetObject("dst", ObjectForSkRect(dst));
+  params->SetObject("sampling", ObjectForSkSamplingOptions(sampling));
   if (paint)
     params->SetObject("paint", ObjectForSkPaint(*paint));
   SkCanvas::onDrawImageRect2(image, src, dst, sampling, paint, constraint);
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index 73b71bc0..96410ab 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -278,8 +278,12 @@
     // --enable-prefer-compositing-to-lcd-text) for details.
     // Ignore it for SPv1 for now.
     success = true;
-    rect_to_map.ClearIsTight();
+  } else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+    // TODO(crbug.com/803649): We still have clip hierarchy issues with fragment
+    // clips. See crbug.com/1228364 for the tests.
+    success = true;
   }
+  rect_to_map.ClearIsTight();
   return !rect_to_map.Rect().IsEmpty();
 }
 
@@ -432,6 +436,10 @@
       // with --enable-prefer-compositing-to-lcd-text) for details.
       // Ignore it for SPv1 for now.
       success = true;
+    } else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+      // TODO(crbug.com/803649): We still have clip hierarchy issues with
+      // fragment clips. See crbug.com/1228364 for the tests.
+      success = true;
     }
     return InfiniteLooseFloatClipRect();
   }
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index 33ddcd3..5162347 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -781,21 +781,18 @@
   LocalToAncestorVisualRectInternal(transform1_state, transform2_and_clip_state,
                                     result, success);
   // Fails, because the clip of the destination state is not an ancestor of the
-  // clip of the source state. A known bug in SPv1 would make such query,
-  // in such case, no clips are applied.
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
-    EXPECT_FALSE(success);
-  } else {
-    EXPECT_TRUE(success);
-    FloatClipRect expected(FloatRect(-100, 0, 100, 100));
-    expected.ClearIsTight();
-    EXPECT_CLIP_RECT_EQ(expected, result);
-  }
+  // clip of the source state. Known bugs in pre-CompositeAfterPaint or
+  // CompositeAfterPaint without LayoutNGBlockFragmentation would make such
+  // query. In such cases, no clips are applied.
+  EXPECT_TRUE(success);
+  FloatClipRect expected(FloatRect(-100, 0, 100, 100));
+  expected.ClearIsTight();
+  EXPECT_CLIP_RECT_EQ(expected, result);
 
   result = FloatClipRect(input_rect);
   GeometryMapper::LocalToAncestorVisualRect(transform2_and_clip_state,
                                             transform1_state, result);
-  FloatClipRect expected(FloatRect(20, -40, 40, 30));
+  expected = FloatClipRect(FloatRect(20, -40, 40, 30));
   // This is because the combined Rotate(45) and Rotate(-45) is not exactly a
   // translation-only transform due to calculation errors.
   expected.ClearIsTight();
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index d67543c..7c63069 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -1328,14 +1328,6 @@
     },
     {
         'paths': [
-            'third_party/blink/renderer/core/css/counter_style.cc',
-            'third_party/blink/renderer/core/layout/',
-            'third_party/blink/renderer/core/paint/',
-        ],
-        'allowed': ['list_marker_text::.+'],
-    },
-    {
-        'paths': [
             'third_party/blink/renderer/modules/crypto/',
         ],
         'allowed': ['crypto::.+'],
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
index fcf8065..8a08fbe1 100644
--- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint
+++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -55,22 +55,3 @@
 crbug.com/1191032 http/tests/devtools/tracing/frame-model-instrumentation.js [ Failure ]
 crbug.com/1191032 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Timeout ]
 crbug.com/1191032 virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Timeout ]
-
-# Tests pass with LayoutNGBlockFragmentation enabled and fail without. Tests
-# crash with CompositeAfterPaint enabled and LayoutNGBlockFragmentation
-# disabled.
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-029.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-036.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-038.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-039.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-040.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-041.html [ Pass ]
-virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-044.html [ Pass ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-029.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-036.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-038.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-039.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-040.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-041.html [ Crash Failure ]
-crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-044.html [ Crash Failure ]
-
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c391d36d..9b3ac612 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1078,6 +1078,12 @@
 virtual/layout_ng_block_frag/external/wpt/css/css-break/transform-006.html [ Pass ]
 virtual/layout_ng_block_frag/external/wpt/css/css-break/transform-008.html [ Pass ]
 virtual/layout_ng_block_frag/external/wpt/css/css-contain/contain-size-monolithic-002.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vlr-ltr-rtl-in-multicol.tentative.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vlr-rtl-ltr-in-multicol.tentative.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vlr-rtl-rtl-in-multicol.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vrl-ltr-rtl-in-multicol.tentative.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vrl-rtl-ltr-in-multicol.tentative.html [ Pass ]
+virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/vrl-rtl-rtl-in-multicol.html [ Pass ]
 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/abspos-containing-block-outside-spanner.html [ Pass ]
 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/balance-break-avoidance-001.html [ Pass ]
 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/balance-orphans-widows-000.html [ Pass ]
@@ -3788,6 +3794,12 @@
 crbug.com/829028 external/wpt/css/css-break/transform-008.html [ Failure ]
 crbug.com/1224888 external/wpt/css/css-break/transform-009.html [ Failure ]
 crbug.com/1156312 external/wpt/css/css-break/widows-orphans-017.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vlr-ltr-rtl-in-multicol.tentative.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vlr-rtl-ltr-in-multicol.tentative.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vlr-rtl-rtl-in-multicol.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vrl-ltr-rtl-in-multicol.tentative.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vrl-rtl-ltr-in-multicol.tentative.html [ Failure ]
+crbug.com/829028 external/wpt/css/css-position/static-position/multicol/vrl-rtl-rtl-in-multicol.html [ Failure ]
 crbug.com/829028 external/wpt/css/css-multicol/abspos-containing-block-outside-spanner.html [ Failure ]
 crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-001.html [ Failure ]
 crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-002.html [ Failure ]
@@ -7328,3 +7340,6 @@
 crbug.com/1229039 [ Mac ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass Timeout ]
 crbug.com/1225643 [ Linux ] external/wpt/webrtc/simulcast/basic.https.html [ Pass Timeout ]
 crbug.com/1225643 [ Mac ] external/wpt/webrtc/simulcast/basic.https.html [ Pass Timeout ]
+
+# Test fails due to more accurate size reporting in heap snapshots.
+crbug.com/1229212 inspector-protocol/heap-profiler/heap-samples-in-snapshot.js [ Failure ]
\ No newline at end of file
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 1e8ecb5..d7be916 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -28,6 +28,7 @@
               "external/wpt/css/css-animations",
               "external/wpt/css/css-scroll-snap",
               "external/wpt/css/css-transforms/animation",
+              "external/wpt/css/css-transforms/individual-transform/animation",
               "external/wpt/feature-policy/experimental-features",
               "external/wpt/permissions-policy/experimental-features",
               "external/wpt/html/canvas/offscreen/manual/convert-to-blob",
@@ -341,6 +342,7 @@
     "prefix": "layout_ng_block_frag",
     "bases": ["external/wpt/css/css-break",
               "external/wpt/css/css-contain",
+              "external/wpt/css/css-position/static-position/multicol",
               "external/wpt/css/css-multicol",
               "external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements",
               "fast/forms/fieldset",
@@ -1145,11 +1147,6 @@
     "args": ["--stable-release-mode"]
   },
   {
-    "prefix": "playback_speed_button",
-    "bases": ["http/tests/media/controls", "media/controls"],
-    "args": [ "--enable-features=PlaybackSpeedButton" ]
-  },
-  {
     "prefix": "dialogfocus-old-behavior",
     "bases": [
       "external/wpt/html/semantics/interactive-elements/the-dialog-element"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part-ref.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part-ref.html
new file mode 100644
index 0000000..7f1af75
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+
+<ol>
+  <div>A.</div>
+  <div>B.</div>
+  <div>C.</div>
+</ol>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part.html b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part.html
new file mode 100644
index 0000000..2be169c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-counter-styles/counter-styles-shadow-dom-part.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Counter style tree-scoped references</title>
+<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#the-counter-style-rule">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#shadow-names">
+<link rel="author" href="mailto:xiaochengh@chromium.org">
+<link rel="match" href="counter-styles-shadow-dom-part-ref.html">
+<meta name="assert" content="The list in the shadow tree should use the counter style defined in the outer document, because it's styled by the outer document">
+
+<style>
+@counter-style foo {
+  system: fixed;
+  symbols: A B C;
+}
+#host::part(list) {
+  list-style-type: foo;
+}
+</style>
+
+<div id="host"></div>
+
+<script>
+document.getElementById("host").attachShadow({mode: 'open'}).innerHTML = `
+<style>
+@counter-style foo {
+  system: fixed;
+  symbols: D E F;
+}
+</style>
+<ol part="list" style="list-style-position: inside">
+  <li></li>
+  <li></li>
+  <li></li>
+</ol>
+`;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-in-multicol-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-in-multicol-ref.html
new file mode 100644
index 0000000..908f43a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-in-multicol-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<style>
+  body { writing-mode: vertical-lr; }
+  .container {
+    background: green;
+    inline-size: 80px;
+    block-size: 600px;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-ltr-in-multicol.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-ltr-in-multicol.html
new file mode 100644
index 0000000..5b597a63
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-ltr-in-multicol.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vlr-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-lr; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container ltr">
+    X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-rtl-in-multicol.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-rtl-in-multicol.tentative.html
new file mode 100644
index 0000000..bef4c85
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-ltr-rtl-in-multicol.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vlr-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-lr; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container ltr">
+    X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-ltr-in-multicol.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-ltr-in-multicol.tentative.html
new file mode 100644
index 0000000..ef2e5b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-ltr-in-multicol.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vlr-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-lr; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container rtl">
+    X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="ltr cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="ltr cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-rtl-in-multicol.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-rtl-in-multicol.html
new file mode 100644
index 0000000..1bfcf21
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vlr-rtl-rtl-in-multicol.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vlr-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-lr; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-in-multicol-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-in-multicol-ref.html
new file mode 100644
index 0000000..0e22219
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-in-multicol-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<style>
+  body { writing-mode: vertical-rl; }
+  .container {
+    background: green;
+    inline-size: 80px;
+    block-size: 600px;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-ltr-in-multicol.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-ltr-in-multicol.html
new file mode 100644
index 0000000..1d6c584
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-ltr-in-multicol.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vrl-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-rl; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container ltr">
+    X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="ltr cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="ltr">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="ltr">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-rtl-in-multicol.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-rtl-in-multicol.tentative.html
new file mode 100644
index 0000000..900a649
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-ltr-rtl-in-multicol.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vrl-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-rl; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container ltr">
+    X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    X<span class="rtl cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container ltr">
+    <span class="cb">X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-ltr-in-multicol.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-ltr-in-multicol.tentative.html
new file mode 100644
index 0000000..41951437
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-ltr-in-multicol.tentative.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vrl-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-rl; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-rtl-in-multicol.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-rtl-in-multicol.html
new file mode 100644
index 0000000..bb59d4f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/multicol/vrl-rtl-rtl-in-multicol.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" />
+<link rel="match" href="vrl-in-multicol-ref.html">
+<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." />
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<style>
+  body { writing-mode: vertical-rl; }
+  .container {
+    position: relative;
+    background: green;
+    font: 16px/1 Ahem;
+    inline-size: 80px;
+    block-size: 100px;
+    color: green;
+  }
+  .multicol {
+    column-count: 2;
+    column-fill: auto;
+    column-gap: 0;
+    block-size: 100px;
+    inline-size: 160px;
+  }
+  .red { color: red; }
+  .cb { position: relative; }
+  .rtl { direction: rtl; }
+  .ltr { direction: ltr; }
+  .inline { display: inline; }
+  .abs { position: absolute; }
+  .zero-inline { inset-inline-start: 0;}
+  .zero-block { inset-block-start: 0;}
+</style>
+
+There should be no red.
+<div class="multicol">
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs inline">XX</div><span class="red">XX</span></span>
+  </div>
+  <div class="container rtl">
+    X<span class="rtl cb">X<div class="abs block">XX</div><br><span class="red">XX</span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs inline">XX</div><span class="red">XX</span></span></span>
+  </div>
+
+  <div class="container rtl">
+    <span class="cb">X<span class="rtl">X<div class="abs block">XX</div><br><span class="red">XX</span></span></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering-ref.html
new file mode 100644
index 0000000..94e7e43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Individual transform: combine individual transform properties</title>
+    <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#individual-transforms">
+    <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#ctm">
+    <meta name="assert" content="Tests that we combine transforms in the correct order."/>
+    <style>
+      @keyframes anim {
+        to {
+          transform: translate(50px, 50px) rotate(45deg) scale(2, 1);
+        }
+      }
+      .block {
+        display:  inline-block;
+        width: 50px;
+        height: 50px;
+        margin:  50px;
+        padding:  0;
+        transform-origin: 0 0;
+        background:  lime;
+        /* Freeze the animation at the midpoint. */
+        animation-timing-function: cubic-bezier(0, 1, 1, 0);
+        animation-duration:  1000000s;
+        animation-delay:  -500000s;
+        animation-name:  anim;
+      }
+    </style>
+  </head>
+  <body>
+    <div>
+      <div class="block"></div>
+      <div class="block"></div>
+    </div>
+    <div>
+      <div class="block"></div>
+      <div class="block"></div>
+    </div>
+    <div>
+      <div class="block"></div>
+      <div class="block"></div>
+    </div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering.html
new file mode 100644
index 0000000..9d127f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/individual-transform/animation/individual-transform-ordering.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Individual transform: combine individual transform properties</title>
+    <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#individual-transforms">
+    <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#ctm">
+    <meta name="assert" content="Tests that we combine transforms in the correct order when animating."/>
+    <link rel="match" href="individual-transform-ordering-ref.html">
+    <style>
+      .block {
+        display:  inline-block;
+        width: 50px;
+        height: 50px;
+        margin:  50px;
+        padding:  0;
+        transform-origin: 0 0;
+        background:  lime;
+        /* Freeze the animation at the midpoint. */
+        animation-timing-function: cubic-bezier(0, 1, 1, 0);
+        animation-duration:  1000000s;
+        animation-delay:  -500000s;
+      }
+      @keyframes anim-1 {
+        to {
+          translate: 50px 50px;
+          rotate: 45deg;
+          scale: 2 1;
+        }
+      }
+      #div-1 {
+        animation-name: anim-1;
+      }
+      @keyframes anim-2 {
+        to {
+          rotate: 45deg;
+          scale: 2 1;
+          translate: 50px 50px;
+        }
+      }
+      #div-2 {
+        animation-name:  anim-2;
+      }
+      @keyframes anim-3 {
+        to {
+          transform: scale(2, 1);
+          translate: 50px 50px;
+          rotate: 45deg;
+        }
+      }
+      #div-3 {
+        animation-name:  anim-3;
+      }
+      @keyframes anim-4 {
+        to {
+          transform: rotate(45deg) scale(2, 1);
+          translate: 50px 50px;
+        }
+      }
+      #div-4 {
+        animation-name: anim-4;
+      }
+      @Keyframes anim-5 {
+        to { transform: rotate(45deg); }
+      }
+      @Keyframes anim-6 {
+        from { transform:  none; }
+        to { transform: translate(50px, 50px) rotate(45deg) scale(2, 1); }
+      }
+      /* anim-6 replaces anim-5 since both updating the transform property. */
+      #div-5 {
+        animation-name: anim-5, anim-6;
+      }
+      @keyframes anim-7 {
+        to {
+          rotate: 45deg;
+          scale:  2 2;
+        }
+      }
+      @keyframes anim-8 {
+        from {
+          translate: 0px 0px;
+          scale: 1 1;
+        }
+        to {
+          translate: 50px 50px;
+          scale: 2 1;
+        }
+      }
+      /*
+       * The scale property is overridden in anim-8, but the rotate property
+       * from anim-7 is still relevant and must be applied in the correct order
+       * (after translate but before scale).
+       */
+      #div-6 {
+        animation-name: anim-7, anim-8;
+      }
+    </style>
+  </head>
+  <body>
+    <div>
+      <div id="div-1" class="block"></div>
+      <div id="div-2" class="block"></div>
+    </div>
+    <div>
+      <div id="div-3" class="block"></div>
+      <div id="div-4" class="block"></div>
+    </div>
+    <div>
+      <div id="div-5" class="block"></div>
+      <div id="div-6" class="block"></div>
+    </div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log-expected.txt b/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log-expected.txt
index 4df594b..19078b0 100644
--- a/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/layers/layer-canvas-log-expected.txt
@@ -9,7 +9,6 @@
             paint : {
                 blendMode : "Src"
                 color : "#00000000"
-                filterLevel : "None"
                 flags : "none"
                 strokeCap : "Butt"
                 strokeJoin : "Miter"
@@ -25,7 +24,6 @@
         params : {
             paint : {
                 color : "#FF0000FF"
-                filterLevel : "Low"
                 flags : "AntiAlias"
                 strokeCap : "Butt"
                 strokeJoin : "Miter"
@@ -47,7 +45,6 @@
         params : {
             paint : {
                 color : "#FFFF0000"
-                filterLevel : "Low"
                 flags : "AntiAlias"
                 strokeCap : "Butt"
                 strokeJoin : "Miter"
@@ -80,7 +77,6 @@
             }
             paint : {
                 color : "#FF000000"
-                filterLevel : "Low"
                 flags : "AntiAlias"
                 strokeCap : "Butt"
                 strokeJoin : "Miter"
@@ -88,6 +84,10 @@
                 strokeWidth : 0
                 styleName : "Fill"
             }
+            sampling : {
+                filter : "kLinear"
+                mipmap : "kLinear"
+            }
             src : {
                 bottom : 21
                 left : 0
@@ -129,7 +129,6 @@
         params : {
             paint : {
                 color : "#7F000000"
-                filterLevel : "None"
                 flags : "AntiAlias"
                 strokeCap : "Butt"
                 strokeJoin : "Miter"
diff --git a/third_party/blink/web_tests/http/tests/media/controls/controls-list-add-hide-expected.txt b/third_party/blink/web_tests/http/tests/media/controls/controls-list-add-hide-expected.txt
deleted file mode 100644
index 410f636..0000000
--- a/third_party/blink/web_tests/http/tests/media/controls/controls-list-add-hide-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test disabling controls on the video element with all controls. Failed to find overflow item: -internal-media-controls-playback-speed-button
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/media/controls/controls-list-remove-show-expected.txt b/third_party/blink/web_tests/http/tests/media/controls/controls-list-remove-show-expected.txt
deleted file mode 100644
index 84beebb..0000000
--- a/third_party/blink/web_tests/http/tests/media/controls/controls-list-remove-show-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test enabling controls on the video element with them enabled. Failed to find overflow item: -internal-media-controls-playback-speed-button
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt b/third_party/blink/web_tests/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt
deleted file mode 100644
index d5037bf0..0000000
--- a/third_party/blink/web_tests/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL The overflow playback speed button is not visible when infinite duration. Failed to find overflow item: -internal-media-controls-playback-speed-button
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt b/third_party/blink/web_tests/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt
deleted file mode 100644
index a65e9b5..0000000
--- a/third_party/blink/web_tests/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Overflow menu children appear in correct order. assert_equals: expected 8 but got 7
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/window-placement-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/window-placement-origin-trial-interfaces.html
index a50f368..c78361e 100644
--- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/window-placement-origin-trial-interfaces.html
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/window-placement-origin-trial-interfaces.html
@@ -15,12 +15,14 @@
 test(t => {
   OriginTrialsHelper.check_properties_exist(this, {
      'global': ['getScreens'],
+     'Screen': ['isExtended', 'onchange'],
   });
 }, 'Window Placement API interfaces and properties in Origin-Trial enabled document.');
 
 test(t => {
-  assert_true('getScreens' in window, 'getScreens function exists on window scope');
-  assert_not_equals(window.getScreens, undefined, 'getScreens function can be accessed on window');
+  assert_not_equals(window.getScreens, undefined);
+  assert_not_equals(window.screen.isExtended, undefined);
+  assert_not_equals(window.screen.onchange, undefined);
 }, 'Window Placement API entry point in Origin-Trial enabled document.');
 
 </script>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/accessibility-playback-speed-button.html b/third_party/blink/web_tests/media/controls/accessibility-playback-speed-button.html
similarity index 88%
rename from third_party/blink/web_tests/virtual/playback_speed_button/media/controls/accessibility-playback-speed-button.html
rename to third_party/blink/web_tests/media/controls/accessibility-playback-speed-button.html
index d22e968b..c11368f 100644
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/accessibility-playback-speed-button.html
+++ b/third_party/blink/web_tests/media/controls/accessibility-playback-speed-button.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Media Controls: playback speed button accessibility tests</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
 <video controls></video>
 <script>
 async_test(t => {
   var video = document.querySelector('video');
   enableTestMode(video);
-  video.src = '../../../../media/content/test.ogv';
+  video.src = '../content/test.ogv';
 
 video.onloadeddata = t.step_func(_ => {
     assert_true(isPlaybackSpeedButtonEnabled(video));
diff --git a/third_party/blink/web_tests/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html b/third_party/blink/web_tests/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html
index 9e4f1d31..a85a508 100644
--- a/third_party/blink/web_tests/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html
+++ b/third_party/blink/web_tests/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html
@@ -12,6 +12,7 @@
   const overflowBtn = overflowButton(video);
   const downloadBtn = downloadsOverflowItem(video);
   const captionsBtn = captionsOverflowItem(video);
+  const playbackSpeedBtn = playbackSpeedOverflowItem(video);
 
   // Add text tracks so that the captions option appears.
   [ '../track/captions-webvtt/captions-fast.vtt',
@@ -32,14 +33,17 @@
   // Neither the downloads button nor the captions button should receive a click during the click and drag.
   downloadBtn.addEventListener('click', t.unreached_func('Downloads received a click'));
   captionsBtn.addEventListener('click', t.unreached_func('Captions received a click'));
+  playbackSpeedBtn.addEventListener('click', t.unreached_func('Playback speed received a click'));
 
   function clickAndDrag() {
     assert_true(isControlVisible(menu), 'Overflow menu should be visible before we start click-and-drag');
     assert_true(isControlVisible(downloadBtn), 'Download button should be visible');
     assert_true(isControlVisible(captionsBtn), 'Captions button should be visible');
+    assert_true(isControlVisible(playbackSpeedBtn), 'Playback speed button should be visible');
 
     const downloadPosition = elementCoordinates(downloadBtn);
     const captionsPosition = elementCoordinates(captionsBtn);
+    const playbackSpeedPosition = elementCoordinates(playbackSpeedBtn);
 
     // Click down on downloads but drag and release over captions and playback speed.
     chrome.gpuBenchmarking.pointerActionSequence([{
@@ -48,6 +52,8 @@
         { name: 'pointerDown', x: downloadPosition[0], y: downloadPosition[1] },
         { name: 'pointerMove', x: captionsPosition[0], y: captionsPosition[1] },
         { name: 'pointerUp', x: captionsPosition[0], y: captionsPosition[1] },
+        { name: 'pointerMove', x: playbackSpeedPosition[0], y: playbackSpeedPosition[1] },
+        { name: 'pointerUp', x: playbackSpeedPosition[0], y: playbackSpeedPosition[1] },
       ]
     }], t.step_func_done(() => {
       assert_true(isControlVisible(menu), 'Overflow menu should still be visible after click-and-drag');
diff --git a/third_party/blink/web_tests/media/controls/overflow-button-disabled-no-source.html b/third_party/blink/web_tests/media/controls/overflow-button-disabled-no-source.html
index 1755c0d0..baa1332 100644
--- a/third_party/blink/web_tests/media/controls/overflow-button-disabled-no-source.html
+++ b/third_party/blink/web_tests/media/controls/overflow-button-disabled-no-source.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
-<title>Test that the overflow menu is shown but disabled with no source.</title>
+<title>Test that the overflow menu is disabled with no source.</title>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <script src="../media-controls.js"></script>
-<video controls width=400 controlsList=nodownload disablePictureInPicture></video>
+<video controls width=400 controlsList="noplaybackrate nodownload" disablePictureInPicture></video>
 <script>
 async_test(t => {
   const video = document.querySelector('video');
diff --git a/third_party/blink/web_tests/media/controls/overflow-menu-hide-on-click-item.html b/third_party/blink/web_tests/media/controls/overflow-menu-hide-on-click-item.html
index 504e069f..c30dc6c 100644
--- a/third_party/blink/web_tests/media/controls/overflow-menu-hide-on-click-item.html
+++ b/third_party/blink/web_tests/media/controls/overflow-menu-hide-on-click-item.html
@@ -38,8 +38,16 @@
         singleTapOnControl(overflowButton(video), t.step_func(() => {
           assert_not_equals(getComputedStyle(menu).display, 'none');
 
-          singleTapOnControl(captionsOverflowItem(video), t.step_func_done(() => {
+          singleTapOnControl(captionsOverflowItem(video), t.step_func(() => {
             assert_equals(getComputedStyle(menu).display, 'none');
+
+            singleTapOnControl(overflowButton(video), t.step_func(() => {
+              assert_not_equals(getComputedStyle(menu).display, 'none');
+
+              singleTapOnControl(playbackSpeedOverflowItem(video), t.step_func_done(() => {
+                assert_equals(getComputedStyle(menu).display, 'none');
+              }));
+            }));
           }));
         }));
       }));
diff --git a/third_party/blink/web_tests/media/controls/overflow-menu-keyboard-navigation.html b/third_party/blink/web_tests/media/controls/overflow-menu-keyboard-navigation.html
index 500040a..e45a731 100644
--- a/third_party/blink/web_tests/media/controls/overflow-menu-keyboard-navigation.html
+++ b/third_party/blink/web_tests/media/controls/overflow-menu-keyboard-navigation.html
@@ -75,10 +75,11 @@
                     menu.lastElementChild);
 
       const elements = [ menu.lastElementChild,
-                         menu.lastElementChild.previousSibling ];
+                         menu.lastElementChild.previousSibling,
+                         menu.lastElementChild.previousSibling.previousSibling ];
 
       if (document.pictureInPictureEnabled)
-        elements.push(menu.lastElementChild.previousSibling.previousSibling);
+        elements.push(menu.lastElementChild.previousSibling.previousSibling.previousSibling);
 
       testNavigation(internals.shadowRoot(video), elements,
                      () => { eventSender.keyDown('ArrowUp'); },
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button-mediastream.html b/third_party/blink/web_tests/media/controls/playback-speed-button-mediastream.html
similarity index 79%
rename from third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button-mediastream.html
rename to third_party/blink/web_tests/media/controls/playback-speed-button-mediastream.html
index 7be8ac3c..553f7cd 100644
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button-mediastream.html
+++ b/third_party/blink/web_tests/media/controls/playback-speed-button-mediastream.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <title>The overflow playback speed button is not visible for mediastream.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
 
 <!--Padding ensures the overflow menu is visible for the tests. -->
 <body style="padding-top: 200px; padding-left: 100px">
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button.html b/third_party/blink/web_tests/media/controls/playback-speed-button.html
similarity index 81%
rename from third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button.html
rename to third_party/blink/web_tests/media/controls/playback-speed-button.html
index 642d9b6..b9f9fd2 100644
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-button.html
+++ b/third_party/blink/web_tests/media/controls/playback-speed-button.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <title>Clicking on the overflow playback speed button shows the playback speed menu.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<script src="../../../../media/overflow-menu.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../overflow-menu.js"></script>
 
 <!--Padding ensures the overflow menu is visible for the tests. -->
 <body style="padding-top: 200px; padding-left: 100px">
@@ -12,7 +12,7 @@
 async_test(function(t) {
   // Set up video.
   var video = document.querySelector("video");
-  video.src = '../../../../media/content/test.ogv';
+  video.src = '../content/test.ogv';
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
 
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-list-hide-on-click-outside.html b/third_party/blink/web_tests/media/controls/playback-speed-list-hide-on-click-outside.html
similarity index 83%
rename from third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-list-hide-on-click-outside.html
rename to third_party/blink/web_tests/media/controls/playback-speed-list-hide-on-click-outside.html
index 670c5b0a..4de80d2b 100644
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-list-hide-on-click-outside.html
+++ b/third_party/blink/web_tests/media/controls/playback-speed-list-hide-on-click-outside.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <title>Clicking on the overflow playback speed button shows the playback speeds list menu.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<script src="../../../../media/overflow-menu.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<script src="../overflow-menu.js"></script>
 
 <!--Padding ensures the overflow menu is visible for the tests. -->
 <body style="padding-top: 200px; padding-left: 100px">
@@ -12,7 +12,7 @@
 async_test(function(t) {
   // Set up video
   var video = document.querySelector("video");
-  video.src = '../../../../media/content/test.ogv';
+  video.src = '../content/test.ogv';
   video.setAttribute("width", "60");
   video.setAttribute("height", "100");
 
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-menu.html b/third_party/blink/web_tests/media/controls/playback-speed-menu.html
similarity index 90%
rename from third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-menu.html
rename to third_party/blink/web_tests/media/controls/playback-speed-menu.html
index 775d2c7..f99d7a9d 100644
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/playback-speed-menu.html
+++ b/third_party/blink/web_tests/media/controls/playback-speed-menu.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <title>Test that we can display a playback speeds list menu and set playback rate from the list.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
 <!-- Width should be large enough to display playback speed button. -->
 <video controls style="width: 500px"></video>
 <script>
 async_test(function(t) {
   var video = document.querySelector("video");
-  video.src = '../../../../media/content/test.ogv';
+  video.src = '../content/test.ogv';
 
   enableTestMode(video);
 
diff --git a/third_party/blink/web_tests/media/controls/video-controls-overflow-menu-text-expected.txt b/third_party/blink/web_tests/media/controls/video-controls-overflow-menu-text-expected.txt
deleted file mode 100644
index 4d4f469..0000000
--- a/third_party/blink/web_tests/media/controls/video-controls-overflow-menu-text-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Overflow menu displays the correct text. assert_equals: expected "playback speed" but got "picture in picture"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/media/video-controls-overflow-menu-fullscreen-button.html b/third_party/blink/web_tests/media/video-controls-overflow-menu-fullscreen-button.html
index 47e3be2c..a346c241 100644
--- a/third_party/blink/web_tests/media/video-controls-overflow-menu-fullscreen-button.html
+++ b/third_party/blink/web_tests/media/video-controls-overflow-menu-fullscreen-button.html
@@ -8,7 +8,7 @@
 
 <!--Padding ensures the overflow menu is visible for the tests. -->
 <body style="padding-top: 200px; padding-left: 100px">
-<video controls disablePictureInPicture></video>
+<video controls controlsList="noplaybackrate" disablePictureInPicture></video>
 <script>
 async_test(function(t) {
   // Set up video
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 4d38cbc..92c6523 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/linux/media/audio-controls-rendering-expected.png
index 9de967c2..a11bb1a 100644
--- a/third_party/blink/web_tests/platform/linux/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/linux/media/audio-repaint-expected.png
index 03f1da5..445c640 100644
--- a/third_party/blink/web_tests/platform/linux/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/linux/media/controls-layout-direction-expected.png
index e5e8d6d..62a11ed 100644
--- a/third_party/blink/web_tests/platform/linux/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/linux/media/media-controls-clone-expected.png
index 9c530f5..4ec84cb7 100644
--- a/third_party/blink/web_tests/platform/linux/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/linux/media/media-controls-grey-scrubber-expected.png
index 9572b808..d2f8471 100644
--- a/third_party/blink/web_tests/platform/linux/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/linux/media/media-document-audio-repaint-expected.png
index fd66e00f..70b8bec8 100644
--- a/third_party/blink/web_tests/platform/linux/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index abfacee..9a4378da 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index a2eeeb28f..fa00af5 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index 4d647566..70629127 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-focus-ring-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
index b534b5f..3a5a617 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
index 9de967c2..a11bb1a 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-repaint-expected.png
index 03f1da5..445c640 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
index e5e8d6d..62a11ed 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
index 9c530f5..4ec84cb7 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
index 9572b808..d2f8471 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
index fd66e00f..70b8bec8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 9ecb131..1676cee 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-controls-rendering-expected.png
index 660f1fc..3afadb40 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-repaint-expected.png
index a185ca7..fd0f3d4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/controls-layout-direction-expected.png
index f805da63..df5b495 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-clone-expected.png
index 5a7ab65..81e3ff6 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-grey-scrubber-expected.png
index e6e87e6..2d74c5f 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-document-audio-repaint-expected.png
index 413020d..a85217a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 81ac686..64421fff 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 9fd2bb49..7c1f2de 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index 2ff66126..4237dea2 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
index 7bded8c..581c7f8 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
index 660f1fc..3afadb40 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-repaint-expected.png
index a185ca7..fd0f3d4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
index f805da63..df5b495 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
index 5a7ab65..81e3ff6 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
index e6e87e6..2d74c5f 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
index 413020d..a85217a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-controls-rendering-expected.png
index 2f2e5c6..4fcf781 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-repaint-expected.png
new file mode 100644
index 0000000..9219f13
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/controls-layout-direction-expected.png
index d490dd2..72cb126 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-clone-expected.png
index 9d3c8f2..369cb14 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-grey-scrubber-expected.png
index c326a6d..1b2cd88a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-document-audio-repaint-expected.png
index f894dea..421f698 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index f17f9518..bb1ee73 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
index 3fc2944..35aeb67e2 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
index 2f2e5c6..4fcf781 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
index d490dd2..72cb126 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
index 9d3c8f2..369cb14 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
index c326a6d..1b2cd88a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
index f894dea..421f698 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 0e09711..2d5e194 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/audio-controls-rendering-expected.png
index 029faa5..7f4d45d2 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/controls-layout-direction-expected.png
index 37a5e6ee..65a83152 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-clone-expected.png
index 53d53b64..6149fae 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-grey-scrubber-expected.png
index a005a14c..88420f90 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-document-audio-repaint-expected.png
index 0d087479..e525e33 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 37ddf2d..442db2f 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 49aa149..162fa65 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index 990eedd..0c704c7 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
index 029faa5..7f4d45d2 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-repaint-expected.png
index 4c440d524..9219f13 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
index 37a5e6ee..65a83152 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
index 53d53b64..6149fae 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
index a005a14c..88420f90 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
index 0d087479..e525e33 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/synchronous_html_parser/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index f2d69d7..44afb914 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac/media/audio-controls-rendering-expected.png
index b1729c1..e89c20c1 100644
--- a/third_party/blink/web_tests/platform/mac/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac/media/audio-repaint-expected.png
index a75c4d49..a601fb67 100644
--- a/third_party/blink/web_tests/platform/mac/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/mac/media/controls-layout-direction-expected.png
index 531e2cb..bf0589e 100644
--- a/third_party/blink/web_tests/platform/mac/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/mac/media/media-controls-clone-expected.png
index ab4d9b7..d814f1e2 100644
--- a/third_party/blink/web_tests/platform/mac/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/mac/media/media-controls-grey-scrubber-expected.png
index e13a47a..abe0a29 100644
--- a/third_party/blink/web_tests/platform/mac/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/mac/media/media-document-audio-repaint-expected.png
index 0222d0db..3231d6e8 100644
--- a/third_party/blink/web_tests/platform/mac/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index b614cdef..0344095 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 203ad8e..ddb4cd7 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index b8bb5cb..5da3c2f 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
index 81f0416c5..299cb82 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 2272219..2f385a5 100644
--- a/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/win/media/audio-controls-rendering-expected.png
index 95c461c..844fb6a 100644
--- a/third_party/blink/web_tests/platform/win/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/audio-repaint-expected.png b/third_party/blink/web_tests/platform/win/media/audio-repaint-expected.png
index e56c329..7f48a38 100644
--- a/third_party/blink/web_tests/platform/win/media/audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/controls-layout-direction-expected.png b/third_party/blink/web_tests/platform/win/media/controls-layout-direction-expected.png
index ec7b2a2..80939478 100644
--- a/third_party/blink/web_tests/platform/win/media/controls-layout-direction-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/controls-layout-direction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/media-controls-clone-expected.png b/third_party/blink/web_tests/platform/win/media/media-controls-clone-expected.png
index 366c068..c68c75c 100644
--- a/third_party/blink/web_tests/platform/win/media/media-controls-clone-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/media-controls-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/media-controls-grey-scrubber-expected.png b/third_party/blink/web_tests/platform/win/media/media-controls-grey-scrubber-expected.png
index cb26ec4..8d613450 100644
--- a/third_party/blink/web_tests/platform/win/media/media-controls-grey-scrubber-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/media-controls-grey-scrubber-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/media-document-audio-repaint-expected.png b/third_party/blink/web_tests/platform/win/media/media-document-audio-repaint-expected.png
index 20f5e52..ce5124d 100644
--- a/third_party/blink/web_tests/platform/win/media/media-document-audio-repaint-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/media-document-audio-repaint-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 66c9e33..458abc1 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh-hc/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
index 6884ba7..a0feae6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/fast/forms/color-scheme/media/video-overlay-menu-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
index f3d44bc..3191694 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-focus-ring-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
index 6193acc..c0cea46 100644
--- a/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/dark-color-scheme/media/audio-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/README.txt b/third_party/blink/web_tests/virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/README.txt
new file mode 100644
index 0000000..86d7324
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/layout_ng_block_frag/external/wpt/css/css-position/static-position/multicol/README.txt
@@ -0,0 +1,3 @@
+# This suite runs the tests in external/wpt/css/css-position/static-position/multicol
+# with--enable-blink-features=LayoutNGBlockFragmentation.
+# The LayoutNG project is described here: http://goo.gl/1hwhfX
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/README.md b/third_party/blink/web_tests/virtual/playback_speed_button/README.md
deleted file mode 100644
index 04b816d..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Overview
-
-This suite runs a small subset of tests with `--enable-features=PlaybackSpeedButton` to make sure the playback speed button shows up in media player controls.
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-add-hide-expected.txt b/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-add-hide-expected.txt
deleted file mode 100644
index 89fbee5..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-add-hide-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Test disabling controls on the video element with all controls.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-remove-show-expected.txt b/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-remove-show-expected.txt
deleted file mode 100644
index 1da368c2..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/controls-list-remove-show-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Test enabling controls on the video element with them enabled.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt b/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt
deleted file mode 100644
index 0184497..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/playback-speed-button-infinite-duration-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS The overflow playback speed button is not visible when infinite duration.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt b/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt
deleted file mode 100644
index 7ec4825..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/http/tests/media/controls/video-controls-overflow-menu-correct-ordering-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Overflow menu children appear in correct order.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html
deleted file mode 100644
index 779751d..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/click-and-drag-on-overflow-menu-doesnt-close.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE html>
-<html>
-<title>Test that when a user clicks and drags on the overflow it does not disappear.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<video controls width=500 preload=none src="https://need_a_url_here_to.show/download/button.mp4"></video>
-<script>
-async_test(t => {
-  const video = document.querySelector('video');
-  const menu = overflowMenu(video);
-  const overflowBtn = overflowButton(video);
-  const downloadBtn = downloadsOverflowItem(video);
-  const captionsBtn = captionsOverflowItem(video);
-  const playbackSpeedBtn = playbackSpeedOverflowItem(video);
-
-  // Add text tracks so that the captions option appears.
-  [ '../track/captions-webvtt/captions-fast.vtt',
-    '../track/captions-webvtt/captions-rtl.vtt' ].forEach(source => {
-    const track = document.createElement('track');
-    track.src = source;
-    track.kind = 'captions';
-    video.appendChild(track);
-  });
-
-  enableTestMode(video);
-
-  window.addEventListener('load', t.step_func(() => {
-    // Open the overflow menu and click and drag on it.
-    singleTapOnControl(overflowBtn, t.step_func(clickAndDrag));
-  }), { once: true });
-
-  // Neither the downloads button nor the captions button should receive a click during the click and drag.
-  downloadBtn.addEventListener('click', t.unreached_func('Downloads received a click'));
-  captionsBtn.addEventListener('click', t.unreached_func('Captions received a click'));
-  playbackSpeedBtn.addEventListener('click', t.unreached_func('Playback speed received a click'));
-
-  function clickAndDrag() {
-    assert_true(isControlVisible(menu), 'Overflow menu should be visible before we start click-and-drag');
-    assert_true(isControlVisible(downloadBtn), 'Download button should be visible');
-    assert_true(isControlVisible(captionsBtn), 'Captions button should be visible');
-    assert_true(isControlVisible(playbackSpeedBtn), 'Playback speed button should be visible');
-
-    const downloadPosition = elementCoordinates(downloadBtn);
-    const captionsPosition = elementCoordinates(captionsBtn);
-    const playbackSpeedPosition = elementCoordinates(playbackSpeedBtn);
-
-    // Click down on downloads but drag and release over captions and playback speed.
-    chrome.gpuBenchmarking.pointerActionSequence([{
-      source: 'mouse',
-      actions: [
-        { name: 'pointerDown', x: downloadPosition[0], y: downloadPosition[1] },
-        { name: 'pointerMove', x: captionsPosition[0], y: captionsPosition[1] },
-        { name: 'pointerUp', x: captionsPosition[0], y: captionsPosition[1] },
-        { name: 'pointerMove', x: playbackSpeedPosition[0], y: playbackSpeedPosition[1] },
-        { name: 'pointerUp', x: playbackSpeedPosition[0], y: playbackSpeedPosition[1] },
-      ]
-    }], t.step_func_done(() => {
-      assert_true(isControlVisible(menu), 'Overflow menu should still be visible after click-and-drag');
-    }));
-  }
-});
-</script>
-</html>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-button-disabled-no-source.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-button-disabled-no-source.html
deleted file mode 100644
index fd86658..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-button-disabled-no-source.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<title>Test that the overflow menu is disabled with no source.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<video controls width=400 controlsList=nodownload disablePictureInPicture></video>
-<script>
-async_test(t => {
-  const video = document.querySelector('video');
-
-  // Make sure the button is disabled.
-  assert_true(overflowButton(video).disabled);
-  assert_equals(overflowButton(video).style.display, '');
-
-  // Set the source and start playing.
-  video.src = '../../../../media/content/60_sec_video.webm';
-
-  video.play().then(t.step_func_done(() => {
-    // Make sure the button is no longer disabled.
-    assert_false(overflowButton(video).disabled);
-    assert_equals(overflowButton(video).style.display, '');
-  }), t.unreached_func());
-});
-</script>
-</html>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-hide-on-click-item.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-hide-on-click-item.html
deleted file mode 100644
index 323c529c..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-hide-on-click-item.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<title>Ensure overflow menu buttons are visible when expected.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<style>
-
-/*
- * We need to have the video small enough to have the mute button
- * displayed in overflow menu. Meanwhile, we want the video element
- * far from edge so that the overflow menu is fully displayed.
- */
-video {
-  width: 150px;
-  position: absolute;
-  left: 400px;
-  top: 400px;
-}
-
-</style>
-<video controls></video>
-<script>
-async_test(t => {
-  const video = document.querySelector('video');
-  video.src = '../../../../media/content/test.ogv';
-  enableTestMode(video);
-  const track = video.addTextTrack('captions');
-
-  video.onloadeddata = t.step_func(() => {
-    const menu = overflowMenu(video);
-
-    singleTapOnControl(overflowButton(video), t.step_func(() => {
-      assert_not_equals(getComputedStyle(menu).display, 'none');
-
-      singleTapOnControl(muteOverflowItem(video), t.step_func(() => {
-        assert_equals(getComputedStyle(menu).display, 'none');
-
-        singleTapOnControl(overflowButton(video), t.step_func(() => {
-          assert_not_equals(getComputedStyle(menu).display, 'none');
-
-          singleTapOnControl(captionsOverflowItem(video), t.step_func(() => {
-            assert_equals(getComputedStyle(menu).display, 'none');
-
-            singleTapOnControl(overflowButton(video), t.step_func(() => {
-              assert_not_equals(getComputedStyle(menu).display, 'none');
-
-              singleTapOnControl(playbackSpeedOverflowItem(video), t.step_func_done(() => {
-                assert_equals(getComputedStyle(menu).display, 'none');
-              }));
-            }));
-          }));
-        }));
-      }));
-    }));
-  });
-});
-</script>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-keyboard-navigation.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-keyboard-navigation.html
deleted file mode 100644
index c516885..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/overflow-menu-keyboard-navigation.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<title>Media Controls: overflow menu keyboard navigation</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<body>
-</body>
-<script>
-
-function testNavigation(root, elements, next, previous) {
-  // Internal copy of the array. They are otherwise passed by reference.
-  const list = elements.slice(0);
-
-  assert_equals(root.activeElement, list[0]);
-
-  list.forEach(element => {
-    if (element == list[0])
-      return;
-
-    next();
-
-    assert_equals(root.activeElement, element);
-    assert_equals(
-        window.getComputedStyle(element).getPropertyValue('background-color'),
-        'rgb(224, 224, 224)');
-  });
-
-  // Next action after reaching the end is a no-op.
-  next();
-  assert_equals(root.activeElement, list.pop());
-  // pop() will remove the last element which will allow the next iteration to
-  // start from n-1.
-
-  list.reverse().forEach(element => {
-    previous();
-
-    assert_equals(root.activeElement, element);
-    assert_equals(
-        window.getComputedStyle(element).getPropertyValue('background-color'),
-        'rgb(224, 224, 224)');
-  });
-
-  // Previous element after reaching the beginning is a no-op.
-  previous();
-  assert_equals(root.activeElement, list[list.length - 1]);
-}
-
-async_test(t => {
-  assert_true('internals' in window);
-  assert_true('eventSender' in window);
-
-  const video = document.createElement('video');
-  video.controls = true;
-  video.src = '../../../../media/content/test.ogv';
-  internals.mediaPlayerRemoteRouteAvailabilityChanged(video, true);
-
-  [ '../track/captions-webvtt/captions-fast.vtt',
-    '../track/captions-webvtt/captions-rtl.vtt' ].forEach(source => {
-    const track = document.createElement('track');
-    track.src = source;
-    track.kind = 'captions';
-    video.appendChild(track);
-  });
-
-  assert_equals(video.textTracks.length, 2);
-
-  document.body.appendChild(video);
-
-  video.addEventListener('loadedmetadata', t.step_func(() => {
-    assert_true(isVisible(overflowButton(video)));
-    singleTapOnControl(overflowButton(video), t.step_func_done(() => {
-      const menu = overflowMenu(video);
-      assert_true(isVisible(menu));
-      assert_equals(internals.shadowRoot(video).activeElement,
-                    menu.lastElementChild);
-
-      const elements = [ menu.lastElementChild,
-                         menu.lastElementChild.previousSibling,
-                         menu.lastElementChild.previousSibling.previousSibling ];
-
-      if (document.pictureInPictureEnabled)
-        elements.push(menu.lastElementChild.previousSibling.previousSibling.previousSibling);
-
-      testNavigation(internals.shadowRoot(video), elements,
-                     () => { eventSender.keyDown('ArrowUp'); },
-                     () => { eventSender.keyDown('ArrowDown'); });
-
-      testNavigation(internals.shadowRoot(video), elements,
-                     () => { eventSender.keyDown('Tab', [ 'shiftKey' ]); },
-                     () => { eventSender.keyDown('Tab'); });
-
-      // Navigating with Shift + Arrow Keys should also work.
-      testNavigation(internals.shadowRoot(video), elements,
-                     () => { eventSender.keyDown('ArrowUp', [ 'shiftKey' ]); },
-                     () => { eventSender.keyDown('ArrowDown', [ 'shiftKey' ]); });
-
-      // Closing.
-      eventSender.keyDown('Escape');
-      assert_false(isVisible(menu));
-      assert_equals(internals.shadowRoot(video).activeElement,
-                    overflowButton(video));
-    }));
-  }), { once: true });
-});
-</script>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/paint-controls-webkit-appearance-none.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/paint-controls-webkit-appearance-none.html
deleted file mode 100644
index 5548c5a..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/paint-controls-webkit-appearance-none.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<title>Test that player controls are painted correctly with -webkit-appearance: none;</title>
-<script src="../../../../media/media-controls.js"></script>
-<style>
-video::-webkit-media-controls-play-button {
-  -webkit-appearance: none;
-}
-</style>
-<video controls width=400></video>
-<script>
-  var video = document.querySelector('video');
-  enableTestMode(video);
-
-  video.requestVideoFrameCallback(() => {
-    if (window.testRunner)
-      testRunner.notifyDone();
-  });
-
-  video.src = '../../../../media/content/counting.ogv';
-
-  if (window.testRunner)
-    testRunner.waitUntilDone();
-</script>
-</html>
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text-expected.txt b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text-expected.txt
deleted file mode 100644
index c7861d9..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Overflow menu displays the correct text.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text.html b/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text.html
deleted file mode 100644
index 8840272..0000000
--- a/third_party/blink/web_tests/virtual/playback_speed_button/media/controls/video-controls-overflow-menu-text.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<title>Overflow menu displays the correct text.</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="../../../../media/media-controls.js"></script>
-<script src="../../../../media/overflow-menu.js"></script>
-
-<!--Padding ensures the overflow menu is visible for the tests. -->
-<body style="padding-top: 200px; padding-left: 100px">
-<video controls></video>
-<script>
-async_test(function(t) {
-  // Set up video
-  var video = document.querySelector("video");
-  video.src = '../../../../media/content/test.ogv';
-  // Add captions
-  var track = video.addTextTrack("captions");
-  // Pretend we have a cast device
-  internals.mediaPlayerRemoteRouteAvailabilityChanged(video, true);
-
-  video.onloadeddata = t.step_func_done(function() {
-    var overflowList = getOverflowList(video);
-    var children = overflowList.children;
-    // Ensure that all of the buttons are visible in the right order
-    for (var i = 0; i < children.length; i++) {
-      var child = children[i];
-      var innerButton = child.children[0];
-      // Check for text content disregarding casing. Mac OS and other OS
-      // have different casing styles.
-      assert_equals(child.textContent.toLowerCase(),
-                    overflowMenuText[i].toLowerCase());
-    }
-  });
-});
-</script>
-</body>
diff --git a/third_party/blink/web_tests/virtual/shared_array_buffer_on_desktop/http/tests/devtools/layers/layer-canvas-log-expected.txt b/third_party/blink/web_tests/virtual/shared_array_buffer_on_desktop/http/tests/devtools/layers/layer-canvas-log-expected.txt
new file mode 100644
index 0000000..19078b0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/shared_array_buffer_on_desktop/http/tests/devtools/layers/layer-canvas-log-expected.txt
@@ -0,0 +1,153 @@
+Tests layer command log
+
+Canvas log:
+{
+    0 : {
+        commandIndex : 0
+        method : "drawPaint"
+        params : {
+            paint : {
+                blendMode : "Src"
+                color : "#00000000"
+                flags : "none"
+                strokeCap : "Butt"
+                strokeJoin : "Miter"
+                strokeMiter : 4
+                strokeWidth : 0
+                styleName : "Fill"
+            }
+        }
+    }
+    1 : {
+        commandIndex : 1
+        method : "drawRect"
+        params : {
+            paint : {
+                color : "#FF0000FF"
+                flags : "AntiAlias"
+                strokeCap : "Butt"
+                strokeJoin : "Miter"
+                strokeMiter : 4
+                strokeWidth : 0
+                styleName : "Fill"
+            }
+            rect : {
+                bottom : 100
+                left : 0
+                right : 100
+                top : 0
+            }
+        }
+    }
+    2 : {
+        commandIndex : 2
+        method : "drawRect"
+        params : {
+            paint : {
+                color : "#FFFF0000"
+                flags : "AntiAlias"
+                strokeCap : "Butt"
+                strokeJoin : "Miter"
+                strokeMiter : 4
+                strokeWidth : 0
+                styleName : "Fill"
+            }
+            rect : {
+                bottom : 50
+                left : 0
+                right : 50
+                top : 0
+            }
+        }
+    }
+    3 : {
+        commandIndex : 3
+        method : "drawImageRect"
+        params : {
+            dst : {
+                bottom : 71
+                left : 0
+                right : 19
+                top : 50
+            }
+            image : {
+                height : 21
+                opaque : false
+                width : 19
+            }
+            paint : {
+                color : "#FF000000"
+                flags : "AntiAlias"
+                strokeCap : "Butt"
+                strokeJoin : "Miter"
+                strokeMiter : 4
+                strokeWidth : 0
+                styleName : "Fill"
+            }
+            sampling : {
+                filter : "kLinear"
+                mipmap : "kLinear"
+            }
+            src : {
+                bottom : 21
+                left : 0
+                right : 19
+                top : 0
+            }
+        }
+    }
+    4 : {
+        commandIndex : 4
+        method : "save"
+        params : undefined
+    }
+    5 : {
+        commandIndex : 5
+        method : "translate"
+        params : {
+            dx : 0
+            dy : 71
+        }
+    }
+    6 : {
+        commandIndex : 6
+        method : "clipRect"
+        params : {
+            SkRegion::Op : "kIntersect_Op"
+            rect : {
+                bottom : 150
+                left : 0
+                right : 300
+                top : 0
+            }
+            softClipEdgeStyle : true
+        }
+    }
+    7 : {
+        commandIndex : 7
+        method : "drawRect"
+        params : {
+            paint : {
+                color : "#7F000000"
+                flags : "AntiAlias"
+                strokeCap : "Butt"
+                strokeJoin : "Miter"
+                strokeMiter : 4
+                strokeWidth : 0
+                styleName : "Fill"
+            }
+            rect : {
+                bottom : 10
+                left : 0
+                right : 10
+                top : 0
+            }
+        }
+    }
+    8 : {
+        commandIndex : 8
+        method : "restore"
+        params : undefined
+    }
+}
+
diff --git a/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-cancel.html b/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-cancel.html
index 11a7e81c0..d52a419 100644
--- a/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-cancel.html
+++ b/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-cancel.html
@@ -63,21 +63,21 @@
 assertAnimationComposited('rotate', 'rotate', true);
 assertAnimationComposited('scale', 'scale', true);
 
-assertAnimationComposited('transform', 'translate', false);
-assertAnimationComposited('transform', 'rotate', false);
-assertAnimationComposited('transform', 'scale', false);
+assertAnimationComposited('transform', 'translate', true);
+assertAnimationComposited('transform', 'rotate', true);
+assertAnimationComposited('transform', 'scale', true);
 
-assertAnimationComposited('translate', 'transform', false);
-assertAnimationComposited('translate', 'rotate', false);
-assertAnimationComposited('translate', 'scale', false);
+assertAnimationComposited('translate', 'transform', true);
+assertAnimationComposited('translate', 'rotate', true);
+assertAnimationComposited('translate', 'scale', true);
 
-assertAnimationComposited('rotate', 'transform', false);
-assertAnimationComposited('rotate', 'scale', false);
-assertAnimationComposited('rotate', 'translate', false);
+assertAnimationComposited('rotate', 'transform', true);
+assertAnimationComposited('rotate', 'scale', true);
+assertAnimationComposited('rotate', 'translate', true);
 
-assertAnimationComposited('scale', 'transform', false);
-assertAnimationComposited('scale', 'rotate', false);
-assertAnimationComposited('scale', 'translate', false);
+assertAnimationComposited('scale', 'transform', true);
+assertAnimationComposited('scale', 'rotate', true);
+assertAnimationComposited('scale', 'translate', true);
 
 assertAnimationComposited('opacity', 'transform', true);
 assertAnimationComposited('opacity', 'translate', true);
diff --git a/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-properties.html b/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-properties.html
index 81efc4e..b7cd669 100644
--- a/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-properties.html
+++ b/third_party/blink/web_tests/virtual/threaded-no-composited-antialiasing/animations/compositor-independent-transform-properties.html
@@ -38,7 +38,6 @@
 }
 
 var assertIsComposited = function(properties) { return assertComposited(properties, true); }
-var assertIsNotComposited = function(properties) { return assertComposited(properties, false); }
 
 assertIsComposited('transform');
 assertIsComposited('opacity');
@@ -52,14 +51,14 @@
 assertIsComposited(['rotate', 'opacity']);
 assertIsComposited(['scale', 'opacity']);
 
-assertIsNotComposited(['transform', 'translate']);
-assertIsNotComposited(['transform', 'scale']);
-assertIsNotComposited(['transform', 'rotate']);
+assertIsComposited(['transform', 'translate']);
+assertIsComposited(['transform', 'scale']);
+assertIsComposited(['transform', 'rotate']);
 
-assertIsNotComposited(['translate', 'scale']);
-assertIsNotComposited(['translate', 'rotate']);
-assertIsNotComposited(['rotate', 'scale']);
+assertIsComposited(['translate', 'scale']);
+assertIsComposited(['translate', 'rotate']);
+assertIsComposited(['rotate', 'scale']);
 
-assertIsNotComposited(['translate', 'rotate', 'scale']);
-assertIsNotComposited(['transform', 'translate', 'rotate', 'scale']);
+assertIsComposited(['translate', 'rotate', 'scale']);
+assertIsComposited(['transform', 'translate', 'rotate', 'scale']);
 </script>
diff --git a/third_party/blink/web_tests/virtual/threaded/external/wpt/css/css-transforms/individual-transform/animation/README.txt b/third_party/blink/web_tests/virtual/threaded/external/wpt/css/css-transforms/individual-transform/animation/README.txt
new file mode 100644
index 0000000..189593f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/threaded/external/wpt/css/css-transforms/individual-transform/animation/README.txt
@@ -0,0 +1,4 @@
+# This suite runs tests in
+# external/wpt/css/css-transforms/individual-transform/animation with
+# --enable-threaded-compositing
+
diff --git a/third_party/blink/web_tests/wpt_internal/sanitizer-api/sanitizer-query-config.https.tenative.html b/third_party/blink/web_tests/wpt_internal/sanitizer-api/sanitizer-query-config.https.tenative.html
index 71e25fa..bd7c7ea3 100644
--- a/third_party/blink/web_tests/wpt_internal/sanitizer-api/sanitizer-query-config.https.tenative.html
+++ b/third_party/blink/web_tests/wpt_internal/sanitizer-api/sanitizer-query-config.https.tenative.html
@@ -12,9 +12,12 @@
       assert_equals(obj1, obj2);
     } else if (typeof obj1 == "boolean") {
       assert_true(obj1 == obj2);
+    } else if (Array.isArray(obj1)) {
+      assert_equals(obj1.length, obj2.length);
+      assert_array_equals(obj1.sort(), obj2.sort());
     } else if (typeof obj1 == "object") {
       assert_array_equals(Object.keys(obj1).sort(), Object.keys(obj2).sort());
-      for (const k in Object.keys(obj1))
+      for (const k of Object.keys(obj1))
         assert_deep_equals(obj1[k], obj2[k]);
     }
   }
@@ -41,7 +44,7 @@
 
   test(t => {
     const configs = [{
-      allowElements: ["div", "sPAn", "helloworld"],
+      allowElements: ["div", "span", "helloworld"],
       dropElements: ["xxx"],
       allowAttributes: { "class": ["*"], "color": ["span", "div"],
                          "onclick": ["*"] },
@@ -53,7 +56,19 @@
     }];
     for (const config of configs)
       assert_deep_equals(config, new Sanitizer(config).getConfiguration());
+
+    // Also test a mixed case variant:
+    const config_0_mixed = {
+      allowElements: ["div", "sPAn", "HelloWorld"],
+      dropElements: ["XXX"],
+      allowAttributes: { "class": ["*"], "color": ["sPAn", "div"],
+                         "onclick": ["*"] },
+      allowCustomElements: true,
+    };
+    assert_deep_equals(configs[0],
+                       new Sanitizer(config_0_mixed).getConfiguration());
   }, "SanitizerAPI getConfiguration() reflects creation config.");
+
 </script>
 </body>
 </html>
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 098117d2..19c88a2 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-10-4-314-g59e95b014
-Revision: 59e95b014aa162393d6d569225cf713d71ffdc33
+Version: VER-2-10-4-323
+Revision: 5d27b10f4c6c8e140bd48a001b98037ac0d54118
 CPEPrefix: cpe:/a:freetype:freetype:2.10.4
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
index 7d69aac..0097f22 100644
--- a/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
+++ b/third_party/freetype/include/freetype-custom/freetype/config/ftoption.h
@@ -105,8 +105,7 @@
    *
    * ```
    *   FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
-   *                       cff:no-stem-darkening=1 \
-   *                       autofitter:warping=1
+   *                       cff:no-stem-darkening=1
    * ```
    *
    */
@@ -913,24 +912,6 @@
 
   /**************************************************************************
    *
-   * Compile 'autofit' module with warp hinting.  The idea of the warping
-   * code is to slightly scale and shift a glyph within a single dimension so
-   * that as much of its segments are aligned (more or less) on the grid.  To
-   * find out the optimal scaling and shifting value, various parameter
-   * combinations are tried and scored.
-   *
-   * You can switch warping on and off with the `warping` property of the
-   * auto-hinter (see file `ftdriver.h` for more information; by default it
-   * is switched off).
-   *
-   * This experimental option is not active if the rendering mode is
-   * `FT_RENDER_MODE_LIGHT`.
-   */
-/* #define AF_CONFIG_OPTION_USE_WARPER */
-
-
-  /**************************************************************************
-   *
    * Use TrueType-like size metrics for 'light' auto-hinting.
    *
    * It is strongly recommended to avoid this option, which exists only to
diff --git a/third_party/libavif/BUILD.gn b/third_party/libavif/BUILD.gn
index 4e5ab33..deaaaeea 100644
--- a/third_party/libavif/BUILD.gn
+++ b/third_party/libavif/BUILD.gn
@@ -19,6 +19,7 @@
     "src/src/read.c",
     "src/src/reformat.c",
     "src/src/reformat_libyuv.c",
+    "src/src/scale.c",
     "src/src/stream.c",
     "src/src/utils.c",
   ]
@@ -26,9 +27,9 @@
   # configs -= [ "//build/config/compiler:chromium_code" ]
   # configs += [ "//build/config/compiler:no_chromium_code" ]
   include_dirs = [ "src/include/" ]
-  defines = []
+  defines = [ "AVIF_LIBYUV_ENABLED" ]
 
-  deps = []
+  deps = [ "//third_party/libyuv" ]
 
   if (enable_dav1d_decoder) {
     sources += [ "src/src/codec_dav1d.c" ]
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium
index fa4af9b..b0b2832 100644
--- a/third_party/metrics_proto/README.chromium
+++ b/third_party/metrics_proto/README.chromium
@@ -1,7 +1,7 @@
 Name: Metrics Protos
 Short Name: metrics_proto
 URL: This is the canonical public repository
-Version: 384480155
+Version: 384565628
 Date: 2021/07/13 UTC
 License: BSD
 Security Critical: Yes
diff --git a/third_party/metrics_proto/system_profile.proto b/third_party/metrics_proto/system_profile.proto
index 3b16229..9e0228e 100644
--- a/third_party/metrics_proto/system_profile.proto
+++ b/third_party/metrics_proto/system_profile.proto
@@ -995,6 +995,7 @@
     CROS_SMART_DIM = 26;
     ZXCVBN_DATA = 27;
     AUTOFILL_REGEX_CONSTANTS = 28;
+    WEBVIEW_APPS_PACKAGE_NAMES_ALLOWLIST = 29;
   }
 
   // Information about what Chrome components are registered and at which
diff --git a/third_party/nearby/OWNERS b/third_party/nearby/OWNERS
index d3714a7..37145905 100644
--- a/third_party/nearby/OWNERS
+++ b/third_party/nearby/OWNERS
@@ -1,5 +1,4 @@
 alexchau@chromium.org
 hansberry@chromium.org
-vecore@chromium.org
 
 file://chrome/browser/nearby_sharing/OWNERS
diff --git a/third_party/securemessage/OWNERS b/third_party/securemessage/OWNERS
index d3714a7..37145905 100644
--- a/third_party/securemessage/OWNERS
+++ b/third_party/securemessage/OWNERS
@@ -1,5 +1,4 @@
 alexchau@chromium.org
 hansberry@chromium.org
-vecore@chromium.org
 
 file://chrome/browser/nearby_sharing/OWNERS
diff --git a/third_party/tcmalloc/README.chromium b/third_party/tcmalloc/README.chromium
index ec09d38..3a8e560 100644
--- a/third_party/tcmalloc/README.chromium
+++ b/third_party/tcmalloc/README.chromium
@@ -79,3 +79,4 @@
 - Enable ASLR support on both Linux and ChromeOS
 - Remove unused base::subtle::Acquire_Store/Release_Load (https://github.com/gperftools/gperftools/pull/1249)
 - Fix thread-safety annotations (https://github.com/gperftools/gperftools/pull/1251)
+- Fixed -Wimplicit-int-float-conversion.
diff --git a/third_party/tcmalloc/chromium/src/sampler.cc b/third_party/tcmalloc/chromium/src/sampler.cc
index 358b52c7..6337826 100644
--- a/third_party/tcmalloc/chromium/src/sampler.cc
+++ b/third_party/tcmalloc/chromium/src/sampler.cc
@@ -116,7 +116,8 @@
   // Very large values of interval overflow ssize_t. If we happen to
   // hit such improbable condition, we simply cheat and clamp interval
   // to largest supported value.
-  return static_cast<ssize_t>(std::min<double>(interval, MAX_SSIZE));
+  return static_cast<ssize_t>(
+      std::min(interval, static_cast<double>(MAX_SSIZE)));
 }
 
 bool Sampler::RecordAllocationSlow(size_t k) {
diff --git a/third_party/ukey2/OWNERS b/third_party/ukey2/OWNERS
index d3714a7..37145905 100644
--- a/third_party/ukey2/OWNERS
+++ b/third_party/ukey2/OWNERS
@@ -1,5 +1,4 @@
 alexchau@chromium.org
 hansberry@chromium.org
-vecore@chromium.org
 
 file://chrome/browser/nearby_sharing/OWNERS
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index 590e6e8..3a55e83 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -49,8 +49,11 @@
 src/unittests/test_group_test.ts
 src/unittests/async_expectations.spec.ts
 src/unittests/basic.spec.ts
+src/webgpu/util/math.ts
+src/webgpu/util/conversion.ts
 src/webgpu/util/check_contents.ts
 src/unittests/check_contents.spec.ts
+src/unittests/conversion.spec.ts
 src/unittests/getStackTrace.spec.ts
 src/unittests/listing.ts
 src/unittests/loaders_and_trees.spec.ts
@@ -67,11 +70,9 @@
 src/webgpu/util/buffer.ts
 src/webgpu/util/navigator_gpu.ts
 src/webgpu/util/device_pool.ts
-src/webgpu/util/math.ts
 src/webgpu/util/unions.ts
 src/webgpu/util/texture/base.ts
 src/webgpu/util/texture/layout.ts
-src/webgpu/util/conversion.ts
 src/webgpu/util/texture/texel_data.ts
 src/webgpu/gpu_test.ts
 src/webgpu/examples.spec.ts
diff --git a/tools/mb/rts_banned_suites.json b/tools/mb/rts_banned_suites.json
index 48b0ff6..a64b9a63 100644
--- a/tools/mb/rts_banned_suites.json
+++ b/tools/mb/rts_banned_suites.json
@@ -2,15 +2,24 @@
 
   "*": [
     "xr_browser_tests",
-    "telemetry_gpu_integration_test",
     "metrics_python_tests",
     "mojo_python_unittests",
     "blink_python_tests",
     "grit_python_unittests",
     "telemetry_perf_unittests",
+    "telemetry_perf_unittests_android_chrome",
+    "telemetry_perf_unittests_android_monochrome",
+    "telemetry_perf_unittests_android_monochrome_bundle",
+    "telemetry_perf_unittests_android_weblayer",
+    "telemetry_perf_unittests_android_webview",
     "maps_tests",
     "telemetry_gpu_unittests",
-    "telemetry_gpu_integration_test"
+    "telemetry_gpu_integration_test",
+    "telemetry_gpu_integration_test_android_chrome",
+    "telemetry_gpu_integration_test_android_monochrome",
+    "telemetry_gpu_integration_test_android_monochrome_bundle",
+    "telemetry_gpu_integration_test_android_weblayer",
+    "telemetry_gpu_integration_test_android_webview"
   ],
   "fuchsia_x64_rts": [
     "blink_web_tests"
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 7354566..73a81d4 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -21224,6 +21224,22 @@
   </description>
 </action>
 
+<action name="ReadingList.Dialog.AddCurrentPage">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user added a page to the reading list from the dialog bubble.
+  </description>
+</action>
+
+<action name="ReadingList.Dialog.Navigation">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user navigated to a page from the reading list dialog bubble.
+  </description>
+</action>
+
 <action name="Redo">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -23260,6 +23276,58 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="SidePanel.Bookmarks.FolderClose">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user collapsed a bookmarks folder within the side panel.
+  </description>
+</action>
+
+<action name="SidePanel.Bookmarks.FolderOpen">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user expanded a bookmarks folder within the side panel.
+  </description>
+</action>
+
+<action name="SidePanel.Bookmarks.Navigation">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user navigated to a page from bookmarks in the side panel.
+  </description>
+</action>
+
+<action name="SidePanel.Hide">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>The user closed the side panel.</description>
+</action>
+
+<action name="SidePanel.ReadingList.AddCurrentPage">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user added a page to the reading list from the side panel.
+  </description>
+</action>
+
+<action name="SidePanel.ReadingList.Navigation">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>
+    The user navigated to a page from the reading list in the side panel.
+  </description>
+</action>
+
+<action name="SidePanel.Show">
+  <owner>corising@chromium.org</owner>
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <description>The user opened the side panel.</description>
+</action>
+
 <action name="Signin_Abort_Signin">
   <owner>mahmadi@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a71a7d17..b1c0aaf 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3441,6 +3441,15 @@
       label="selected all downloads, and then selected downloading the page"/>
 </enum>
 
+<enum name="AppPackageNameLoggingRuleStatus">
+  <int value="0" label="Not loaded and no cache"/>
+  <int value="1" label="Not loaded and using cached"/>
+  <int value="2" label="Loading new version failed and no cache"/>
+  <int value="3" label="Loading new version failed and using cached"/>
+  <int value="4" label="New version is loaded"/>
+  <int value="5" label="New version is the same as cached"/>
+</enum>
+
 <enum name="AppPromoAction">
   <int value="0" label="PROMO_LAUNCH_APP"/>
   <int value="1" label="PROMO_LAUNCH_WEB_STORE"/>
@@ -47919,6 +47928,7 @@
   <int value="-731502579" label="CupsPrintersUiOverhaul:disabled"/>
   <int value="-731133967" label="AutofillSettingsCardTypeSplit:disabled"/>
   <int value="-728461030" label="AutofillPruneSuggestions:disabled"/>
+  <int value="-728187009" label="NtpRealboxSuggestionAnswers:enabled"/>
   <int value="-727860269" label="WebAuthenticationBle:disabled"/>
   <int value="-726892130" label="AndroidMessagesIntegration:disabled"/>
   <int value="-726844226"
@@ -49034,6 +49044,8 @@
   <int value="224019823" label="CompositeAfterPaint:enabled"/>
   <int value="225610933" label="SystemLatinPhysicalTyping:enabled"/>
   <int value="226590039" label="OverviewButton:disabled"/>
+  <int value="228107154"
+      label="OmniboxUpdatedConnectionSecurityIndicators:enabled"/>
   <int value="229476202" label="CryptAuthV2Enrollment:enabled"/>
   <int value="229877058" label="ShelfScrollable:disabled"/>
   <int value="233721248" label="DownloadRename:disabled"/>
@@ -50915,6 +50927,8 @@
   <int value="1777806335" label="UsePasswordSeparatedSigninFlow:disabled"/>
   <int value="1779530254"
       label="AccessibilityInternalsPageImprovements:disabled"/>
+  <int value="1780392521"
+      label="OmniboxUpdatedConnectionSecurityIndicators:disabled"/>
   <int value="1782210532" label="PerNavigationMojoInterface:disabled"/>
   <int value="1783293530" label="disallow-autofill-sync-credential"/>
   <int value="1783837132" label="enable-threaded-gpu-rasterization"/>
@@ -51293,6 +51307,7 @@
   <int value="2072231406" label="SingleProcessMash:disabled"/>
   <int value="2073113207" label="SensorContentSetting:disabled"/>
   <int value="2075207488" label="AutomaticPasswordGeneration:disabled"/>
+  <int value="2075718434" label="NtpRealboxSuggestionAnswers:disabled"/>
   <int value="2076787478" label="OmniboxDisplayTitleForCurrentUrl:disabled"/>
   <int value="2076903744" label="progress-bar-animation"/>
   <int value="2077106718" label="EnableMessagesWebPush:enabled"/>
@@ -58571,6 +58586,11 @@
   <int value="2" label="NoteShared"/>
 </enum>
 
+<enum name="NoteShareDestination">
+  <int value="0" label="First Party"/>
+  <int value="1" label="Third Party"/>
+</enum>
+
 <enum name="NoteTakingAppLaunchResult">
   <int value="0" label="Chrome app launched successfully"/>
   <int value="1" label="Chrome app missing"/>
@@ -65811,6 +65831,7 @@
   <int value="19" label="kClientCertRequested"/>
   <int value="20" label="kNavigationRequestNetworkFailure"/>
   <int value="21" label="kMaxNumOfRunningPrerendersExceeded"/>
+  <int value="22" label="kCancelAllHostsForTesting"/>
 </enum>
 
 <enum name="PrerenderHoverEvent">
@@ -78866,7 +78887,7 @@
 <enum name="SyncErrorInfoBarAction">
   <int value="0" label="Shown"/>
   <int value="1" label="Dismissed"/>
-  <int value="2" label="Open settings clicked"/>
+  <int value="2" label="Button clicked"/>
 </enum>
 
 <enum name="SyncErrorInfobarTypes">
@@ -82645,6 +82666,12 @@
   <int value="0" label="WiFi Scan"/>
 </enum>
 
+<enum name="UserInteractionType">
+  <int value="0" label="keyboard"/>
+  <int value="1" label="tap or click"/>
+  <int value="2" label="drag"/>
+</enum>
+
 <enum name="UsernameDetectionMethod">
   <int value="0" label="No username detected"/>
   <int value="1" label="Base heuristic"/>
diff --git a/tools/metrics/histograms/histograms_xml/android/histograms.xml b/tools/metrics/histograms/histograms_xml/android/histograms.xml
index fb377c8..28cc075 100644
--- a/tools/metrics/histograms/histograms_xml/android/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/android/histograms.xml
@@ -3333,6 +3333,19 @@
   </summary>
 </histogram>
 
+<histogram name="Android.WebView.Metrics.PackagesAllowList.RecordStatus"
+    enum="AppPackageNameLoggingRuleStatus" expires_after="2022-07-01">
+  <owner>hazems@chromium.org</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Records the status of the apps package names allowlist used to populate the
+    &quot;app_package_name&quot; field in UMA metrics log. The status tracks if
+    a new version is loaded, a cached one is used or if loading the allowlist
+    has failed. It's recorded everytime the app package name is queried when a
+    new metrics log is created.
+  </summary>
+</histogram>
+
 <histogram
     name="Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay"
     units="ms" expires_after="2022-07-01">
diff --git a/tools/metrics/histograms/histograms_xml/browser/histograms.xml b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
index 80b6391f..eb82e8d7 100644
--- a/tools/metrics/histograms/histograms_xml/browser/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
@@ -121,8 +121,28 @@
 </histogram>
 
 <histogram
+    name="Browser.ContinuousSearch.UI.CarouselScrolled2{ExperimentCategory}"
+    enum="Boolean" expires_after="2021-09-20">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <owner>yashard@chromium.org</owner>
+  <summary>
+    Records whether the UI was scrolled while being shown. It is emmited when
+    the CSN session is considered ended. Actions that can end the session
+    include closing the tab, navigating away from the CSN url list or dismissing
+    the UI.
+  </summary>
+  <token key="ExperimentCategory" variants="ContinuousSearchExperiment"/>
+</histogram>
+
+<histogram
     name="Browser.ContinuousSearch.UI.CarouselScrolled{ExperimentCategory}"
     enum="Boolean" expires_after="2021-09-20">
+  <obsolete>
+    Obsoleted as of 2021-07. It is replaced by
+    Browser.ContinuousSearch.UI.CarouselScrolled2 as the emission method has
+    changed.
+  </obsolete>
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
   <owner>yashard@chromium.org</owner>
@@ -146,6 +166,36 @@
   <token key="ExperimentCategory" variants="ContinuousSearchExperiment"/>
 </histogram>
 
+<histogram
+    name="Browser.ContinuousSearch.UI.DismissButtonClicked{ExperimentCategory}"
+    enum="Boolean" expires_after="2021-09-20">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <owner>yashard@chromium.org</owner>
+  <summary>
+    Records whether the UI dismiss button was pressed while UI was being shown.
+    It is emmited when the CSN session is considered ended. Actions that can end
+    the session include closing the tab, navigating away from the CSN url list
+    or dismissing the UI.
+  </summary>
+  <token key="ExperimentCategory" variants="ContinuousSearchExperiment"/>
+</histogram>
+
+<histogram
+    name="Browser.ContinuousSearch.UI.ProviderButtonClicked{ExperimentCategory}"
+    enum="Boolean" expires_after="2021-09-20">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <owner>yashard@chromium.org</owner>
+  <summary>
+    Records whether the provider button was pressed while UI was being shown. It
+    is emmited when the CSN session is considered ended. Actions that can end
+    the session include closing the tab, navigating away from the CSN url list
+    or dismissing the UI.
+  </summary>
+  <token key="ExperimentCategory" variants="ContinuousSearchExperiment"/>
+</histogram>
+
 <histogram name="Browser.DarkModeStatus" enum="DarkModeStatus"
     expires_after="2021-08-29">
   <owner>lgrey@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/content/histograms.xml b/tools/metrics/histograms/histograms_xml/content/histograms.xml
index 5409a61..91962351 100644
--- a/tools/metrics/histograms/histograms_xml/content/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/content/histograms.xml
@@ -1752,6 +1752,16 @@
   </token>
 </histogram>
 
+<histogram name="ContentSuggestions.{FeedType}.LoadStreamStatus.ManualRefresh"
+    enum="FeedLoadStreamStatus" expires_after="2022-07-01">
+  <owner>jianli@chromium.org</owner>
+  <owner>feed@chromium.org</owner>
+  <summary>
+    Android: status of pulling-to-refresh the {FeedType} stream per the user
+    request. Reported when the refresh completes.
+  </summary>
+</histogram>
+
 <histogram name="ContentSuggestions.{FeedType}.ReachedEndOfFeed" units="index"
     expires_after="2022-07-01">
   <owner>harringtond@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
index 075cedd..c60d091 100644
--- a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
@@ -289,6 +289,9 @@
 
 <histogram name="Extensions.Checkup.NtpPromoClicked"
     enum="ExtensionCheckupMessage" expires_after="M85">
+  <obsolete>
+    Code removed 2021/07.
+  </obsolete>
   <owner>archanasimha@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -304,6 +307,9 @@
 
 <histogram name="Extensions.Checkup.NtpPromoShown"
     enum="ExtensionCheckupMessage" expires_after="M85">
+  <obsolete>
+    Code removed 2021/07.
+  </obsolete>
   <owner>archanasimha@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -318,6 +324,9 @@
 </histogram>
 
 <histogram name="Extensions.Checkup.TimeSpent" units="ms" expires_after="M85">
+  <obsolete>
+    Code removed 2021/07.
+  </obsolete>
   <owner>archanasimha@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -3965,7 +3974,7 @@
 
 <histogram
     name="Extensions.{ExtensionSource}ForceInstalled{ErrorType}HttpErrorCode2"
-    enum="HttpResponseCode" expires_after="2021-08-22">
+    enum="HttpResponseCode" expires_after="2022-02-01">
   <owner>burunduk@chromium.org</owner>
   <owner>swapnilgupta@google.com</owner>
   <owner>managed-devices@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/ios/histograms.xml b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
index bae12c9..c599558be 100644
--- a/tools/metrics/histograms/histograms_xml/ios/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
@@ -396,6 +396,9 @@
 
 <histogram name="IOS.Dialogs.JavaScriptDialogClosed"
     enum="IOSJavaScriptDialogDismissalCause" expires_after="M80">
+  <obsolete>
+    Deprecated 07/2021 as it is no longer used for analysis.
+  </obsolete>
   <owner>kkhorimoto@chromium.org</owner>
   <owner>michaeldo@chromium.org</owner>
   <summary>Tracks the way JavaScript dialogs are closed on iOS.</summary>
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index c6d306e..12b6210 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -5394,8 +5394,8 @@
 </histogram>
 
 <histogram name="Net.TcpConnectAttempt.Latency.Error" units="ms"
-    expires_after="2021-08-22">
-  <owner>eroman@chromium.org</owner>
+    expires_after="2022-07-12">
+  <owner>bashi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
     Time taken when failed to establish a TCP connection to an individual
@@ -5405,8 +5405,8 @@
 </histogram>
 
 <histogram name="Net.TcpConnectAttempt.Latency.Success" units="ms"
-    expires_after="2021-10-25">
-  <owner>eroman@chromium.org</owner>
+    expires_after="2022-07-12">
+  <owner>bashi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
     Time taken to successfully establish a TCP connection to an individual
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 84a3c33..a2cbe7ea 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -10669,6 +10669,15 @@
   </summary>
 </histogram>
 
+<histogram name="NoteCreation.ShareDestination" enum="NoteShareDestination"
+    expires_after="2021-12-01">
+  <owner>sebsg@chromium.org</owner>
+  <owner>chrome-creation@google.com</owner>
+  <summary>
+    Records the destination type (first or third party) for the shared note.
+  </summary>
+</histogram>
+
 <histogram name="NoteCreation.TimeTo{action}" units="ms"
     expires_after="2021-12-01">
   <owner>sebsg@chromium.org</owner>
@@ -13447,7 +13456,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.GetFallbackFontsTime" units="ms"
-    expires_after="2021-08-09">
+    expires_after="2022-07-14">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -13458,7 +13467,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.GetFallbackFontTime" units="ms"
-    expires_after="2021-12-12">
+    expires_after="2022-07-14">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -13469,7 +13478,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.ShapeRunsFallback" enum="ShapeRunFallback"
-    expires_after="2021-12-12">
+    expires_after="2022-07-14">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
@@ -13479,7 +13488,7 @@
 </histogram>
 
 <histogram name="RenderTextHarfBuzz.ShapeRunsWithFallbackFontsTime" units="ms"
-    expires_after="2021-12-12">
+    expires_after="2022-07-14">
   <owner>ccameron@chromium.org</owner>
   <owner>etienneb@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/password/histograms.xml b/tools/metrics/histograms/histograms_xml/password/histograms.xml
index 5aba793..47bd248 100644
--- a/tools/metrics/histograms/histograms_xml/password/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/password/histograms.xml
@@ -2488,6 +2488,16 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.UpdateLoginPasswordIssuesHasValue"
+    enum="BooleanSet" expires_after="2021-09-30">
+  <owner>ioanap@chromium.org</owner>
+  <owner>chrome-password-manager-metrics-alerts@google.com</owner>
+  <summary>
+    Recorded when UpdateLogin is called on the login database. Records whether
+    the form passed to the method has a value set for password_issues or not.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.UpdateUIDismissalReason"
     enum="PasswordManagerUIDismissalReason" expires_after="2021-12-12">
   <owner>vasilii@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/power/histograms.xml b/tools/metrics/histograms/histograms_xml/power/histograms.xml
index e61afd2..b471cef 100644
--- a/tools/metrics/histograms/histograms_xml/power/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/power/histograms.xml
@@ -993,6 +993,10 @@
 
 <histogram name="Power.MainScreenBrightness" units="%"
     expires_after="2021-11-30">
+  <obsolete>
+    Replaced by Power.MainScreenBrightness2 in July 2021. The new histogram
+    allows value superior to 100% as sometime reported by the OS.
+  </obsolete>
   <owner>sebmarchand@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -1001,6 +1005,18 @@
   </summary>
 </histogram>
 
+<histogram name="Power.MainScreenBrightness2" units="%"
+    expires_after="2021-11-30">
+  <owner>sebmarchand@chromium.org</owner>
+  <owner>catan-team@chromium.org</owner>
+  <summary>
+    The level of the screen backlight in percent if it's not available. Only
+    recorded on Mac devices with an Intel processor. Recorded every 2 minutes.
+    Note: the reported value can sometime exceed 100%, this histogram allows
+    value up to 150%.
+  </summary>
+</histogram>
+
 <histogram name="Power.MainScreenBrightnessAvailable" units="Boolean"
     expires_after="2021-11-30">
   <owner>sebmarchand@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 08822b97..8725a7c 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -13297,6 +13297,12 @@
       The interval duration, in seconds.
     </summary>
   </metric>
+  <metric name="MainScreenBrightnessPercent">
+    <summary>
+      The brightness of the main screen in percent or -1 if not available.
+      Samples have a 20% granularity, e.g. 65% will report as 60%.
+    </summary>
+  </metric>
   <metric name="MaxTabCount">
     <summary>
       The maximum number of tabs that existed at the same time during the
@@ -14161,6 +14167,40 @@
   </metric>
 </event>
 
+<event name="Responsiveness.UserInteraction">
+  <owner>hbsong@chromium.org</owner>
+  <summary>
+    Metrics that are associated with user interactions and recorded when users
+    interact with web pages. Currently we are interested in keyboard, tap, click
+    and drag. A user interaction often encompasses multiple input events. For
+    keyboard interactions, we only care about keydown and keyup. For tap, click
+    and drag, we only measure pointerdown, pointerup and click.
+  </summary>
+  <metric name="InteractionType" enum="UserInteractionType">
+    <summary>
+      The type of the user interaction that triggered input event sequence, not
+      the input event type. It can be keyboard, tap, click or drag.
+    </summary>
+  </metric>
+  <metric name="MaxEventDuration">
+    <summary>
+      The longest input event duration within the user interaction. The unit of
+      duration is ms. For example, if a user pressed a key, we can get a keydown
+      and a keyup. If the duration(keydown) &gt; duration(keyup), the value of
+      this metric will be duration(keydown).
+    </summary>
+  </metric>
+  <metric name="TotalEventDuration">
+    <summary>
+      The sum of input event durations within the user interaction without
+      double counting the overlap. The unit of duration is ms. For example, if a
+      user pressed a key, we can get a keydown and a keyup. The value of this
+      metric will be duration(keydown) + duration(keyup) -
+      duration(intersection(keydown, keyup)).
+    </summary>
+  </metric>
+</event>
+
 <event name="ResponsivenessMeasurement">
   <owner>npm@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 04fb516..902b24d 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -128,6 +128,15 @@
     ]
   }
 
+  group("telemetry_chrome_test_android_monochrome_bundle") {
+    testonly = true
+
+    data_deps = [
+      ":telemetry_chrome_test",
+      "//chrome/android:monochrome_public_bundle",
+    ]
+  }
+
   group("telemetry_chrome_test_android_weblayer") {
     testonly = true
 
@@ -147,6 +156,28 @@
       "//android_webview/tools/system_webview_shell:system_webview_shell_apk",
     ]
   }
+
+  if (enable_chrome_android_internal) {
+    import("//clank/telemetry_browser_types.gni")
+
+    template("telemetry_chrome_test_clank_template") {
+      forward_variables_from(invoker, [ "telemetry_target_suffix" ])
+      group(target_name) {
+        testonly = true
+        data_deps = [
+          ":telemetry_chrome_test",
+          "//clank:telemetry_clank_test${telemetry_target_suffix}",
+        ]
+      }
+    }
+
+    foreach(_target_suffix, telemetry_clank_browser_target_suffixes) {
+      telemetry_chrome_test_clank_template(
+          "telemetry_chrome_test${_target_suffix}") {
+        telemetry_target_suffix = _target_suffix
+      }
+    }
+  }
 }
 
 group("telemetry_weblayer_apks") {
diff --git a/tools/perf/chrome_telemetry_build/android_browser_types.gni b/tools/perf/chrome_telemetry_build/android_browser_types.gni
index cb5eb4c4..f7d0350 100644
--- a/tools/perf/chrome_telemetry_build/android_browser_types.gni
+++ b/tools/perf/chrome_telemetry_build/android_browser_types.gni
@@ -2,9 +2,22 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/android/config.gni")
+
+# This provides a list of suffixes for all Android Chromium Telemetry targets
+# for use in auto-generating binary-specific targets.
+# All the suffixes should be kept in sync with android_browser_types.py.
+
 telemetry_android_browser_target_suffixes = [
   "_android_chrome",
   "_android_monochrome",
+  "_android_monochrome_bundle",
   "_android_weblayer",
   "_android_webview",
 ]
+
+if (enable_chrome_android_internal) {
+  import("//clank/telemetry_browser_types.gni")
+  telemetry_android_browser_target_suffixes +=
+      telemetry_clank_browser_target_suffixes
+}
diff --git a/tools/perf/chrome_telemetry_build/android_browser_types.py b/tools/perf/chrome_telemetry_build/android_browser_types.py
new file mode 100644
index 0000000..c066588
--- /dev/null
+++ b/tools/perf/chrome_telemetry_build/android_browser_types.py
@@ -0,0 +1,45 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import sys
+
+# This file should be kept in sync with android_browser_types.gni. It provides
+# a list of Android Chromium Telemetry targets for use in Python scripts.
+
+_CHROMIUM_SRC_DIR = os.path.realpath(
+    os.path.join(os.path.dirname(__file__), '..', '..', '..'))
+_CLANK_DIR = os.path.join(_CHROMIUM_SRC_DIR, 'clank')
+_CLANK_LIST_FILEPATH = os.path.join(_CLANK_DIR, 'telemetry_browser_types.py')
+
+TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES = [
+    '_android_chrome',
+    '_android_monochrome',
+    '_android_monochrome_bundle',
+    '_android_weblayer',
+    '_android_webview',
+]
+
+if os.path.exists(_CLANK_LIST_FILEPATH):
+  sys.path.append(_CLANK_DIR)
+  import telemetry_browser_types  # pylint: disable=import-error,wrong-import-position
+  sys.path.remove(_CLANK_DIR)
+  TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES +=\
+      telemetry_browser_types.TELEMETRY_CLANK_BROWSER_TARGET_SUFFIXES
+else:
+  logging.warning(
+      'No Clank checkout detected - falling back to hard-coded list of '
+      'suffixes, which may be out of date')
+  TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES += [
+      '_android_clank_chrome',
+      '_android_clank_monochrome',
+      '_android_clank_monochrome_64_32_bundle',
+      '_android_clank_monochrome_bundle',
+      '_android_clank_trichrome_bundle',
+      '_android_clank_trichrome_webview',
+      '_android_clank_trichrome_webview_bundle',
+      '_android_clank_webview',
+      '_android_clank_webview_bundle',
+  ]
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr.py b/tools/perf/cli_tools/update_wpr/update_wpr.py
index 5c550b6..efb821a 100644
--- a/tools/perf/cli_tools/update_wpr/update_wpr.py
+++ b/tools/perf/cli_tools/update_wpr/update_wpr.py
@@ -342,19 +342,28 @@
         dest.write(line)
         return dest.name
 
+  def _GetTargetFromConfiguration(self, configuration):
+    """Returns the target that should be used for a Pinpoint job."""
+    if configuration == 'android-pixel2-perf':
+      return 'performance_test_suite_android_clank_monochrome_64_32_bundle'
+    elif configuration in ('linux-perf', 'win-10-perf',
+                           'mac-10_12_laptop_low_end-perf'):
+      return 'performance_test_suite'
+    raise RuntimeError('Unknown configuration %s' % configuration)
+
   def _StartPinpointJob(self, configuration):
     """Creates, starts a Pinpoint job and returns its URL."""
     try:
       resp = pinpoint_service.NewJob(
           base_git_hash='HEAD',
-          target='performance_test_suite',
+          target=self._GetTargetFromConfiguration(configuration),
           patch=self._GetBranchIssueUrl(),
           bug_id=self.bug_id or '',
           story=self.story,
           extra_test_args='--pageset-repeat=%d' % self.repeat,
           configuration=configuration,
-          benchmark='system_health.common_%s' % (
-            'desktop' if self._IsDesktop() else 'mobile'))
+          benchmark='system_health.common_%s' %
+          ('desktop' if self._IsDesktop() else 'mobile'))
     except request.RequestError as e:
       cli_helpers.Comment(
           'Failed to start a Pinpoint job for {config} automatically:\n {err}',
diff --git a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py
index a289965..639e6dc9 100644
--- a/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py
+++ b/tools/perf/cli_tools/update_wpr/update_wpr_unittest.py
@@ -378,12 +378,15 @@
         benchmark='system_health.common_desktop')
     self.assertEqual(new_job.call_count, 3)
 
+  @mock.patch(WPR_UPDATER + 'WprUpdater._GetTargetFromConfiguration',
+              return_value='performance_test_suite')
   @mock.patch(WPR_UPDATER + 'WprUpdater._GetBranchIssueUrl',
               return_value='<issue-url>')
   @mock.patch('core.services.pinpoint_service.NewJob',
               side_effect=request.ServerError(
                   mock.Mock(), mock.Mock(status=500), ''))
-  def testStartPinPointJobsMobileFail(self, new_job, get_branch_issue_url):
+  def testStartPinPointJobsMobileFail(self, new_job, get_branch_issue_url,
+                                      get_target):
     del get_branch_issue_url  # Unused.
     self.wpr_updater.device_id = '<serial>'
     self.assertEqual(
@@ -397,6 +400,15 @@
         extra_test_args='--pageset-repeat=1',
         configuration='<config>',
         benchmark='system_health.common_mobile')
+    get_target.assert_called_once_with('<config>')
+
+  @mock.patch('core.services.pinpoint_service.NewJob',
+              side_effect=request.ServerError(mock.Mock(),
+                                              mock.Mock(status=500), ''))
+  def testStartPinpointJobsInvalidConfig(self, new_job):
+    with self.assertRaises(RuntimeError):
+      self.wpr_updater.StartPinpointJobs(['<config>'])
+    new_job.assert_not_called()
 
 
 if __name__ == "__main__":
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index ea978cb..0e5fe4a 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -27,6 +27,7 @@
 import tempfile
 import textwrap
 
+from chrome_telemetry_build import android_browser_types
 from core import benchmark_finders
 from core import benchmark_utils
 from core import bot_platforms
@@ -127,9 +128,11 @@
     },
     'android-pixel2-perf-calibration': {
         'tests': [{
-            'isolate': 'performance_test_suite',
+            'isolate':
+            'performance_test_suite_android_clank_monochrome_64_32_bundle',
         }],
-        'platform': 'android-chrome-64-bundle',
+        'platform':
+        'android-chrome-64-bundle',
         'dimension': {
             'pool': 'chrome.tests.perf',
             'os': 'Android',
@@ -156,7 +159,7 @@
     'android-nexus5x-perf-fyi': {
         'tests': [{
             'isolate':
-            'performance_test_suite',
+            'performance_test_suite_android_clank_chrome',
             'extra_args': [
                 '--output-format=histograms',
                 '--experimental-tbmv3-metrics',
@@ -175,7 +178,7 @@
     'android-pixel2-perf-fyi': {
         'tests': [{
             'isolate':
-            'performance_test_suite',
+            'performance_test_suite_android_clank_chrome',
             'extra_args': [
                 '--output-format=histograms',
                 '--experimental-tbmv3-metrics',
@@ -195,9 +198,11 @@
     },
     'android-pixel2-perf-aab-fyi': {
         'tests': [{
-            'isolate': 'performance_test_suite',
+            'isolate':
+            'performance_test_suite_android_clank_monochrome_bundle',
         }],
-        'platform': 'android-chrome-bundle',
+        'platform':
+        'android-chrome-bundle',
         'dimension': {
             'pool': 'chrome.tests.perf-fyi',
             'os': 'Android',
@@ -539,7 +544,7 @@
     'android-go-perf': {
         'tests': [{
             'name': 'performance_test_suite',
-            'isolate': 'performance_test_suite',
+            'isolate': 'performance_test_suite_android_clank_chrome',
         }],
         'platform':
         'android-chrome',
@@ -567,7 +572,7 @@
     'Android Nexus5 Perf': {
         'tests': [
             {
-                'isolate': 'performance_test_suite',
+                'isolate': 'performance_test_suite_android_chrome',
                 'extra_args': [
                     '--assert-gpu-compositing',
                 ],
@@ -628,9 +633,11 @@
     },
     'android-pixel2-perf': {
         'tests': [{
-            'isolate': 'performance_test_suite',
+            'isolate':
+            'performance_test_suite_android_clank_monochrome_64_32_bundle',
         }],
-        'platform': 'android-chrome-64-bundle',
+        'platform':
+        'android-chrome-64-bundle',
         'dimension': {
             'pool': 'chrome.tests.perf',
             'os': 'Android',
@@ -667,9 +674,11 @@
     },
     'android-pixel4-perf': {
         'tests': [{
-            'isolate': 'performance_test_suite',
+            'isolate':
+            'performance_test_suite_android_clank_trichrome_bundle',
         }],
-        'platform': 'android-trichrome-bundle',
+        'platform':
+        'android-trichrome-bundle',
         'dimension': {
             'pool': 'chrome.tests.perf',
             'os': 'Android',
@@ -680,7 +689,7 @@
     },
     'android-pixel4a_power-perf': {
         'tests': [{
-            'isolate': 'performance_test_suite',
+            'isolate': 'performance_test_suite_android_clank_chrome',
             'extra_args': [
                 '--experimental-tbmv3-metrics',
             ],
@@ -1180,6 +1189,15 @@
 
 TELEMETRY_PERF_BENCHMARKS = _get_telemetry_perf_benchmarks_metadata()
 
+PERFORMANCE_TEST_SUITES = [
+    'performance_test_suite',
+    'performance_test_suite_eve',
+    'performance_webview_test_suite',
+    'performance_weblayer_test_suite',
+]
+for suffix in android_browser_types.TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES:
+  PERFORMANCE_TEST_SUITES.append('performance_test_suite' + suffix)
+
 
 def get_scheduled_non_telemetry_benchmarks(perf_waterfall_file):
   test_names = set()
@@ -1199,9 +1217,7 @@
     # TODO(eyaich): Determine new way to generate ownership based
     # on the benchmark bot map instead of on the generated tests
     # for new perf recipe.
-    if not name in ('performance_test_suite', 'performance_test_suite_eve',
-                    'performance_webview_test_suite',
-                    'performance_weblayer_test_suite'):
+    if not name in PERFORMANCE_TEST_SUITES:
       test_names.add(name)
 
   for platform in bot_platforms.ALL_PLATFORMS:
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py
index 12faa15f..b5d6d49 100644
--- a/tools/perf/core/perf_json_config_validator.py
+++ b/tools/perf/core/perf_json_config_validator.py
@@ -6,6 +6,7 @@
 import os
 import json
 
+from chrome_telemetry_build import android_browser_types
 from core import path_util
 from core import bot_platforms
 
@@ -41,6 +42,14 @@
     'android-webview-trichrome-google-bundle',
 }
 
+_PERFORMANCE_TEST_SUITES = {
+    'performance_test_suite',
+    'performance_test_suite_eve',
+    'performance_webview_test_suite',
+}
+for suffix in android_browser_types.TELEMETRY_ANDROID_BROWSER_TARGET_SUFFIXES:
+  _PERFORMANCE_TEST_SUITES.add('performance_test_suite' + suffix)
+
 
 def _ValidateSwarmingDimension(builder_name, swarming_dimensions):
   for dimension in swarming_dimensions:
@@ -144,21 +153,16 @@
     _ValidateSwarmingDimension(
         builder_name,
         swarming_dimensions=test_config['swarming'].get('dimension_sets', {}))
-    if (test_config['isolate_name'] in ('performance_test_suite',
-                                        'performance_test_suite_eve',
-                                        'performance_webview_test_suite')):
+    if test_config['isolate_name'] in _PERFORMANCE_TEST_SUITES:
       _ValidateShardingData(builder_name, test_config)
       _ValidateBrowserType(builder_name, test_config)
 
-  if ('performance_test_suite' in test_names or
-      'performance_webview_test_suite' in test_names):
-    if test_names[-1] not in ('performance_test_suite',
-                              'performance_webview_test_suite'):
+  if any(suite in test_names for suite in _PERFORMANCE_TEST_SUITES):
+    if test_names[-1] not in _PERFORMANCE_TEST_SUITES:
       raise ValueError(
-          'performance_test_suite or performance_webview_test_suite must run '
-          'at the end of builder %s to avoid starving other test step '
-          '(see crbug.com/873389). Instead found %s' % (
-            repr(builder_name), test_names[-1]))
+          'performance_test_suite-based targets must run at the end of builder '
+          '%s to avoid starving other test step (see crbug.com/873389). '
+          'Instead found %s' % (repr(builder_name), test_names[-1]))
 
 
 
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 38eefaf..2a4ad882 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -2,15 +2,15 @@
     "trace_processor_shell": {
         "win": {
             "hash": "711c1ef1d13ae18e0dc950a11774deb2bf03fab7",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/162fe0e78f24ee73d5ac38f81680b2ebb03f63d1/trace_processor_shell.exe"
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/7b7e355d04c3b5f759e8dfd3352b550a6ec1a0a7/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "9553d226a4780c049c31e0a71e526051f7e26bc2",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/137ce0e99b24902b52a900f5a47970d14b627dd1/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/7b7e355d04c3b5f759e8dfd3352b550a6ec1a0a7/trace_processor_shell"
         },
         "linux": {
-            "hash": "8184e149b615d87ed64ce5877e86e2724d7ccbdf",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/137ce0e99b24902b52a900f5a47970d14b627dd1/trace_processor_shell"
+            "hash": "c195fdc1f83e98b2ed5b6ce67a1e5b1f1bcc0082",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/97facadd961825cf2b6eb12398e0908a102d0c4a/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 115321b0..2d057b1 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -52,7 +52,7 @@
  <item id="chrome_cart_get_discounted_link" added_in_milestone="92" hash_code="58596544" type="0" content_hash_code="86139104" os_list="linux,windows" file_path="chrome/browser/cart/cart_discount_link_fetcher.cc"/>
  <item id="chrome_cleaner" added_in_milestone="63" hash_code="27071967" type="0" content_hash_code="111240292" os_list="windows" file_path="chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc"/>
  <item id="chrome_cleanup_report" added_in_milestone="70" hash_code="71102679" type="0" content_hash_code="130565656" os_list="windows" file_path="chrome/chrome_cleaner/logging/cleaner_logging_service.cc"/>
- <item id="chrome_feedback_report_app" added_in_milestone="62" hash_code="134729048" type="0" content_hash_code="73916972" os_list="linux,windows" file_path="components/feedback/feedback_uploader.cc"/>
+ <item id="chrome_feedback_report_app" added_in_milestone="62" hash_code="134729048" type="0" content_hash_code="79660618" os_list="linux,windows" file_path="components/feedback/feedback_uploader.cc"/>
  <item id="chrome_variations_service" added_in_milestone="62" hash_code="115188287" type="0" content_hash_code="16094337" os_list="linux,windows" file_path="components/variations/service/variations_service.cc"/>
  <item id="client_download_request" added_in_milestone="62" hash_code="125522256" type="0" content_hash_code="79464901" os_list="linux,windows" file_path="chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc"/>
  <item id="cloud_print" added_in_milestone="65" hash_code="111712433" type="2" content_hash_code="60926140" os_list="linux,windows" semantics_fields="1,5" policy_fields="-1,3,4" file_path="chrome/service/cloud_print/cloud_print_url_fetcher.cc"/>
diff --git a/tools/typescript/definitions/chrome_downloads.d.ts b/tools/typescript/definitions/chrome_downloads.d.ts
new file mode 100644
index 0000000..cb960023
--- /dev/null
+++ b/tools/typescript/definitions/chrome_downloads.d.ts
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Definitions for chrome.downloads API */
+
+declare namespace chrome {
+  export namespace downloads {
+    function getFileIcon(downloadId: number, resolve: (data: string) => void):
+        void;
+  }
+}
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 76a29e7..86efa989 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -250,6 +250,7 @@
     "platform/inspect/ax_inspect_scenario_unittest.cc",
     "platform/inspect/ax_inspect_utils_unittest.cc",
     "platform/inspect/ax_property_node_unittest.cc",
+    "platform/inspect/ax_script_instruction_unittest.cc",
     "run_all_unittests.cc",
   ]
 
diff --git a/ui/accessibility/ax_tree_manager_map.cc b/ui/accessibility/ax_tree_manager_map.cc
index 1ff8f76..1a8f999 100644
--- a/ui/accessibility/ax_tree_manager_map.cc
+++ b/ui/accessibility/ax_tree_manager_map.cc
@@ -5,6 +5,7 @@
 #include "ui/accessibility/ax_tree_manager_map.h"
 
 #include "base/containers/contains.h"
+#include "base/no_destructor.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 
 namespace ui {
diff --git a/ui/accessibility/ax_tree_manager_map.h b/ui/accessibility/ax_tree_manager_map.h
index 6efd33d..a400ebf 100644
--- a/ui/accessibility/ax_tree_manager_map.h
+++ b/ui/accessibility/ax_tree_manager_map.h
@@ -8,7 +8,6 @@
 #include <unordered_map>
 
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "ui/accessibility/ax_tree_id.h"
 #include "ui/accessibility/ax_tree_manager.h"
 
diff --git a/ui/accessibility/platform/BUILD.gn b/ui/accessibility/platform/BUILD.gn
index 277ea0b3..69a0354 100644
--- a/ui/accessibility/platform/BUILD.gn
+++ b/ui/accessibility/platform/BUILD.gn
@@ -69,6 +69,8 @@
     "inspect/ax_inspect_utils.h",
     "inspect/ax_property_node.cc",
     "inspect/ax_property_node.h",
+    "inspect/ax_script_instruction.cc",
+    "inspect/ax_script_instruction.h",
     "inspect/ax_tree_formatter.cc",
     "inspect/ax_tree_formatter.h",
     "inspect/ax_tree_formatter_base.cc",
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index c727ff3..7759e9b3 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -2099,6 +2099,7 @@
   r -= r.OffsetFromOrigin();
 
   AXActionData action_data;
+  action_data.action = ax::mojom::Action::kScrollToMakeVisible;
   action_data.target_node_id = GetData().id;
   action_data.target_rect = r;
   action_data.horizontal_scroll_alignment =
diff --git a/ui/accessibility/platform/inspect/ax_inspect_scenario.cc b/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
index 1ea150f5..eb796dc 100644
--- a/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
+++ b/ui/accessibility/platform/inspect/ax_inspect_scenario.cc
@@ -9,6 +9,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "ui/accessibility/platform/inspect/ax_inspect.h"
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
 
 namespace ui {
 
@@ -116,7 +117,7 @@
       property_filters.emplace_back(value, AXPropertyFilter::DENY);
       break;
     case kScript:
-      property_filters.emplace_back(value, AXPropertyFilter::SCRIPT);
+      script_instructions.emplace_back(value);
       break;
     case kNodeFilter: {
       const auto& parts = base::SplitString(value, "=", base::TRIM_WHITESPACE,
diff --git a/ui/accessibility/platform/inspect/ax_inspect_scenario.h b/ui/accessibility/platform/inspect/ax_inspect_scenario.h
index 9c807b9..5733b0a 100644
--- a/ui/accessibility/platform/inspect/ax_inspect_scenario.h
+++ b/ui/accessibility/platform/inspect/ax_inspect_scenario.h
@@ -14,6 +14,7 @@
 
 struct AXPropertyFilter;
 struct AXNodeFilter;
+class AXScriptInstruction;
 
 // Describes the test execution flow, which is parsed from a sequence
 // of testing directives (instructions). The testing directives are typically
@@ -81,6 +82,9 @@
   // a formatted tree.
   std::vector<AXNodeFilter> node_filters;
 
+  // Scripting instructions.
+  std::vector<AXScriptInstruction> script_instructions;
+
  private:
   enum Directive {
     // No directive.
diff --git a/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc b/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc
index e6e79b4..788c3840 100644
--- a/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc
+++ b/ui/accessibility/platform/inspect/ax_inspect_scenario_unittest.cc
@@ -7,50 +7,43 @@
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/accessibility/platform/inspect/ax_inspect.h"
+#include "ui/accessibility/platform/inspect/ax_property_node.h"
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
 
 namespace ui {
 
-class AXInspectScenarioTest : public testing::Test {
- public:
-  AXInspectScenarioTest() = default;
-  ~AXInspectScenarioTest() override = default;
-
-  AXInspectScenarioTest(const AXInspectScenarioTest&) = delete;
-  AXInspectScenarioTest& operator=(const AXInspectScenarioTest&) = delete;
-};
-
-TEST_F(AXInspectScenarioTest, NoLoadExpected) {
+TEST(AXInspectScenarioTest, NoLoadExpected) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@NO-LOAD-EXPECTED:broken.jpg"});
   EXPECT_THAT(scenario.no_load_expected, testing::ElementsAre("broken.jpg"));
 }
 
-TEST_F(AXInspectScenarioTest, WaitFor) {
+TEST(AXInspectScenarioTest, WaitFor) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@WAIT-FOR:(0, 50"});
   EXPECT_THAT(scenario.wait_for, testing::ElementsAre("(0, 50"));
 }
 
-TEST_F(AXInspectScenarioTest, DefaultActionOn) {
+TEST(AXInspectScenarioTest, DefaultActionOn) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@DEFAULT-ACTION-ON:Show time picker"});
   EXPECT_THAT(scenario.default_action_on,
               testing::ElementsAre("Show time picker"));
 }
 
-TEST_F(AXInspectScenarioTest, ExecuteAndWaitFor) {
+TEST(AXInspectScenarioTest, ExecuteAndWaitFor) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@EXECUTE-AND-WAIT-FOR:open_modal()"});
   EXPECT_THAT(scenario.execute, testing::ElementsAre("open_modal()"));
 }
 
-TEST_F(AXInspectScenarioTest, RunUntil) {
+TEST(AXInspectScenarioTest, RunUntil) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@MAC-RUN-UNTIL-EVENT:AXRowCollapsed"});
   EXPECT_THAT(scenario.run_until, testing::ElementsAre("AXRowCollapsed"));
 }
 
-TEST_F(AXInspectScenarioTest, PropertyFilters) {
+TEST(AXInspectScenarioTest, PropertyFilters) {
   AXInspectScenario scenario = AXInspectScenario::From(
       "@MAC", {"@MAC-ALLOW:AXRoleDescription", "@MAC-ALLOW-EMPTY:AXARIALive",
                "@MAC-DENY:AXTitle"});
@@ -63,7 +56,7 @@
   EXPECT_EQ(scenario.property_filters[2].match_str, "AXTitle");
 }
 
-TEST_F(AXInspectScenarioTest, PropertyFilters_Multiline) {
+TEST(AXInspectScenarioTest, PropertyFilters_Multiline) {
   AXInspectScenario scenario = AXInspectScenario::From(
       "@MAC", {"@MAC-ALLOW:", "  AXRoleDescription", "  AXARIALive"});
   EXPECT_EQ(scenario.property_filters.size(), 2U);
@@ -73,7 +66,7 @@
   EXPECT_EQ(scenario.property_filters[1].match_str, "AXARIALive");
 }
 
-TEST_F(AXInspectScenarioTest, NodeFilters) {
+TEST(AXInspectScenarioTest, NodeFilters) {
   AXInspectScenario scenario =
       AXInspectScenario::From("@MAC", {"@MAC-DENY-NODE:AXRole=AXCheckBox"});
   EXPECT_EQ(scenario.node_filters.size(), 1U);
@@ -81,4 +74,21 @@
   EXPECT_EQ(scenario.node_filters[0].pattern, "AXCheckBox");
 }
 
+TEST(AXInspectScenarioTest, Script) {
+  std::vector<std::string> lines(
+      {"@MAC-SCRIPT:",
+       "  text_range:= textarea.AXTextMarkerRangeForUIElement(textarea)",
+       "  textarea.AXSelectedTextMarkerRange(text_range)",
+       "  wait for AXSelectedTextChanged", "textarea.AXSelectedText"});
+  AXInspectScenario scenario = AXInspectScenario::From("@MAC", lines);
+  EXPECT_EQ(scenario.script_instructions.size(), 4U);
+  EXPECT_EQ(scenario.script_instructions[0].AsScript().ToString(),
+            "text_range");
+  EXPECT_EQ(scenario.script_instructions[1].AsScript().ToString(),
+            "textarea.AXSelectedTextMarkerRange(text_range)");
+  EXPECT_EQ(scenario.script_instructions[2].AsEvent(), "AXSelectedTextChanged");
+  EXPECT_EQ(scenario.script_instructions[3].AsScript().ToString(),
+            "textarea.AXSelectedText");
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/inspect/ax_script_instruction.cc b/ui/accessibility/platform/inspect/ax_script_instruction.cc
new file mode 100644
index 0000000..2201dcf
--- /dev/null
+++ b/ui/accessibility/platform/inspect/ax_script_instruction.cc
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
+
+#include <cstring>
+
+#include "base/check.h"
+#include "ui/accessibility/platform/inspect/ax_inspect.h"
+#include "ui/accessibility/platform/inspect/ax_property_node.h"
+
+namespace ui {
+
+const char kWaitFor[] = "wait for ";
+const size_t kWaitForLength = sizeof(kWaitFor) / sizeof(kWaitFor[0]) - 1;
+
+AXScriptInstruction::AXScriptInstruction(const std::string& instruction)
+    : instruction_(instruction) {}
+
+bool AXScriptInstruction::IsEvent() const {
+  return EventNameStartIndex() != std::string::npos;
+}
+bool AXScriptInstruction::IsScript() const {
+  return !IsEvent();
+}
+
+AXPropertyNode AXScriptInstruction::AsScript() const {
+  DCHECK(!IsEvent());
+  return AXPropertyNode::From({instruction_, AXPropertyFilter::SCRIPT});
+}
+
+std::string AXScriptInstruction::AsEvent() const {
+  DCHECK(IsEvent());
+  return instruction_.substr(kWaitForLength);
+}
+
+size_t AXScriptInstruction::EventNameStartIndex() const {
+  return instruction_.find(kWaitFor);
+}
+
+}  // namespace ui
diff --git a/ui/accessibility/platform/inspect/ax_script_instruction.h b/ui/accessibility/platform/inspect/ax_script_instruction.h
new file mode 100644
index 0000000..df721c4
--- /dev/null
+++ b/ui/accessibility/platform/inspect/ax_script_instruction.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_SCRIPT_INSTRUCTION_H_
+#define UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_SCRIPT_INSTRUCTION_H_
+
+#include <string>
+
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+class AXPropertyNode;
+
+// A single script instruction. See AXInspectScenario.
+// Note: this is only for executing tests or for running a script via
+// ax_dump_tree/ax_dump_events for inspecting from out of process.
+class AX_EXPORT AXScriptInstruction final {
+ public:
+  explicit AXScriptInstruction(const std::string& instruction);
+
+  bool IsEvent() const;
+  bool IsScript() const;
+  AXPropertyNode AsScript() const;
+  std::string AsEvent() const;
+
+ private:
+  size_t EventNameStartIndex() const;
+  std::string instruction_;
+};
+
+}  // namespace ui
+
+#endif  // UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_SCRIPT_INSTRUCTION_H_
diff --git a/ui/accessibility/platform/inspect/ax_script_instruction_unittest.cc b/ui/accessibility/platform/inspect/ax_script_instruction_unittest.cc
new file mode 100644
index 0000000..2e9534d
--- /dev/null
+++ b/ui/accessibility/platform/inspect/ax_script_instruction_unittest.cc
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/inspect/ax_script_instruction.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/platform/inspect/ax_property_node.h"
+
+namespace ui {
+
+TEST(AXScriptInstructionTest, Parse) {
+  AXScriptInstruction script("textbox.AXRole");
+  EXPECT_TRUE(script.IsScript());
+  EXPECT_FALSE(script.IsEvent());
+  EXPECT_EQ(script.AsScript().ToString(), "textbox.AXRole");
+
+  AXScriptInstruction event("wait for AXTitleChange");
+  EXPECT_TRUE(event.IsEvent());
+  EXPECT_FALSE(event.IsScript());
+  EXPECT_EQ(event.AsEvent(), "AXTitleChange");
+
+  AXScriptInstruction event2("wait for AXTitleChange on AXButton");
+  EXPECT_TRUE(event2.IsEvent());
+  EXPECT_FALSE(event2.IsScript());
+  EXPECT_EQ(event2.AsEvent(), "AXTitleChange on AXButton");
+}
+
+}  // namespace ui
diff --git a/ui/accessibility/platform/inspect/ax_tree_formatter.h b/ui/accessibility/platform/inspect/ax_tree_formatter.h
index c4182cfb..ff8e266 100644
--- a/ui/accessibility/platform/inspect/ax_tree_formatter.h
+++ b/ui/accessibility/platform/inspect/ax_tree_formatter.h
@@ -19,6 +19,7 @@
 namespace ui {
 
 class AXNode;
+class AXScriptInstruction;
 class AXTreeID;
 class AXPlatformNodeDelegate;
 
@@ -97,7 +98,14 @@
   // Dumps accessibility tree.
   virtual std::string FormatTree(const base::Value& tree_node) const = 0;
 
-  // Propery filter predefined sets.
+  // Evaluates script instructions between the given indices.
+  virtual std::string EvaluateScript(
+      AXPlatformNodeDelegate* root,
+      const std::vector<AXScriptInstruction>& instructions,
+      size_t start_index,
+      size_t end_index) const = 0;
+
+  // Property filter predefined sets.
   enum PropertyFilterSet {
     // Empty set.
     kFiltersEmptySet,
diff --git a/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc b/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
index 5209fcfd..b7ab72b 100644
--- a/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
+++ b/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc
@@ -28,7 +28,6 @@
 
 // static
 const char AXTreeFormatterBase::kChildrenDictAttr[] = "children";
-const char AXTreeFormatterBase::kScriptsDictAttr[] = "scripts";
 
 bool AXTreeFormatterBase::ShouldDumpNode(
     const AXPlatformNodeDelegate& node) const {
@@ -66,21 +65,7 @@
 
 std::string AXTreeFormatterBase::FormatTree(const base::Value& dict) const {
   std::string contents;
-
-  // Format the tree.
   RecursiveFormatTree(dict, &contents);
-
-  // Format scripts.
-  const base::Value* scripts = dict.FindListKey(kScriptsDictAttr);
-  if (!scripts)
-    return contents;
-
-  for (const base::Value& script : scripts->GetList()) {
-    std::string line;
-    WriteAttribute(true, script.GetString(), &line);
-    contents += line + "\n";
-  }
-
   return contents;
 }
 
@@ -90,6 +75,15 @@
   return base::Value();
 }
 
+std::string AXTreeFormatterBase::EvaluateScript(
+    AXPlatformNodeDelegate* root,
+    const std::vector<AXScriptInstruction>& instructions,
+    size_t start_index,
+    size_t end_index) const {
+  NOTREACHED() << "Not implemented";
+  return {};
+}
+
 void AXTreeFormatterBase::RecursiveFormatTree(const base::Value& dict,
                                               std::string* contents,
                                               int depth) const {
diff --git a/ui/accessibility/platform/inspect/ax_tree_formatter_base.h b/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
index b53da12..781e93b 100644
--- a/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
+++ b/ui/accessibility/platform/inspect/ax_tree_formatter_base.h
@@ -26,18 +26,19 @@
   bool ShouldDumpNode(const AXPlatformNodeDelegate& node) const;
   bool ShouldDumpChildren(const AXPlatformNodeDelegate& node) const;
 
-  // Dumps formatted the given accessibility tree into a string.
-  std::string Format(AXPlatformNodeDelegate* root) const override;
-
-  // Dumps the given accessibility node out as a string.
-  std::string FormatNode(AXPlatformNodeDelegate* node) const override;
-
   // Build an accessibility tree for the current Chrome app.
   virtual base::Value BuildTree(AXPlatformNodeDelegate* root) const = 0;
 
   // AXTreeFormatter overrides.
+  std::string Format(AXPlatformNodeDelegate* root) const override;
+  std::string FormatNode(AXPlatformNodeDelegate* node) const override;
   std::string FormatTree(const base::Value& tree_node) const override;
   base::Value BuildTreeForNode(ui::AXNode* root) const override;
+  std::string EvaluateScript(
+      AXPlatformNodeDelegate* root,
+      const std::vector<AXScriptInstruction>& instructions,
+      size_t start_index,
+      size_t end_index) const override;
   void SetPropertyFilters(const std::vector<AXPropertyFilter>& property_filters,
                           PropertyFilterSet default_filters_set) override;
   void SetNodeFilters(const std::vector<AXNodeFilter>& node_filters) override;
@@ -48,7 +49,6 @@
 
  protected:
   static const char kChildrenDictAttr[];
-  static const char kScriptsDictAttr[];
 
   //
   // Overridden by platform subclasses.
diff --git a/ui/accessibility/platform/uia_registrar_win.cc b/ui/accessibility/platform/uia_registrar_win.cc
index 36463e5..a9940b1f 100644
--- a/ui/accessibility/platform/uia_registrar_win.cc
+++ b/ui/accessibility/platform/uia_registrar_win.cc
@@ -6,6 +6,7 @@
 
 #include <wrl/implements.h>
 
+#include "base/no_destructor.h"
 #include "ui/accessibility/accessibility_features.h"
 
 namespace ui {
diff --git a/ui/accessibility/platform/uia_registrar_win.h b/ui/accessibility/platform/uia_registrar_win.h
index a477ef3..fe53a52 100644
--- a/ui/accessibility/platform/uia_registrar_win.h
+++ b/ui/accessibility/platform/uia_registrar_win.h
@@ -7,8 +7,8 @@
 
 #include <objbase.h>
 #include <uiautomation.h>
+
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "ui/accessibility/ax_export.h"
 
 namespace ui {
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index 7743f7c7..2ee52a5 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -16,7 +16,6 @@
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
 #include "base/containers/flat_map.h"
-#include "base/no_destructor.h"
 #include "base/process/process.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
diff --git a/ui/base/data_transfer_policy/OWNERS b/ui/base/data_transfer_policy/OWNERS
index ed5b6d0..c68ffbf 100644
--- a/ui/base/data_transfer_policy/OWNERS
+++ b/ui/base/data_transfer_policy/OWNERS
@@ -2,4 +2,5 @@
 ayaelattar@chromium.org
 
 # Secondary:
-huangdarwin@chromium.org
+mek@chromium.org
+pwnall@chromium.org
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index e18dd34..2ecaac5 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -62,6 +62,9 @@
 
 #if defined(OS_WIN)
 #include "ui/display/win/dpi.h"
+
+// To avoid conflicts with the macro from the Windows SDK...
+#undef LoadBitmap
 #endif
 
 namespace ui {
diff --git a/ui/base/x/x11_gl_egl_utility.cc b/ui/base/x/x11_gl_egl_utility.cc
index 8464e44..624c6f9 100644
--- a/ui/base/x/x11_gl_egl_utility.cc
+++ b/ui/base/x/x11_gl_egl_utility.cc
@@ -39,20 +39,8 @@
 
 void GetPlatformExtraDisplayAttribs(EGLenum platform_type,
                                     std::vector<EGLAttrib>* attributes) {
-  // ANGLE_NULL and SwiftShader backends don't use the visual,
-  // and may run without X11 where we can't get it anyway.
-  if ((platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) &&
-      (std::find(attributes->begin(), attributes->end(),
-                 EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE) ==
-       attributes->end())) {
-    x11::VisualId visual_id;
-    XVisualManager::GetInstance()->ChooseVisualForWindow(
-        true, &visual_id, nullptr, nullptr, nullptr);
-    attributes->push_back(EGL_X11_VISUAL_ID_ANGLE);
-    attributes->push_back(static_cast<EGLAttrib>(visual_id));
-    attributes->push_back(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
-    attributes->push_back(EGL_PLATFORM_X11_EXT);
-  }
+  attributes->push_back(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
+  attributes->push_back(EGL_PLATFORM_X11_EXT);
 }
 
 void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size,
diff --git a/ui/events/chromecast/scroller_unittest.cc b/ui/events/chromecast/scroller_unittest.cc
index d955f318..1ffbd21 100644
--- a/ui/events/chromecast/scroller_unittest.cc
+++ b/ui/events/chromecast/scroller_unittest.cc
@@ -103,15 +103,9 @@
   base::TimeTicks start_time = base::TimeTicks::Now();
 
   // Start a fling and verify initialized values.
-  scroller.Fling(kDefaultStartX,
-                 kDefaultStartY,
-                 kDefaultVelocityX,
-                 kDefaultVelocityY,
-                 INT_MIN,
-                 INT_MAX,
-                 INT_MIN,
-                 INT_MAX,
-                 start_time);
+  scroller.Fling(kDefaultStartX, kDefaultStartY, kDefaultVelocityX,
+                 kDefaultVelocityY, INT_MIN, static_cast<float>(INT_MAX),
+                 INT_MIN, static_cast<float>(INT_MAX), start_time);
 
   EXPECT_EQ(kDefaultStartX, scroller.GetStartX());
   EXPECT_EQ(kDefaultStartY, scroller.GetStartY());
diff --git a/ui/gl/gl_surface_egl_surface_control.cc b/ui/gl/gl_surface_egl_surface_control.cc
index 2c7f88c..7b14cc5 100644
--- a/ui/gl/gl_surface_egl_surface_control.cc
+++ b/ui/gl/gl_surface_egl_surface_control.cc
@@ -243,10 +243,15 @@
   DCHECK_LE(pending_surfaces_count_, surface_list_.size());
   for (size_t i = pending_surfaces_count_; i < surface_list_.size(); ++i) {
     auto& surface_state = surface_list_[i];
-    pending_transaction_->SetBuffer(*surface_state.surface, nullptr,
-                                    base::ScopedFD());
-    pending_transaction_->SetVisibility(*surface_state.surface, false);
-    surface_state.visibility = false;
+    if (surface_state.hardware_buffer) {
+      pending_transaction_->SetBuffer(*surface_state.surface, nullptr,
+                                      base::ScopedFD());
+      surface_state.hardware_buffer = nullptr;
+    }
+    if (surface_state.visibility) {
+      pending_transaction_->SetVisibility(*surface_state.surface, false);
+      surface_state.visibility = false;
+    }
   }
 
   // TODO(khushalsagar): Consider using the SetDamageRect API for partial
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 6e4dd559..19405d461 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -215,7 +215,7 @@
 // is large enough and allows DWM to consider the main backbuffer as an
 // an overlay candidate.
 const base::Feature kDirectCompositionForceFullDamage{
-    "DirectCompositionForceFullDamage", base::FEATURE_ENABLED_BY_DEFAULT};
+    "DirectCompositionForceFullDamage", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Use presentation feedback event queries (must be enabled) to limit latency.
 const base::Feature kDirectCompositionLowLatencyPresentation{
diff --git a/ui/ozone/common/egl_util.cc b/ui/ozone/common/egl_util.cc
index 9b322cd..a630e18 100644
--- a/ui/ozone/common/egl_util.cc
+++ b/ui/ozone/common/egl_util.cc
@@ -136,6 +136,8 @@
       FILE_PATH_LITERAL("egltrace.so");
   base::NativeLibrary trace_library =
       base::LoadNativeLibrary(base::FilePath(kDefaultTraceSoname), &error);
+  if (!trace_library)
+    LOG(ERROR) << error.ToString();
   gl::AddGLNativeLibrary(trace_library);
 #endif
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 315d7455..9929ffc 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -119,7 +119,6 @@
     "controls/button/menu_button_controller.h",
     "controls/button/radio_button.h",
     "controls/button/toggle_button.h",
-    "controls/color_tracking_icon_view.h",
     "controls/combobox/combobox.h",
     "controls/combobox/combobox_util.h",
     "controls/dot_indicator.h",
@@ -339,7 +338,6 @@
     "controls/button/menu_button_controller.cc",
     "controls/button/radio_button.cc",
     "controls/button/toggle_button.cc",
-    "controls/color_tracking_icon_view.cc",
     "controls/combobox/combobox.cc",
     "controls/combobox/combobox_util.cc",
     "controls/combobox/empty_combobox_model.cc",
diff --git a/ui/views/accessibility/widget_ax_tree_id_map.cc b/ui/views/accessibility/widget_ax_tree_id_map.cc
index 617b771..f1ba26c 100644
--- a/ui/views/accessibility/widget_ax_tree_id_map.cc
+++ b/ui/views/accessibility/widget_ax_tree_id_map.cc
@@ -5,6 +5,7 @@
 #include "ui/views/accessibility/widget_ax_tree_id_map.h"
 
 #include "base/containers/contains.h"
+#include "base/no_destructor.h"
 
 namespace views {
 
diff --git a/ui/views/accessibility/widget_ax_tree_id_map.h b/ui/views/accessibility/widget_ax_tree_id_map.h
index cdb6e00..454cdd2c 100644
--- a/ui/views/accessibility/widget_ax_tree_id_map.h
+++ b/ui/views/accessibility/widget_ax_tree_id_map.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/no_destructor.h"
 #include "ui/accessibility/ax_tree_id.h"
 #include "ui/accessibility/ax_tree_manager.h"
 #include "ui/views/views_export.h"
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc
index 225f1f0..5b651165 100644
--- a/ui/views/bubble/bubble_border.cc
+++ b/ui/views/bubble/bubble_border.cc
@@ -38,6 +38,20 @@
 // key the cache.
 using ShadowCacheKey = std::tuple<int, SkColor>;
 
+enum class BubbleArrowSide { kLeft, kRight, kTop, kBottom };
+
+BubbleArrowSide GetBubbleArrowSide(BubbleBorder::Arrow arrow) {
+  DCHECK(BubbleBorder::has_arrow(arrow));
+  // Note: VERTICAL arrows are on the sides of the bubble, while !VERTICAL are
+  // on the top or bottom.
+  if (arrow & BubbleBorder::VERTICAL) {
+    return (arrow & BubbleBorder::RIGHT) ? BubbleArrowSide::kRight
+                                         : BubbleArrowSide::kLeft;
+  }
+  return (arrow & BubbleBorder::BOTTOM) ? BubbleArrowSide::kBottom
+                                        : BubbleArrowSide::kTop;
+}
+
 // Utility functions for getting alignment points on the edge of a rectangle.
 gfx::Point CenterTop(const gfx::Rect& rect) {
   return gfx::Point(rect.CenterPoint().x(), rect.y());
@@ -95,18 +109,19 @@
                                            BubbleBorder::kVisibleArrowLength
                                      : BubbleBorder::kVisibleArrowLength;
   gfx::Insets result;
-  // Note: VERTICAL arrows are on the sides of the bubble, while !VERTICAL are
-  // on the top or bottom.
-  if (arrow & BubbleBorder::VERTICAL) {
-    if (arrow & BubbleBorder::RIGHT)
+  switch (GetBubbleArrowSide(arrow)) {
+    case BubbleArrowSide::kRight:
       result.set_right(arrow_size);
-    else
+      break;
+    case BubbleArrowSide::kLeft:
       result.set_left(arrow_size);
-  } else {
-    if (arrow & BubbleBorder::BOTTOM)
-      result.set_bottom(arrow_size);
-    else
+      break;
+    case BubbleArrowSide::kTop:
       result.set_top(arrow_size);
+      break;
+    case BubbleArrowSide::kBottom:
+      result.set_bottom(arrow_size);
+      break;
   }
   return result;
 }
@@ -116,34 +131,37 @@
 SkPath GetVisibleArrowPath(BubbleBorder::Arrow arrow,
                            const gfx::Rect& bounds,
                            BubbleArrowPart part) {
+  constexpr size_t kNumPoints = 3;
   gfx::RectF bounds_f(bounds);
-  SkPoint point1, point2, point3;
-  if (arrow & BubbleBorder::VERTICAL) {
-    if (arrow & BubbleBorder::RIGHT) {
-      point1 = {bounds_f.x(), bounds_f.y()};
-      point2 = {bounds_f.right(),
-                bounds_f.y() + BubbleBorder::kVisibleArrowRadius};
-      point3 = {bounds_f.x(), bounds_f.bottom()};
-    } else {
-      point1 = {bounds_f.right(), bounds_f.bottom()};
-      point2 = {bounds_f.x(), bounds_f.y() + BubbleBorder::kVisibleArrowRadius};
-      point3 = {bounds_f.right(), bounds_f.y()};
-    }
-  } else {
-    if (arrow & BubbleBorder::BOTTOM) {
-      point1 = {bounds_f.right(), bounds_f.y()};
-      point2 = {bounds_f.x() + BubbleBorder::kVisibleArrowRadius,
-                bounds_f.bottom()};
-      point3 = {bounds_f.x(), bounds_f.y()};
-    } else {
-      point1 = {bounds_f.x(), bounds_f.bottom()};
-      point2 = {bounds_f.x() + BubbleBorder::kVisibleArrowRadius, bounds_f.y()};
-      point3 = {bounds_f.right(), bounds_f.bottom()};
-    }
+  SkPoint points[kNumPoints];
+  switch (GetBubbleArrowSide(arrow)) {
+    case BubbleArrowSide::kRight:
+      points[0] = {bounds_f.x(), bounds_f.y()};
+      points[1] = {bounds_f.right(),
+                   bounds_f.y() + BubbleBorder::kVisibleArrowRadius};
+      points[2] = {bounds_f.x(), bounds_f.bottom()};
+      break;
+    case BubbleArrowSide::kLeft:
+      points[0] = {bounds_f.right(), bounds_f.bottom()};
+      points[1] = {bounds_f.x(),
+                   bounds_f.y() + BubbleBorder::kVisibleArrowRadius};
+      points[2] = {bounds_f.right(), bounds_f.y()};
+      break;
+    case BubbleArrowSide::kTop:
+      points[0] = {bounds_f.x(), bounds_f.bottom()};
+      points[1] = {bounds_f.x() + BubbleBorder::kVisibleArrowRadius,
+                   bounds_f.y()};
+      points[2] = {bounds_f.right(), bounds_f.bottom()};
+      break;
+    case BubbleArrowSide::kBottom:
+      points[0] = {bounds_f.right(), bounds_f.y()};
+      points[1] = {bounds_f.x() + BubbleBorder::kVisibleArrowRadius,
+                   bounds_f.bottom()};
+      points[2] = {bounds_f.x(), bounds_f.y()};
+      break;
   }
 
-  return SkPath::Polygon({point1, point2, point3},
-                         part == BubbleArrowPart::kFill);
+  return SkPath::Polygon(points, kNumPoints, part == BubbleArrowPart::kFill);
 }
 
 const gfx::ShadowValues& GetShadowValues(const ui::NativeTheme* theme,
@@ -601,21 +619,36 @@
   gfx::Point arrow_origin = visible_arrow_rect_.origin();
   View::ConvertPointFromScreen(&view, &arrow_origin);
   const gfx::Rect arrow_bounds(arrow_origin, visible_arrow_rect_.size());
+
+  // Clip the canvas to a box that's big enough to hold the shadow in every
+  // dimension but won't overlap the bubble itself.
+  gfx::ScopedCanvas scoped(canvas);
+  gfx::Rect clip_rect = arrow_bounds;
+  const BubbleArrowSide side = GetBubbleArrowSide(arrow_);
+  clip_rect.Inset(side == BubbleArrowSide::kRight ? 0 : -2,
+                  side == BubbleArrowSide::kBottom ? 0 : -2,
+                  side == BubbleArrowSide::kLeft ? 0 : -2,
+                  side == BubbleArrowSide::kTop ? 0 : -2);
+  canvas->ClipRect(clip_rect);
+
   cc::PaintFlags flags;
-  flags.setColor(background_color());
-  flags.setStyle(cc::PaintFlags::kFill_Style);
-  flags.setAntiAlias(true);
-  canvas->DrawPath(
-      GetVisibleArrowPath(arrow_, arrow_bounds, BubbleArrowPart::kFill), flags);
-  SkColor kBorderColor = view.GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_BubbleBorderWhenShadowPresent);
-  flags.setColor(kBorderColor);
-  flags.setStyle(cc::PaintFlags::kStroke_Style);
   flags.setStrokeCap(cc::PaintFlags::kRound_Cap);
-  flags.setStrokeWidth(1.3);
+
+  flags.setColor(view.GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_BubbleBorderWhenShadowPresent));
+  flags.setStyle(cc::PaintFlags::kStroke_Style);
+  flags.setStrokeWidth(1.2);
+  flags.setAntiAlias(true);
   canvas->DrawPath(
       GetVisibleArrowPath(arrow_, arrow_bounds, BubbleArrowPart::kBorder),
       flags);
+
+  flags.setColor(background_color());
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setStrokeWidth(1.0);
+  flags.setAntiAlias(true);
+  canvas->DrawPath(
+      GetVisibleArrowPath(arrow_, arrow_bounds, BubbleArrowPart::kFill), flags);
 }
 
 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
diff --git a/ui/views/bubble/bubble_border.h b/ui/views/bubble/bubble_border.h
index df15b19..5aa07e11 100644
--- a/ui/views/bubble/bubble_border.h
+++ b/ui/views/bubble/bubble_border.h
@@ -90,7 +90,7 @@
   static constexpr int kShadowVerticalOffset = 2;
 
   // Space between the anchor view and a visible arrow if one is present.
-  static constexpr int kVisibleArrowGap = 2;
+  static constexpr int kVisibleArrowGap = 1;
 
   // Length of the visible arrow (distance from the bubble to the tip of the
   // arrow) if one is present.
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc
index 3b48555..205684b 100644
--- a/ui/views/bubble/bubble_dialog_model_host.cc
+++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -223,7 +223,7 @@
 
   // TODO(pbos): Consider refactoring ::SetExtraView() so it can be called after
   // the Widget is created and still be picked up. Moving this to
-  // OnDialogInitialized() will not work until then.
+  // OnWidgetInitialized() will not work until then.
   auto* extra_button = model_->extra_button(GetPassKey());
   if (extra_button) {
     SetExtraView(std::make_unique<MdTextButton>(
@@ -293,7 +293,7 @@
       FindDialogModelHostField(model_->GetFieldByUniqueId(unique_id.value())));
 }
 
-void BubbleDialogModelHost::OnDialogInitialized() {
+void BubbleDialogModelHost::OnWidgetInitialized() {
   // Dialog buttons are added on dialog initialization.
   if (GetOkButton()) {
     AddDialogModelHostFieldForExistingView(
diff --git a/ui/views/bubble/bubble_dialog_model_host.h b/ui/views/bubble/bubble_dialog_model_host.h
index c6da96b..f511bc44f 100644
--- a/ui/views/bubble/bubble_dialog_model_host.h
+++ b/ui/views/bubble/bubble_dialog_model_host.h
@@ -47,7 +47,7 @@
   // TODO(pbos): Populate initparams with initial view instead of overriding
   // GetInitiallyFocusedView().
   View* GetInitiallyFocusedView() override;
-  void OnDialogInitialized() override;
+  void OnWidgetInitialized() override;
 
   // ui::DialogModelHost:
   void Close() override;
diff --git a/ui/views/controls/color_tracking_icon_view.cc b/ui/views/controls/color_tracking_icon_view.cc
deleted file mode 100644
index d7c3ded..0000000
--- a/ui/views/controls/color_tracking_icon_view.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/color_tracking_icon_view.h"
-
-#include "ui/gfx/paint_vector_icon.h"
-
-namespace views {
-
-ColorTrackingIconView::ColorTrackingIconView(
-    const gfx::VectorIcon& icon,
-    int icon_size,
-    ui::NativeTheme::ColorId icon_color_id)
-    : icon_(icon), icon_size_(icon_size), icon_color_id_(icon_color_id) {
-  // Set the image using the color generated from icon_color_id_. This will
-  // allow the ImageView to report its preferred size before OnThemeChanged for
-  // layout purposes.
-  SetImage(gfx::CreateVectorIcon(
-      icon_, icon_size_, GetNativeTheme()->GetSystemColor(icon_color_id_)));
-}
-
-void ColorTrackingIconView::OnThemeChanged() {
-  ImageView::OnThemeChanged();
-  SetImage(gfx::CreateVectorIcon(
-      icon_, icon_size_, GetNativeTheme()->GetSystemColor(icon_color_id_)));
-}
-
-}  // namespace views
diff --git a/ui/views/controls/color_tracking_icon_view.h b/ui/views/controls/color_tracking_icon_view.h
deleted file mode 100644
index 40525f28..0000000
--- a/ui/views/controls/color_tracking_icon_view.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_
-#define UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_
-
-#include "ui/native_theme/native_theme.h"
-#include "ui/views/controls/image_view.h"
-
-namespace gfx {
-struct VectorIcon;
-}
-
-namespace views {
-
-// An ImageView that displays |icon| at |icon_size|. Tracks theme changes so the
-// icon is always the correct color.
-class VIEWS_EXPORT ColorTrackingIconView : public ImageView {
- public:
-  ColorTrackingIconView(const gfx::VectorIcon& icon,
-                        int icon_size,
-                        ui::NativeTheme::ColorId icon_color_id =
-                            ui::NativeTheme::kColorId_DefaultIconColor);
-
-  // ImageView:
-  void OnThemeChanged() override;
-
- private:
-  const gfx::VectorIcon& icon_;
-  const int icon_size_;
-  const ui::NativeTheme::ColorId icon_color_id_;
-};
-
-}  // namespace views
-
-#endif  // UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc
index 43bb863..1c033b5 100644
--- a/ui/views/controls/image_view.cc
+++ b/ui/views/controls/image_view.cc
@@ -33,6 +33,10 @@
 
 ImageView::ImageView() = default;
 
+ImageView::ImageView(const ui::ImageModel& image_model) {
+  SetImage(image_model);
+}
+
 ImageView::~ImageView() = default;
 
 void ImageView::SetImage(const ui::ImageModel& image_model) {
diff --git a/ui/views/controls/image_view.h b/ui/views/controls/image_view.h
index e4a1de26..26c0dac 100644
--- a/ui/views/controls/image_view.h
+++ b/ui/views/controls/image_view.h
@@ -39,6 +39,7 @@
   enum class Alignment { kLeading, kCenter, kTrailing };
 
   ImageView();
+  explicit ImageView(const ui::ImageModel& image_model);
   ~ImageView() override;
 
   // Set the image that should be displayed.
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 818861a..8ba686c 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -1733,16 +1733,19 @@
       return MenuAnchorPosition::kTopRight;
     case MenuAnchorPosition::kTopRight:
       return MenuAnchorPosition::kTopLeft;
-    case MenuAnchorPosition::kBubbleLeft:
-      return MenuAnchorPosition::kBubbleRight;
-    case MenuAnchorPosition::kBubbleRight:
-      return MenuAnchorPosition::kBubbleLeft;
     case MenuAnchorPosition::kBubbleTopLeft:
       return MenuAnchorPosition::kBubbleTopRight;
     case MenuAnchorPosition::kBubbleTopRight:
       return MenuAnchorPosition::kBubbleTopLeft;
+    case MenuAnchorPosition::kBubbleLeft:
+      return MenuAnchorPosition::kBubbleRight;
+    case MenuAnchorPosition::kBubbleRight:
+      return MenuAnchorPosition::kBubbleLeft;
+    case MenuAnchorPosition::kBubbleBottomLeft:
+      return MenuAnchorPosition::kBubbleBottomRight;
+    case MenuAnchorPosition::kBubbleBottomRight:
+      return MenuAnchorPosition::kBubbleBottomLeft;
     case MenuAnchorPosition::kBottomCenter:
-    case MenuAnchorPosition::kBubbleBelow:
       return position;
   }
 }
@@ -2483,166 +2486,121 @@
     menu_size.set_width(std::min(
         menu_size.width(), item->GetDelegate()->GetMaxWidthForMenu(item)));
 
-    if (state_.anchor == MenuAnchorPosition::kBubbleBelow) {
-      // Align the left edges of the menu and anchor.
-      x = std::max(monitor_bounds.x(),
-                   anchor_bounds.x() - border_and_shadow_insets.left());
-      if (x + menu_size.width() > monitor_bounds.right()) {
-        // Align the right of the menu with the right of the anchor.
-        x = anchor_bounds.right() - menu_size.width() +
-            border_and_shadow_insets.right();
-      }
-      // Align the top of the menu with the bottom of the anchor.
-      const int y_for_menu_below = anchor_bounds.bottom() -
-                                   border_and_shadow_insets.top() +
-                                   menu_config.touchable_anchor_offset;
-      // Align the bottom of the menu with the top of the anchor.
-      const int y_for_menu_above = anchor_bounds.y() - menu_size.height() +
-                                   border_and_shadow_insets.bottom() -
-                                   menu_config.touchable_anchor_offset;
+    // Calculate possible coordinates. Do not clamp values; that happens later.
+    int x_menu_on_left = 0;
+    int x_menu_on_right = 0;
+    int y_menu_above = 0;
+    int y_menu_below = 0;
+    switch (state_.anchor) {
+      case MenuAnchorPosition::kBubbleTopLeft:
+      case MenuAnchorPosition::kBubbleTopRight:
+      case MenuAnchorPosition::kBubbleBottomLeft:
+      case MenuAnchorPosition::kBubbleBottomRight:
+        // Align the right edges of the menu and anchor.
+        x_menu_on_left = anchor_bounds.right() - menu_size.width() +
+                         border_and_shadow_insets.right();
+        // Align the left edges of the menu and anchor.
+        x_menu_on_right = anchor_bounds.x() - border_and_shadow_insets.left();
+        // Align the bottom of the menu with the top of the anchor.
+        y_menu_above = anchor_bounds.y() - menu_size.height() +
+                       border_and_shadow_insets.bottom() -
+                       menu_config.touchable_anchor_offset;
+        // Align the top of the menu with the bottom of the anchor.
+        y_menu_below = anchor_bounds.bottom() - border_and_shadow_insets.top() +
+                       menu_config.touchable_anchor_offset;
+        break;
+      case MenuAnchorPosition::kBubbleLeft:
+      case MenuAnchorPosition::kBubbleRight:
+        // Align the right edge of the menu with the left edge of the anchor.
+        x_menu_on_left = anchor_bounds.x() - menu_size.width() +
+                         border_and_shadow_insets.right() -
+                         menu_config.touchable_anchor_offset;
+        // Align the left edge of the menu with the right edge of the anchor.
+        x_menu_on_right = anchor_bounds.right() -
+                          border_and_shadow_insets.left() +
+                          menu_config.touchable_anchor_offset;
+        // Align the bottom of the menu with the bottom of the anchor.
+        y_menu_above = anchor_bounds.bottom() - menu_size.height() +
+                       border_and_shadow_insets.bottom();
+        // Align the top of the menu with the top of the anchor.
+        y_menu_below = anchor_bounds.y() - border_and_shadow_insets.top();
+        break;
+      case MenuAnchorPosition::kTopLeft:
+      case MenuAnchorPosition::kTopRight:
+      case MenuAnchorPosition::kBottomCenter:
+        NOTREACHED();
+    }
 
-        // Respect the previous MenuPosition. The menu contents could change
-        // while the menu is shown, the menu position should not change.
-        const bool able_to_show_menu_below =
-            (y_for_menu_below + menu_size.height() <= monitor_bounds.bottom());
-        const bool able_to_show_menu_above =
-            y_for_menu_above >= monitor_bounds.y();
-        if (item->actual_menu_position() == MenuPosition::kBelowBounds &&
-            able_to_show_menu_below) {
-          y = y_for_menu_below;
-        } else if (item->actual_menu_position() == MenuPosition::kAboveBounds &&
-                   able_to_show_menu_above) {
-          // No room below.
-          y = y_for_menu_above;
-        } else if (able_to_show_menu_below) {
-          // No room above, and no prevailing menu position.
-          y = y_for_menu_below;
+    // Choose the most appropriate x coordinate.
+    switch (state_.anchor) {
+      case MenuAnchorPosition::kBubbleTopLeft:
+      case MenuAnchorPosition::kBubbleLeft:
+      case MenuAnchorPosition::kBubbleBottomLeft:
+        x = x_menu_on_left >= monitor_bounds.x() ? x_menu_on_left
+                                                 : x_menu_on_right;
+        break;
+      case MenuAnchorPosition::kBubbleTopRight:
+      case MenuAnchorPosition::kBubbleRight:
+      case MenuAnchorPosition::kBubbleBottomRight:
+        x = x_menu_on_right + menu_size.width() <= monitor_bounds.right()
+                ? x_menu_on_right
+                : x_menu_on_left;
+        break;
+      case MenuAnchorPosition::kTopLeft:
+      case MenuAnchorPosition::kTopRight:
+      case MenuAnchorPosition::kBottomCenter:
+        NOTREACHED();
+    }
+
+    // Choose the most appropriate y coordinate.
+    const bool able_to_show_menu_below =
+        y_menu_below + menu_size.height() <= monitor_bounds.bottom();
+    const bool able_to_show_menu_above = y_menu_above >= monitor_bounds.y();
+    switch (state_.anchor) {
+      case MenuAnchorPosition::kBubbleLeft:
+      case MenuAnchorPosition::kBubbleRight:
+      case MenuAnchorPosition::kBubbleBottomLeft:
+      case MenuAnchorPosition::kBubbleBottomRight:
+        // Respect the actual menu position calculated earlier if possible, to
+        // prevent changing positions during menu size updates.
+        if (able_to_show_menu_below &&
+            (item->actual_menu_position() != MenuPosition::kAboveBounds ||
+             !able_to_show_menu_above)) {
+          y = y_menu_below;
           item->set_actual_menu_position(MenuPosition::kBelowBounds);
         } else if (able_to_show_menu_above) {
-          // No room below, but there is room above. Show above the anchor.
-          y = y_for_menu_above;
+          y = y_menu_above;
           item->set_actual_menu_position(MenuPosition::kAboveBounds);
         } else {
-          // No room above or below. Show as low as possible. Align the bottom
-          // of the menu with the bottom of the screen.
+          // No room above or below. Show the menu as low as possible.
           y = monitor_bounds.bottom() - menu_size.height();
           item->set_actual_menu_position(MenuPosition::kBestFit);
         }
-    } else if (state_.anchor == MenuAnchorPosition::kBubbleTopLeft ||
-               state_.anchor == MenuAnchorPosition::kBubbleTopRight) {
-      // Align the right of the menu with the right of the anchor.
-      const int x_for_top_left = std::max(
-          monitor_bounds.x(), anchor_bounds.right() - menu_size.width() +
-                                  border_and_shadow_insets.right());
-      // Align the left of the menu with the left of the anchor.
-      const int x_for_top_right =
-          std::min(monitor_bounds.right() - menu_size.width(),
-                   anchor_bounds.x() - border_and_shadow_insets.left());
-      if (state_.anchor == MenuAnchorPosition::kBubbleTopRight) {
-        x = x_for_top_right;
-        if (x + menu_size.width() > monitor_bounds.right())
-          x = x_for_top_left;
-      } else {
-        x = x_for_top_left;
-        if (x < monitor_bounds.x())
-          x = x_for_top_right;
-      }
-
-      // Align the top of the menu with the bottom of the anchor.
-      const int y_for_menu_below = anchor_bounds.bottom() -
-                                   border_and_shadow_insets.top() +
-                                   menu_config.touchable_anchor_offset;
-      // Align the bottom of the menu with the top of the anchor.
-      const int y_for_menu_above = anchor_bounds.y() - menu_size.height() +
-                                   border_and_shadow_insets.bottom() -
-                                   menu_config.touchable_anchor_offset;
-
-      const bool able_to_show_menu_below =
-          (y_for_menu_below + menu_size.height() <= monitor_bounds.bottom());
-      const bool able_to_show_menu_above =
-          (y_for_menu_above >= monitor_bounds.y());
-
-      // Respect the previous MenuPosition. The menu contents could change
-      // while the menu is shown, the menu position should not change.
-      if (item->actual_menu_position() == MenuPosition::kAboveBounds &&
-          able_to_show_menu_above) {
-        y = y_for_menu_above;
-      } else if (item->actual_menu_position() == MenuPosition::kBelowBounds &&
-                 able_to_show_menu_below) {
-        // No room above.
-        y = y_for_menu_below;
-      } else if (able_to_show_menu_above) {
-        // No room below, and no prevailing menu position.
-        y = y_for_menu_above;
-        item->set_actual_menu_position(MenuPosition::kAboveBounds);
-      } else if (able_to_show_menu_below) {
-        // No room above.
-        y = y_for_menu_below;
-        item->set_actual_menu_position(MenuPosition::kBelowBounds);
-      } else {
-        // No room above or below. Show the menu as high as possible.
-        // Align the top of the menu with the top of the screen.
-        y = monitor_bounds.y();
-        item->set_actual_menu_position(MenuPosition::kBestFit);
-      }
-    } else if (state_.anchor == MenuAnchorPosition::kBubbleLeft ||
-               state_.anchor == MenuAnchorPosition::kBubbleRight) {
-      if (state_.anchor == MenuAnchorPosition::kBubbleLeft) {
-        // Align the right of the menu with the left of the anchor.
-        x = anchor_bounds.x() - menu_size.width() +
-            border_and_shadow_insets.right() -
-            menu_config.touchable_anchor_offset;
-        // Align the left of the menu with the right of the anchor.
-        if (x < monitor_bounds.x()) {
-          x = anchor_bounds.right() - border_and_shadow_insets.left() +
-              menu_config.touchable_anchor_offset;
+        break;
+      case MenuAnchorPosition::kBubbleTopLeft:
+      case MenuAnchorPosition::kBubbleTopRight:
+        // Respect the actual menu position calculated earlier if possible, to
+        // prevent changing positions during menu size updates.
+        if (able_to_show_menu_above &&
+            (item->actual_menu_position() != MenuPosition::kBelowBounds ||
+             !able_to_show_menu_below)) {
+          y = y_menu_above;
+          item->set_actual_menu_position(MenuPosition::kAboveBounds);
+        } else if (able_to_show_menu_below) {
+          y = y_menu_below;
+          item->set_actual_menu_position(MenuPosition::kBelowBounds);
+        } else {
+          // No room above or below. Show the menu as high as possible.
+          y = monitor_bounds.y();
+          item->set_actual_menu_position(MenuPosition::kBestFit);
         }
-      } else {
-        // Align the left of the menu with the right of the anchor.
-        x = anchor_bounds.right() - border_and_shadow_insets.left() +
-            menu_config.touchable_anchor_offset;
-        if (x + menu_size.width() > monitor_bounds.right()) {
-          // Align the right of the menu with the left of the anchor.
-          x = anchor_bounds.x() - menu_size.width() +
-              border_and_shadow_insets.right() -
-              menu_config.touchable_anchor_offset;
-        }
-      }
-
-      // Align the top of the menu with the top of the anchor.
-      const int y_for_menu_below =
-          anchor_bounds.y() - border_and_shadow_insets.top();
-      // Align the bottom of the menu with the bottom of the anchor.
-      const int y_for_menu_above = anchor_bounds.bottom() - menu_size.height() +
-                                   border_and_shadow_insets.bottom();
-
-      const bool able_to_show_menu_below =
-          (y_for_menu_below + menu_size.height() <= monitor_bounds.bottom());
-      const bool able_to_show_menu_above =
-          (y_for_menu_above >= monitor_bounds.y());
-
-      // Respect the actual menu position calculated earlier if possible, to
-      // prevent changing positions during menu size updates.
-      if (item->actual_menu_position() == MenuPosition::kBelowBounds &&
-          able_to_show_menu_below) {
-        y = y_for_menu_below;
-      } else if (item->actual_menu_position() == MenuPosition::kAboveBounds &&
-                 able_to_show_menu_above) {
-        y = y_for_menu_above;
-      } else if (able_to_show_menu_below) {
-        // No room below, and no prevailing menu position.
-        y = y_for_menu_below;
-        item->set_actual_menu_position(MenuPosition::kBelowBounds);
-      } else if (able_to_show_menu_above) {
-        // No room below, but there is room above. Show above the anchor.
-        y = y_for_menu_above;
-        item->set_actual_menu_position(MenuPosition::kAboveBounds);
-      } else {
-        // No room above or below. Show as low as possible.
-        y = monitor_bounds.bottom() - menu_size.height();
-        item->set_actual_menu_position(MenuPosition::kBestFit);
-      }
+        break;
+      case MenuAnchorPosition::kTopLeft:
+      case MenuAnchorPosition::kTopRight:
+      case MenuAnchorPosition::kBottomCenter:
+        NOTREACHED();
     }
+
     // The above adjustments may have shifted a large menu off the screen.
     // Clamp the menu origin to the valid range.
     const int x_min = monitor_bounds.x() - border_and_shadow_insets.left();
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 39289858..58b0e7c8 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -1083,10 +1083,11 @@
   }
 }
 
-// Verifies that the context menu bubble position, MenuPosition::kBubbleBelow,
-// does not shift as items are removed. The menu position will shift it items
-// are added and the menu no longer fits in its previous position.
-TEST_F(MenuControllerTest, VerifyMenuBubbleBelowPositionAfterSizeChanges) {
+// Verifies that the context menu bubble position,
+// MenuAnchorPosition::kBubbleBottomRight, does not shift as items are removed.
+// The menu position will shift if items are added and the menu no longer fits
+// in its previous position.
+TEST_F(MenuControllerTest, VerifyContextMenuBubblePositionAfterSizeChanges) {
   constexpr gfx::Rect kMonitorBounds(0, 0, 500, 500);
   constexpr gfx::Size kMenuSize(100, 200);
   const gfx::Insets border_and_shadow_insets =
@@ -1103,7 +1104,7 @@
                                     border_and_shadow_insets.top());
 
   MenuBoundsOptions options;
-  options.menu_anchor = MenuAnchorPosition::kBubbleBelow;
+  options.menu_anchor = MenuAnchorPosition::kBubbleBottomRight;
   options.monitor_bounds = kMonitorBounds;
   options.anchor_bounds = gfx::Rect(anchor_point, gfx::Size());
 
@@ -1145,6 +1146,15 @@
     EXPECT_EQ(MenuItemView::MenuPosition::kAboveBounds,
               menu_item()->ActualMenuPosition());
   }
+
+  // Case 4: There is enough space for the menu below `anchor_point`. The cached
+  // menu position is below the anchor. The menu should show below the anchor.
+  {
+    options.menu_position = MenuItemView::MenuPosition::kBelowBounds;
+    CalculateBubbleMenuBounds(options);
+    EXPECT_EQ(MenuItemView::MenuPosition::kBelowBounds,
+              menu_item()->ActualMenuPosition());
+  }
 }
 
 // Tests that opening the menu and pressing 'Home' selects the first menu item.
@@ -2207,10 +2217,18 @@
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kTopLeft));
   EXPECT_EQ(MenuAnchorPosition::kTopRight,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kTopRight));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleTopLeft,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleTopLeft));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleTopRight,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleTopRight));
   EXPECT_EQ(MenuAnchorPosition::kBubbleLeft,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleLeft));
   EXPECT_EQ(MenuAnchorPosition::kBubbleRight,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleRight));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleBottomLeft,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleBottomLeft));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleBottomRight,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleBottomRight));
 
   base::i18n::SetRTLForTesting(true);
 
@@ -2219,10 +2237,18 @@
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kTopRight));
   EXPECT_EQ(MenuAnchorPosition::kTopRight,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kTopLeft));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleTopLeft,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleTopRight));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleTopRight,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleTopLeft));
   EXPECT_EQ(MenuAnchorPosition::kBubbleLeft,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleRight));
   EXPECT_EQ(MenuAnchorPosition::kBubbleRight,
             AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleLeft));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleBottomLeft,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleBottomRight));
+  EXPECT_EQ(MenuAnchorPosition::kBubbleBottomRight,
+            AdjustAnchorPositionForRtl(MenuAnchorPosition::kBubbleBottomLeft));
 
   base::i18n::SetRTLForTesting(false);
 }
@@ -2259,7 +2285,7 @@
 TEST_P(MenuControllerTest, TestMenuFitsOnScreen) {
   const int display_size = 500;
   // Simulate multiple display layouts.
-  for (int x = -1; x <= 1; x++)
+  for (int x = -1; x <= 1; x++) {
     for (int y = -1; y <= 1; y++) {
       const gfx::Rect monitor_bounds(x * display_size, y * display_size,
                                      display_size, display_size);
@@ -2267,14 +2293,19 @@
       TestMenuFitsOnScreen(MenuAnchorPosition::kBubbleTopRight, monitor_bounds);
       TestMenuFitsOnScreen(MenuAnchorPosition::kBubbleLeft, monitor_bounds);
       TestMenuFitsOnScreen(MenuAnchorPosition::kBubbleRight, monitor_bounds);
+      TestMenuFitsOnScreen(MenuAnchorPosition::kBubbleBottomLeft,
+                           monitor_bounds);
+      TestMenuFitsOnScreen(MenuAnchorPosition::kBubbleBottomRight,
+                           monitor_bounds);
     }
+  }
 }
 
 // Test that menus show up on screen with zero sized anchors.
 TEST_P(MenuControllerTest, TestMenuFitsOnScreenSmallAnchor) {
   const int display_size = 500;
   // Simulate multiple display layouts.
-  for (int x = -1; x <= 1; x++)
+  for (int x = -1; x <= 1; x++) {
     for (int y = -1; y <= 1; y++) {
       const gfx::Rect monitor_bounds(x * display_size, y * display_size,
                                      display_size, display_size);
@@ -2286,7 +2317,12 @@
                                       monitor_bounds);
       TestMenuFitsOnScreenSmallAnchor(MenuAnchorPosition::kBubbleRight,
                                       monitor_bounds);
+      TestMenuFitsOnScreenSmallAnchor(MenuAnchorPosition::kBubbleBottomLeft,
+                                      monitor_bounds);
+      TestMenuFitsOnScreenSmallAnchor(MenuAnchorPosition::kBubbleBottomRight,
+                                      monitor_bounds);
     }
+  }
 }
 
 // Test that menus fit a small screen.
@@ -2294,7 +2330,7 @@
   const int display_size = 500;
 
   // Simulate multiple display layouts.
-  for (int x = -1; x <= 1; x++)
+  for (int x = -1; x <= 1; x++) {
     for (int y = -1; y <= 1; y++) {
       const gfx::Rect monitor_bounds(x * display_size, y * display_size,
                                      display_size, display_size);
@@ -2306,7 +2342,12 @@
                                 monitor_bounds);
       TestMenuFitsOnSmallScreen(MenuAnchorPosition::kBubbleRight,
                                 monitor_bounds);
+      TestMenuFitsOnSmallScreen(MenuAnchorPosition::kBubbleBottomLeft,
+                                monitor_bounds);
+      TestMenuFitsOnSmallScreen(MenuAnchorPosition::kBubbleBottomRight,
+                                monitor_bounds);
     }
+  }
 }
 
 // Test that submenus are displayed within the screen bounds on smaller screens.
@@ -2326,7 +2367,7 @@
   for (auto menu_position : {MenuAnchorPosition::kBubbleTopLeft,
                              MenuAnchorPosition::kBubbleTopRight}) {
     // Simulate multiple display layouts.
-    for (int x = -1; x <= 1; x++)
+    for (int x = -1; x <= 1; x++) {
       for (int y = -1; y <= 1; y++) {
         const gfx::Rect monitor_bounds(x * kDisplayWidth, y * kDisplayHeight,
                                        kDisplayWidth, kDisplayHeight);
@@ -2362,6 +2403,7 @@
             gfx::Rect(gfx::Point(x_qtr, y_min), parent_size_wide),
             menu_position);
       }
+    }
   }
 }
 
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 468bdc6..039cbc90 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -300,7 +300,8 @@
     case MenuAnchorPosition::kBubbleTopRight:
     case MenuAnchorPosition::kBubbleLeft:
     case MenuAnchorPosition::kBubbleRight:
-    case MenuAnchorPosition::kBubbleBelow:
+    case MenuAnchorPosition::kBubbleBottomLeft:
+    case MenuAnchorPosition::kBubbleBottomRight:
       return true;
   }
 }
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc
index da2b71c..979682a 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -418,7 +418,8 @@
     case MenuAnchorPosition::kBubbleTopRight:
     case MenuAnchorPosition::kBubbleLeft:
     case MenuAnchorPosition::kBubbleRight:
-    case MenuAnchorPosition::kBubbleBelow:
+    case MenuAnchorPosition::kBubbleBottomLeft:
+    case MenuAnchorPosition::kBubbleBottomRight:
       return BubbleBorder::FLOAT;
   }
 }
diff --git a/ui/views/controls/menu/menu_types.h b/ui/views/controls/menu/menu_types.h
index 365123df..5cfc74ff 100644
--- a/ui/views/controls/menu/menu_types.h
+++ b/ui/views/controls/menu/menu_types.h
@@ -8,9 +8,8 @@
 namespace views {
 
 // Where a popup menu should be anchored to for non-RTL languages. The opposite
-// position will be used if base::i18n:IsRTL() is true. The BUBBLE flags are
-// used when the menu should get enclosed by a bubble. The Fixed flags are
-// used for the menus that have a fixed anchor position.
+// position will be used if base::i18n:IsRTL() is true. The Bubble flags are
+// used when the menu should get enclosed by a bubble.
 enum class MenuAnchorPosition {
   kTopLeft,
   kTopRight,
@@ -19,7 +18,8 @@
   kBubbleTopRight,
   kBubbleLeft,
   kBubbleRight,
-  kBubbleBelow,
+  kBubbleBottomLeft,
+  kBubbleBottomRight,
 };
 
 }  // namespace views
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc
index 1d25f05..f8d6e19c 100644
--- a/ui/views/controls/scroll_view.cc
+++ b/ui/views/controls/scroll_view.cc
@@ -262,26 +262,13 @@
   // Protect against clients passing a contents view that has its own Layer.
   DCHECK(!a_view->layer());
   if (ScrollsWithLayers()) {
-    bool fills_opaquely = true;
-    if (!a_view->background()) {
-      // Contents views may not be aware they need to fill their entire bounds -
-      // play it safe here to avoid graphical glitches
-      // (https://crbug.com/826472). If there's no solid background, mark the
-      // view as not filling its bounds opaquely.
-      if (GetBackgroundColor()) {
-        a_view->SetBackground(
-            CreateSolidBackground(GetBackgroundColor().value()));
-      } else {
-        fills_opaquely = false;
-      }
-    }
     a_view->SetPaintToLayer();
     a_view->layer()->SetDidScrollCallback(base::BindRepeating(
         &ScrollView::OnLayerScrolled, base::Unretained(this)));
     a_view->layer()->SetScrollable(contents_viewport_->bounds().size());
-    a_view->layer()->SetFillsBoundsOpaquely(fills_opaquely);
   }
   SetHeaderOrContents(contents_viewport_, std::move(a_view), &contents_);
+  UpdateBackground();
 }
 
 void ScrollView::SetContents(std::nullptr_t) {
@@ -1124,8 +1111,14 @@
   // the viewport as well. This way if the viewport has a layer
   // SetFillsBoundsOpaquely() is honored.
   contents_viewport_->SetBackground(create_background());
-  if (contents_ && ScrollsWithLayers())
+  if (contents_ && ScrollsWithLayers()) {
     contents_->SetBackground(create_background());
+    // Contents views may not be aware they need to fill their entire bounds -
+    // play it safe here to avoid graphical glitches (https://crbug.com/826472).
+    // If there's no solid background, mark the contents view as not filling its
+    // bounds opaquely.
+    contents_->layer()->SetFillsBoundsOpaquely(!!background_color);
+  }
   if (contents_viewport_->layer()) {
     contents_viewport_->layer()->SetFillsBoundsOpaquely(!!background_color);
   }
diff --git a/ui/views/examples/examples_with_content_main.cc b/ui/views/examples/examples_with_content_main.cc
index 7fca765e..a638ccbb 100644
--- a/ui/views/examples/examples_with_content_main.cc
+++ b/ui/views/examples/examples_with_content_main.cc
@@ -18,6 +18,7 @@
 #endif
 
 #if defined(OS_WIN)
+#include "base/win/windows_types.h"
 #include "content/public/app/sandbox_helper_win.h"
 #include "sandbox/win/src/sandbox_types.h"
 #endif
diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc
index 1588bbc..ad611ca 100644
--- a/ui/views/widget/widget_delegate.cc
+++ b/ui/views/widget/widget_delegate.cc
@@ -49,8 +49,7 @@
 WidgetDelegate::Params::~Params() = default;
 
 WidgetDelegate::WidgetDelegate()
-    : widget_initializing_callbacks_(std::make_unique<ClosureVector>()),
-      widget_initialized_callbacks_(std::make_unique<ClosureVector>()),
+    : widget_initialized_callbacks_(std::make_unique<ClosureVector>()),
       client_view_factory_(
           base::BindOnce(&CreateDefaultClientView, base::Unretained(this))),
       non_client_frame_view_factory_(
@@ -195,10 +194,6 @@
 
 void WidgetDelegate::WidgetInitializing(Widget* widget) {
   widget_ = widget;
-  for (auto&& callback : *widget_initializing_callbacks_)
-    std::move(callback).Run();
-  widget_initializing_callbacks_.reset();
-  OnWidgetInitializing();
 }
 
 void WidgetDelegate::WidgetInitialized() {
@@ -402,12 +397,6 @@
   SetCanResize(has_controls);
 }
 
-void WidgetDelegate::RegisterWidgetInitializingCallback(
-    base::OnceClosure callback) {
-  DCHECK(widget_initializing_callbacks_);
-  widget_initializing_callbacks_->emplace_back(std::move(callback));
-}
-
 void WidgetDelegate::RegisterWidgetInitializedCallback(
     base::OnceClosure callback) {
   DCHECK(widget_initialized_callbacks_);
diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h
index 45f8c59..8accd587 100644
--- a/ui/views/widget/widget_delegate.h
+++ b/ui/views/widget/widget_delegate.h
@@ -142,10 +142,6 @@
   // menu bars, etc.) changes in size.
   virtual void OnWorkAreaChanged();
 
-  // Called when the widget's initialization is beginning, right after the
-  // ViewsDelegate decides to use this WidgetDelegate for a Widget.
-  virtual void OnWidgetInitializing() {}
-
   // Called when the widget's initialization is complete.
   virtual void OnWidgetInitialized() {}
 
@@ -373,7 +369,6 @@
   // SetCanMinimize, and SetCanResize.
   void SetHasWindowSizeControls(bool has_controls);
 
-  void RegisterWidgetInitializingCallback(base::OnceClosure callback);
   void RegisterWidgetInitializedCallback(base::OnceClosure callback);
   void RegisterWindowWillCloseCallback(base::OnceClosure callback);
   void RegisterWindowClosingCallback(base::OnceClosure callback);
@@ -431,10 +426,9 @@
   // WidgetDelegate if the client has given ownership to the Widget.
   bool* destructor_ran_ = nullptr;
 
-  // The first two are stored as unique_ptrs to make it easier to check in the
+  // This is stored as a unique_ptr to make it easier to check in the
   // registration methods whether a callback is being registered too late in the
   // WidgetDelegate's lifecycle.
-  std::unique_ptr<ClosureVector> widget_initializing_callbacks_;
   std::unique_ptr<ClosureVector> widget_initialized_callbacks_;
   ClosureVector window_will_close_callbacks_;
   ClosureVector window_closing_callbacks_;
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index 558638c4a..cb44f2f 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -286,19 +286,19 @@
 }
 
 views::LabelButton* DialogDelegate::GetOkButton() const {
-  DCHECK(GetWidget()) << "Don't call this before OnDialogInitialized";
+  DCHECK(GetWidget()) << "Don't call this before OnWidgetInitialized";
   auto* client = GetDialogClientView();
   return client ? client->ok_button() : nullptr;
 }
 
 views::LabelButton* DialogDelegate::GetCancelButton() const {
-  DCHECK(GetWidget()) << "Don't call this before OnDialogInitialized";
+  DCHECK(GetWidget()) << "Don't call this before OnWidgetInitialized";
   auto* client = GetDialogClientView();
   return client ? client->cancel_button() : nullptr;
 }
 
 views::View* DialogDelegate::GetExtraView() const {
-  DCHECK(GetWidget()) << "Don't call this before OnDialogInitialized";
+  DCHECK(GetWidget()) << "Don't call this before OnWidgetInitialized";
   auto* client = GetDialogClientView();
   return client ? client->extra_view() : nullptr;
 }
@@ -453,10 +453,6 @@
   return std::move(footnote_view_);
 }
 
-void DialogDelegate::OnWidgetInitialized() {
-  OnDialogInitialized();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // DialogDelegateView:
 
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h
index 556912ea..d620377 100644
--- a/ui/views/window/dialog_delegate.h
+++ b/ui/views/window/dialog_delegate.h
@@ -105,16 +105,6 @@
                                                       gfx::NativeView parent,
                                                       const gfx::Rect& bounds);
 
-  // Called when the DialogDelegate and its frame have finished initializing but
-  // not been shown yet. Override this to perform customizations to the dialog
-  // that need to happen after the dialog's widget, border, buttons, and so on
-  // are ready.
-  //
-  // Overrides of this method should be quite rare - prefer to do dialog
-  // customization before the frame/widget/etc are ready if at all possible, via
-  // other setters on this class.
-  virtual void OnDialogInitialized() {}
-
   // Returns a mask specifying which of the available DialogButtons are visible
   // for the dialog.
   // TODO(https://crbug.com/1011446): Rename this to buttons().
@@ -184,13 +174,13 @@
   BubbleFrameView* GetBubbleFrameView() const;
 
   // Helpers for accessing parts of the DialogClientView without needing to know
-  // about DialogClientView. Do not call these before OnDialogInitialized.
+  // about DialogClientView. Do not call these before OnWidgetInitialized().
   views::LabelButton* GetOkButton() const;
   views::LabelButton* GetCancelButton() const;
   views::View* GetExtraView() const;
 
   // Helper for accessing the footnote view. Unlike the three methods just
-  // above, this *is* safe to call before OnDialogInitialized.
+  // above, this *is* safe to call before OnWidgetInitialized().
   views::View* GetFootnoteViewForTesting() const;
 
   // Add or remove an observer notified by calls to DialogModelChanged().
@@ -317,10 +307,6 @@
   std::unique_ptr<View> DisownFootnoteView();
 
  private:
-  // Overridden from WidgetDelegate. If you need to hook after widget
-  // initialization, use OnDialogInitialized above.
-  void OnWidgetInitialized() final;
-
   // A helper for accessing the DialogClientView object contained by this
   // delegate's Window.
   const DialogClientView* GetDialogClientView() const;
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 0c5c6ba..7c2628a 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -227,6 +227,7 @@
     "$root_dir/js/cr/ui/focus_row.m.d.ts",
     "$root_dir/js/cr/ui/keyboard_shortcut_list.m.d.ts",
     "$root_dir/js/cr/ui/store_client.m.d.ts",
+    "$root_dir/js/custom_element.d.ts",
     "$root_dir/js/event_tracker.m.d.ts",
     "$root_dir/js/load_time_data.m.d.ts",
     "$root_dir/js/parse_html_subset.m.d.ts",
@@ -305,6 +306,7 @@
     "js/cr/ui/keyboard_shortcut_list.m.js",
     "js/cr/ui/store_client.m.js",
     "js/cr/ui/store.m.js",
+    "js/custom_element.js",
     "js/event_tracker.m.js",
     "js/icon.m.js",
     "js/load_time_data.m.js",
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn
index 3d5d2b7b..5ea79d1 100644
--- a/ui/webui/resources/cr_components/BUILD.gn
+++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -43,6 +43,7 @@
       "chromeos/network/cellular_off.svg",
       "chromeos/network/cellular_locked.svg",
       "chromeos/network/ethernet.svg",
+      "chromeos/network/globe_badge.svg",
       "chromeos/network/vpn.svg",
       "chromeos/network/wifi_0_with_x.svg",
       "chromeos/network/wifi_0.svg",
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_provisioning_entry.ts b/ui/webui/resources/cr_components/certificate_manager/certificate_provisioning_entry.ts
index e13f238..637f34b 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_provisioning_entry.ts
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_provisioning_entry.ts
@@ -24,7 +24,7 @@
 export interface CertificateProvisioningEntryElement {
   $: {
     dots: HTMLElement,
-    menu: CrLazyRenderElement,
+    menu: CrLazyRenderElement<CrActionMenuElement>,
   };
 }
 
@@ -55,7 +55,7 @@
   }
 
   private onDotsClick_() {
-    (this.$.menu.get() as CrActionMenuElement).showAt(this.$.dots);
+    this.$.menu.get().showAt(this.$.dots);
   }
 
   private onDetailsClick_() {
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.ts b/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.ts
index 7caa453e..687ce87 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.ts
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.ts
@@ -25,7 +25,7 @@
 
 export interface CertificateSubentryElement {
   $: {
-    menu: CrLazyRenderElement,
+    menu: CrLazyRenderElement<CrActionMenuElement>,
     dots: HTMLElement,
   };
 }
@@ -148,8 +148,7 @@
   }
 
   private onDotsClick_() {
-    const actionMenu = this.$.menu.get() as CrActionMenuElement;
-    actionMenu.showAt(this.$.dots);
+    this.$.menu.get().showAt(this.$.dots);
   }
 
   private getPolicyIndicatorType_(model: CertificateSubnode):
diff --git a/ui/webui/resources/cr_components/chromeos/network/globe_badge.svg b/ui/webui/resources/cr_components/chromeos/network/globe_badge.svg
new file mode 100644
index 0000000..491c54f6
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network/globe_badge.svg
@@ -0,0 +1,3 @@
+<svg width="5" height="5" viewBox="0 0 5 5" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M1.93749 3.89096C1.82214 3.79916 1.74787 3.65767 1.74787 3.49968V3.24968L1 2.5018C1.00074 3.13053 1.3883 3.66865 1.93749 3.89096ZM3.08473 1.11824C2.99564 1.19996 2.87708 1.25 2.7474 1.25H2.2474V1.75C2.2474 1.8875 2.1349 2 1.9974 2H1.4974V2.5H2.9974C3.1349 2.5 3.2474 2.6125 3.2474 2.75V3.5H3.4974C3.53523 3.5 3.57194 3.50417 3.60713 3.51207C3.85114 3.24529 4 2.89003 4 2.5C4 1.87901 3.62264 1.34616 3.08473 1.11824ZM5 2.5C5 3.88071 3.88071 5 2.5 5C1.11929 5 0 3.88071 0 2.5C0 1.11929 1.11929 0 2.5 0C3.88071 0 5 1.11929 5 2.5Z" fill="#5F6368"/>
+</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_icon.html b/ui/webui/resources/cr_components/chromeos/network/network_icon.html
index 0649dc01..7e3d35c 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_icon.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_icon.html
@@ -53,6 +53,21 @@
         right: 0;
       }
 
+      /* Left middle between icon image and technology badge*/
+      #roaming {
+        --iron-icon-fill-color: #5a5a5a;
+        height: 5px;
+        left: 2px;
+        position: absolute;
+        top: 9px;
+        width: 5px;
+      }
+
+      :host-context([dir='rtl']) #roaming {
+        left: auto;
+        right: 16px;
+      }
+
       /* Images */
       #icon.ethernet {
         background: url(chrome://resources/cr_components/chromeos/network/ethernet.svg);
@@ -184,6 +199,9 @@
     <iron-icon id="secure" hidden="[[!showSecure_(networkState)]]"
         icon="network8:badge-secure">
     </iron-icon>
+    <iron-icon id="roaming" hidden="[[!showRoaming_(networkState)]]"
+        src="chrome://resources/cr_components/chromeos/network/globe_badge.svg">
+    </iron-icon>
   </template>
   <script src="network_icon.js"></script>
 </dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_icon.js b/ui/webui/resources/cr_components/chromeos/network/network_icon.js
index 92b8fd80..03fb2713 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_icon.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_icon.js
@@ -305,4 +305,17 @@
     return this.networkState.type === mojom.NetworkType.kWiFi &&
         this.networkState.typeState.wifi.security !== mojom.SecurityType.kNone;
   },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  showRoaming_() {
+    if (!this.networkState) {
+      return false;
+    }
+    const mojom = chromeos.networkConfig.mojom;
+    return this.networkState.type === mojom.NetworkType.kCellular &&
+        this.networkState.typeState.cellular.roaming;
+  },
 });
diff --git a/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts b/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts
index 7f9abac..faeff7d 100644
--- a/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts
+++ b/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.d.ts
@@ -4,15 +4,16 @@
 
 import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js';
 
-interface CrLazyRenderElement extends LegacyElementMixin, HTMLElement {
-  get(): Element;
-  getIfExists(): (Element|null);
+interface CrLazyRenderElement<T extends HTMLElement> extends LegacyElementMixin,
+                                                             HTMLElement {
+  get(): T;
+  getIfExists(): (T|null);
 }
 
 export {CrLazyRenderElement};
 
 declare global {
   interface HTMLElementTagNameMap {
-    'cr-lazy-render': CrLazyRenderElement;
+    'cr-lazy-render': CrLazyRenderElement<HTMLElement>;
   }
 }
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc
index d6d1340..8642f25 100644
--- a/weblayer/browser/tab_impl.cc
+++ b/weblayer/browser/tab_impl.cc
@@ -838,7 +838,7 @@
 
 void TabImpl::ShowTranslateUi(JNIEnv* env) {
   TranslateClientImpl::FromWebContents(web_contents())
-      ->ManualTranslateWhenReady();
+      ->ShowTranslateUiWhenReady();
 }
 
 void TabImpl::RemoveTabFromBrowserBeforeDestroying(JNIEnv* env) {
diff --git a/weblayer/browser/translate_client_impl.cc b/weblayer/browser/translate_client_impl.cc
index 599753c6..9b6477b 100644
--- a/weblayer/browser/translate_client_impl.cc
+++ b/weblayer/browser/translate_client_impl.cc
@@ -145,17 +145,17 @@
 
 void TranslateClientImpl::OnLanguageDetermined(
     const translate::LanguageDetectionDetails& details) {
-  if (manual_translate_on_ready_) {
-    GetTranslateManager()->InitiateManualTranslation();
-    manual_translate_on_ready_ = false;
+  if (show_translate_ui_on_ready_) {
+    GetTranslateManager()->ShowTranslateUI();
+    show_translate_ui_on_ready_ = false;
   }
 }
 
-void TranslateClientImpl::ManualTranslateWhenReady() {
+void TranslateClientImpl::ShowTranslateUiWhenReady() {
   if (GetLanguageState().source_language().empty()) {
-    manual_translate_on_ready_ = true;
+    show_translate_ui_on_ready_ = true;
   } else {
-    GetTranslateManager()->InitiateManualTranslation();
+    GetTranslateManager()->ShowTranslateUI();
   }
 }
 
diff --git a/weblayer/browser/translate_client_impl.h b/weblayer/browser/translate_client_impl.h
index e7953f3..4399b49d 100644
--- a/weblayer/browser/translate_client_impl.h
+++ b/weblayer/browser/translate_client_impl.h
@@ -70,9 +70,9 @@
   void OnLanguageDetermined(
       const translate::LanguageDetectionDetails& details) override;
 
-  // Trigger a manual translation when the necessary state (e.g. source
-  // language) is ready.
-  void ManualTranslateWhenReady();
+  // Show the translation UI when the necessary state (e.g. source language) is
+  // ready.
+  void ShowTranslateUiWhenReady();
 
  private:
   explicit TranslateClientImpl(content::WebContents* web_contents);
@@ -84,8 +84,8 @@
   translate::ContentTranslateDriver translate_driver_;
   std::unique_ptr<translate::TranslateManager> translate_manager_;
 
-  // Whether to trigger a manual translation when ready.
-  bool manual_translate_on_ready_ = false;
+  // Whether to show translation UI when ready.
+  bool show_translate_ui_on_ready_ = false;
 
   base::ScopedObservation<
       translate::TranslateDriver,