diff --git a/DEPS b/DEPS
index d00be901..6f89e6b 100644
--- a/DEPS
+++ b/DEPS
@@ -209,11 +209,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': 'f208f81e1d6884f6b9042f48cde4edc9b2d1926a',
+  'skia_revision': 'e74638b83f1bd6426c067b30640f4875ef65cc20',
   # 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': 'e09c58db3219b0fb5d409ea7e5d503963ab785e1',
+  'v8_revision': 'fe51be573022a012a96497518948b6a216efd3d4',
   # 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.
@@ -221,7 +221,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': '078a2ba669b6ffea140d3babb12d2265639a647c',
+  'angle_revision': '257b29efa976dd5ce1aa0fc6015c6d2980133e61',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '9a8df8603a9dc3e8646d01d90c3335ec66a5cbe4',
+  'dawn_revision': '2a979e6b70f6992b6f3b5c5318d461fa662f4688',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -395,7 +395,7 @@
   'libcxx_revision':       '8fa87946779682841e21e2da977eccfb6cb3bded',
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:dba01723a441c358d843a575cb7720d54ddcdf92',
+  'gn_version': 'git_revision:6771ce569fb4803dad7a427aa2e2c23e960b917e',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -548,7 +548,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/ios/third_party/earl_grey2/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'bd4649d035b14a8ef54a686a0717122d529a4478',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '1bbcdeb54662bbb5695f81db9fe57ec368de2cd7',
       'condition': 'checkout_ios',
   },
 
@@ -966,7 +966,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3a56ba9d9c9d22bc78e24f96a9096247d53649f8',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0d1afc97295c538cf179214fd98ec3c2cca85c8f',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1338,7 +1338,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '3c17caaf951e52670f10349e5a88bed5bc86b271',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '52fefceb29bb88140996879a9a8970d7ea6dce83',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1416,7 +1416,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'PNMyschZLgBf2Dn-ygogmtVo9JfvV8HyeL9WMxQRtF4C'
+              'version': 'kswh0qF56RoEDBXJbyo1IWPAJ9F7WGAvMHGyWGbpBtUC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1549,10 +1549,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0b8774ce8cec1dc8f4308810bf05eb8867c62de',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '04615127de529c1b7aad103e61abce816ed0fe6f',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3692cbbd3224f9d7e2ae138ef26bd584855249a1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '73604615328f92daaee6dc7f78efa28e1dda2b60',
+    Var('webrtc_git') + '/src.git' + '@' + '141a4de0727cb2eba7d21e896e4ecf72b5be1502',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1613,7 +1613,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@82b849c5e44e578cd6f1003596a85db5197921f6',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f3b3a61d8e581b0da22a4058d293f3ccf0e10fab',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc
index b3180b95..6c6936d6 100644
--- a/android_webview/common/crash_reporter/crash_keys.cc
+++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -55,41 +55,40 @@
     "total-discardable-memory-allocated",
 
     // Navigation
-    "VerifyDidCommit-browser_intended",
-    "VerifyDidCommit-renderer_intended",
-
-    "VerifyDidCommit-browser_method",
-    "VerifyDidCommit-renderer_method",
-    "VerifyDidCommit-original_method",
-
-    "VerifyDidCommit-browser_unreachable",
-    "VerifyDidCommit-renderer_unreachable",
-
-    "VerifyDidCommit-base_url_exp_match",
     "VerifyDidCommit-prev_ldwb",
     "VerifyDidCommit-prev_ldwbu",
-    "VerifyDidCommit-b_base_url_valid",
-    "VerifyDidCommit-b_base_url_empty",
-    "VerifyDidCommit-b_hist_url_empty",
-    "VerifyDidCommit-b_data_url_empty",
-    "VerifyDidCommit-r_base_url_empty",
-    "VerifyDidCommit-r_base_url_error",
-    "VerifyDidCommit-r_history_url_empty",
+    "VerifyDidCommit-base_url_fdu_empty",
+    "VerifyDidCommit-data_url_empty",
+    "VerifyDidCommit-history_url_fdu_empty",
 
-    "VerifyDidCommit-browser_post_id",
-    "VerifyDidCommit-renderer_post_id",
+    "VerifyDidCommit-intended_browser",
+    "VerifyDidCommit-intended_renderer",
 
-    "VerifyDidCommit-browser_override_ua",
-    "VerifyDidCommit-renderer_override_ua",
+    "VerifyDidCommit-method_post_browser",
+    "VerifyDidCommit-method_post_renderer",
+    "VerifyDidCommit-original_method_post",
 
-    "VerifyDidCommit-browser_code",
-    "VerifyDidCommit-renderer_code",
+    "VerifyDidCommit-unreachable_browser",
+    "VerifyDidCommit-unreachable_renderer",
 
-    "VerifyDidCommit-browser_suh",
-    "VerifyDidCommit-renderer_suh",
+    "VerifyDidCommit-post_id_matches",
+    "VerifyDidCommit-post_id_-1_browser",
+    "VerifyDidCommit-post_id_-1_renderer",
 
-    "VerifyDidCommit-browser_gesture",
-    "VerifyDidCommit-renderer_gesture",
+    "VerifyDidCommit-override_ua_browser",
+    "VerifyDidCommit-override_ua_renderer",
+
+    "VerifyDidCommit-code_browser",
+    "VerifyDidCommit-code_renderer",
+
+    "VerifyDidCommit-suh_browser",
+    "VerifyDidCommit-suh_renderer",
+
+    "VerifyDidCommit-gesture_browser",
+    "VerifyDidCommit-gesture_renderer",
+
+    "VerifyDidCommit-replace_browser",
+    "VerifyDidCommit-replace_renderer",
 
     "VerifyDidCommit-is_same_document",
     "VerifyDidCommit-is_history_api",
@@ -103,8 +102,14 @@
     "VerifyDidCommit-redirects_size",
 
     "VerifyDidCommit-entry_offset",
+    "VerifyDidCommit-entry_count",
+    "VerifyDidCommit-last_committed_index",
+
     "VerifyDidCommit-is_reload",
     "VerifyDidCommit-is_restore",
+    "VerifyDidCommit-is_history",
+    "VerifyDidCommit-has_valid_page_state",
+
     "VerifyDidCommit-has_gesture",
     "VerifyDidCommit-was_click",
 
@@ -115,6 +120,7 @@
 
     "VerifyDidCommit-original_same_doc",
 
+    "VerifyDidCommit-committed_real_load",
     "VerifyDidCommit-last_url_empty",
     "VerifyDidCommit-last_url_blank",
     "VerifyDidCommit-last_url_srcdoc",
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc
index 4590922..7046d443 100644
--- a/ash/public/cpp/ash_features.cc
+++ b/ash/public/cpp/ash_features.cc
@@ -70,9 +70,6 @@
 const base::Feature kManagedDeviceUIRedesign{"ManagedDeviceUIRedesign",
                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kMediaSessionNotification{"MediaSessionNotification",
-                                              base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kNightLight{"NightLight", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kNotificationExpansionAnimation{
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h
index b62f6f3..2d54ef5 100644
--- a/ash/public/cpp/ash_features.h
+++ b/ash/public/cpp/ash_features.h
@@ -92,11 +92,6 @@
 // Enables the redesigned managed device info UI in the system tray.
 ASH_PUBLIC_EXPORT extern const base::Feature kManagedDeviceUIRedesign;
 
-// Enables the media session notification. If this is enabled, we will show
-// a notification that shows the currently playing media with controls.
-// TODO(beccahughes): Remove after launch. (https://crbug.com/897836)
-ASH_PUBLIC_EXPORT extern const base::Feature kMediaSessionNotification;
-
 // Enables resizing/moving the selection region for partial screenshot.
 ASH_PUBLIC_EXPORT extern const base::Feature kMovablePartialScreenshot;
 
diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc
index 3a21df8..6e9e43d 100644
--- a/ash/wm/mru_window_tracker.cc
+++ b/ash/wm/mru_window_tracker.cc
@@ -269,14 +269,6 @@
   mru_windows_.insert(mru_windows_.begin(), window);
 }
 
-void MruWindowTracker::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void MruWindowTracker::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
 //////////////////////////////////////////////////////////////////////////////
 // MruWindowTracker, private:
 
@@ -312,9 +304,6 @@
   // else we may end up with a deleted window in |mru_windows_|.
   base::Erase(mru_windows_, window);
   window->RemoveObserver(this);
-
-  for (auto& observer : observers_)
-    observer.OnWindowUntracked(window);
 }
 
 void MruWindowTracker::OnWindowInitialized(aura::Window* window) {
diff --git a/ash/wm/mru_window_tracker.h b/ash/wm/mru_window_tracker.h
index 4828c1a..dad4097 100644
--- a/ash/wm/mru_window_tracker.h
+++ b/ash/wm/mru_window_tracker.h
@@ -9,7 +9,6 @@
 
 #include "ash/ash_export.h"
 #include "base/macros.h"
-#include "base/observer_list.h"
 #include "ui/aura/env_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/wm/public/activation_change_observer.h"
@@ -42,12 +41,6 @@
  public:
   using WindowList = std::vector<aura::Window*>;
 
-  class Observer : public base::CheckedObserver {
-   public:
-    // Invoked when a tracked window is destroyed,
-    virtual void OnWindowUntracked(aura::Window* untracked_window) {}
-  };
-
   MruWindowTracker();
   ~MruWindowTracker() override;
 
@@ -99,10 +92,6 @@
   // used window across all desks.
   void OnWindowMovedOutFromRemovingDesk(aura::Window* window);
 
-  // Add/Remove observers.
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
   const std::vector<aura::Window*>& GetMruWindowsForTesting() {
     return mru_windows_;
   }
@@ -127,8 +116,6 @@
   // through, sorted such that the most recently used window comes last.
   std::vector<aura::Window*> mru_windows_;
 
-  base::ObserverList<Observer, true> observers_;
-
   bool ignore_window_activations_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(MruWindowTracker);
diff --git a/ash/wm/native_cursor_manager_ash.cc b/ash/wm/native_cursor_manager_ash.cc
index 86e93cf..b2d7aa2 100644
--- a/ash/wm/native_cursor_manager_ash.cc
+++ b/ash/wm/native_cursor_manager_ash.cc
@@ -102,8 +102,9 @@
     gfx::NativeCursor invisible_cursor(ui::mojom::CursorType::kNone);
     cursor_loader_.SetPlatformCursor(&invisible_cursor);
     cursor.SetPlatformCursor(invisible_cursor.platform());
+    if (cursor.type() != ui::mojom::CursorType::kCustom)
+      cursor.set_image_scale_factor(cursor_loader_.scale());
   }
-  cursor.set_image_scale_factor(cursor_loader_.scale());
 
   delegate->CommitCursor(cursor);
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index b7093a5..59dae84 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1099,6 +1099,7 @@
       "win/scoped_hglobal.h",
       "win/scoped_hstring.cc",
       "win/scoped_hstring.h",
+      "win/scoped_localalloc.h",
       "win/scoped_process_information.cc",
       "win/scoped_process_information.h",
       "win/scoped_propvariant.h",
@@ -1109,9 +1110,13 @@
       "win/scoped_windows_thread_environment.h",
       "win/scoped_winrt_initializer.cc",
       "win/scoped_winrt_initializer.h",
+      "win/security_util.cc",
+      "win/security_util.h",
       "win/shlwapi.h",
       "win/shortcut.cc",
       "win/shortcut.h",
+      "win/sid.cc",
+      "win/sid.h",
       "win/sphelper.h",
       "win/startup_information.cc",
       "win/startup_information.h",
@@ -3284,11 +3289,14 @@
       "win/scoped_bstr_unittest.cc",
       "win/scoped_handle_unittest.cc",
       "win/scoped_hstring_unittest.cc",
+      "win/scoped_localalloc_unittest.cc",
       "win/scoped_process_information_unittest.cc",
       "win/scoped_safearray_unittest.cc",
       "win/scoped_variant_unittest.cc",
       "win/scoped_winrt_initializer_unittest.cc",
+      "win/security_util_unittest.cc",
       "win/shortcut_unittest.cc",
+      "win/sid_unittest.cc",
       "win/startup_information_unittest.cc",
       "win/variant_util_unittest.cc",
       "win/variant_vector_unittest.cc",
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index 09f449f..e8248e8 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -147,7 +147,9 @@
 // Ref. TestMockTimeTaskRunner::RunsTasksInCurrentSequence().
 TestMockTimeTaskRunner::ScopedContext::ScopedContext(
     scoped_refptr<TestMockTimeTaskRunner> scope)
-    : thread_task_runner_handle_override_(scope) {
+    : thread_task_runner_handle_override_(scope),
+      sequence_local_storage_map_override_(
+          scope->sequence_local_storage_map_.get()) {
   scope->RunUntilIdle();
 }
 
@@ -167,10 +169,15 @@
 TestMockTimeTaskRunner::TestMockTimeTaskRunner(Time start_time,
                                                TimeTicks start_ticks,
                                                Type type)
-    : now_(start_time),
+    : owning_thread_(ThreadTaskRunnerHandle::IsSet()
+                         ? ThreadTaskRunnerHandle::Get()
+                         : nullptr),
+      now_(start_time),
       now_ticks_(start_ticks),
       tasks_lock_cv_(&tasks_lock_),
       proxy_task_runner_(MakeRefCounted<NonOwningProxyTaskRunner>(this)),
+      sequence_local_storage_map_(
+          std::make_unique<internal::SequenceLocalStorageMap>()),
       mock_clock_(this) {
   if (type == Type::kBoundToThread) {
     RunLoop::RegisterDelegateForCurrentThread(this);
@@ -179,7 +186,38 @@
   }
 }
 
+void TestMockTimeTaskRunner::OnDestruct() const {
+  // We need to ensure that destruction happens on the thread of creation (which
+  // is also the thread where tasks in this task runner should be running). This
+  // is to handle values registered in the |sequence_local_storage_map_| that
+  // are thread-affine.
+  if (owning_thread_ && !owning_thread_->BelongsToCurrentThread()) {
+    const bool owning_thread_accepted_task =
+        owning_thread_->DeleteSoon(FROM_HERE, this);
+    DCHECK(owning_thread_accepted_task)
+        << "TestMockTimeTaskRunner must be destroyed before its owning thread "
+           "is shutdown.";
+  } else {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    delete this;
+  }
+}
+
 TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  {
+    base::Optional<ThreadTaskRunnerHandleOverrideForTesting> ttrh_override;
+    if (!ThreadTaskRunnerHandle::IsSet() ||
+        ThreadTaskRunnerHandle::Get() != proxy_task_runner_.get()) {
+      ttrh_override.emplace(proxy_task_runner_.get());
+    }
+    {
+      base::internal::SequenceLocalStorageMapOverrideForTesting slsm_override(
+          sequence_local_storage_map_.get());
+      ClearPendingTasks();
+    }
+    sequence_local_storage_map_.reset();
+  }
   proxy_task_runner_->Detach();
 }
 
@@ -355,6 +393,8 @@
       ThreadTaskRunnerHandle::Get() != proxy_task_runner_.get()) {
     ttrh_override.emplace(proxy_task_runner_.get());
   }
+  base::internal::SequenceLocalStorageMapOverrideForTesting slsm_override(
+      sequence_local_storage_map_.get());
 
   const TimeTicks original_now_ticks = NowTicks();
   for (int i = 0; !quit_run_loop_ && (limit < 0 || i < limit); i++) {
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index acc83a3..165fdcc 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -20,6 +20,7 @@
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/test/test_pending_task.h"
+#include "base/threading/sequence_local_storage_map.h"
 #include "base/threading/thread_checker_impl.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/clock.h"
@@ -120,6 +121,8 @@
    private:
     ThreadTaskRunnerHandleOverrideForTesting
         thread_task_runner_handle_override_;
+    internal::SequenceLocalStorageMapOverrideForTesting
+        sequence_local_storage_map_override_;
     DISALLOW_COPY_AND_ASSIGN(ScopedContext);
   };
 
@@ -204,7 +207,11 @@
                                   OnceClosure task,
                                   TimeDelta delay) override;
 
+  // TaskRunner:
+  void OnDestruct() const override;
+
  protected:
+  friend class DeleteHelper<TestMockTimeTaskRunner>;
   ~TestMockTimeTaskRunner() override;
 
   // Called before the next task to run is selected, so that subclasses have a
@@ -284,6 +291,12 @@
   // needs to be a ThreadCheckerImpl.
   ThreadCheckerImpl thread_checker_;
 
+  // The task runner this TestMockTimeTaskRunner was created on, if any. If
+  // non-null, destruction will be posted back to this thread if it happens
+  // elsewhere. It's null in unit tests without a main thread task environment
+  // where deletion will thus always proceed synchronously.
+  const scoped_refptr<SingleThreadTaskRunner> owning_thread_;
+
   Time now_;
   TimeTicks now_ticks_;
 
@@ -300,6 +313,8 @@
 
   const scoped_refptr<NonOwningProxyTaskRunner> proxy_task_runner_;
   std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
+  std::unique_ptr<internal::SequenceLocalStorageMap>
+      sequence_local_storage_map_;
 
   // Set to true in RunLoop::Delegate::Quit() to signal the topmost
   // RunLoop::Delegate::Run() instance to stop, reset to false when it does.
diff --git a/base/test/test_mock_time_task_runner_unittest.cc b/base/test/test_mock_time_task_runner_unittest.cc
index 1fff6c3..db36d073 100644
--- a/base/test/test_mock_time_task_runner_unittest.cc
+++ b/base/test/test_mock_time_task_runner_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/bind.h"
 #include "base/test/gtest_util.h"
 #include "base/test/test_timeouts.h"
+#include "base/threading/sequence_local_storage_slot.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -357,4 +358,56 @@
   expected_value += 4096;
   EXPECT_EQ(expected_value, counter);
 }
+
+TEST(TestMockTimeTaskRunnerTest, CanStoreSequenceLocalValues) {
+  SequenceLocalStorageSlot<int> slot;
+  auto outer_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
+      TestMockTimeTaskRunner::Type::kStandalone);
+  int counter = 0;
+
+  // We create an 'inner' task runner from the 'outer' task runner so that the
+  // inner ThreadCheckerImpl is bound to the outer thread.
+  scoped_refptr<TestMockTimeTaskRunner> inner_task_runner;
+  {
+    TestMockTimeTaskRunner::ScopedContext outer_context(outer_task_runner);
+    inner_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
+        TestMockTimeTaskRunner::Type::kStandalone);
+  }
+
+  // This outer task simply stores the value '6' in the outer sequence; we'll
+  // retrieve it later to make sure it remains stored after running other tasks.
+  outer_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
+                                EXPECT_EQ(slot.GetValuePointer(), nullptr);
+                                slot.GetOrCreateValue() = 6;
+                                counter += 1;
+                              }));
+
+  // These inner tasks store and retrieve the value '5' in the inner sequence.
+  // We run the tasks in the outer task runner but in the context of the inner
+  // sequence. This basically tests that the storage map of the inner sequence
+  // is independent from the storage map of the outer sequence.
+  inner_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
+                                // In the inner sequence, no value has been
+                                // stored in the slot yet.
+                                EXPECT_EQ(slot.GetValuePointer(), nullptr);
+                                slot.GetOrCreateValue() = 5;
+                                counter += 2;
+                              }));
+  inner_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
+                                // In the inner sequence, the slot refers to '5'
+                                // and not '6'.
+                                EXPECT_EQ(slot.GetOrCreateValue(), 5);
+                                counter += 4;
+                              }));
+  outer_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
+                                inner_task_runner->RunUntilIdle();
+                                // After leaving the inner sequence context, we
+                                // should be able to retrieve the value from the
+                                // outer sequence.
+                                EXPECT_EQ(slot.GetOrCreateValue(), 6);
+                                counter += 8;
+                              }));
+  outer_task_runner->RunUntilIdle();
+  EXPECT_EQ(counter, 1 + 2 + 4 + 8);
+}
 }  // namespace base
diff --git a/base/threading/sequence_local_storage_map.cc b/base/threading/sequence_local_storage_map.cc
index 26ce4b17..29f6334 100644
--- a/base/threading/sequence_local_storage_map.cc
+++ b/base/threading/sequence_local_storage_map.cc
@@ -34,6 +34,18 @@
   tls_current_sequence_local_storage.Get().Set(nullptr);
 }
 
+SequenceLocalStorageMapOverrideForTesting::
+    SequenceLocalStorageMapOverrideForTesting(
+        SequenceLocalStorageMap* sequence_local_storage)
+    : old_sls_map_(tls_current_sequence_local_storage.Get().Get()) {
+  tls_current_sequence_local_storage.Get().Set(sequence_local_storage);
+}
+
+SequenceLocalStorageMapOverrideForTesting::
+    ~SequenceLocalStorageMapOverrideForTesting() {
+  tls_current_sequence_local_storage.Get().Set(old_sls_map_);
+}
+
 // static
 SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() {
   SequenceLocalStorageMap* current_sequence_local_storage =
diff --git a/base/threading/sequence_local_storage_map.h b/base/threading/sequence_local_storage_map.h
index 3857cc2..404cac35 100644
--- a/base/threading/sequence_local_storage_map.h
+++ b/base/threading/sequence_local_storage_map.h
@@ -89,6 +89,21 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(ScopedSetSequenceLocalStorageMapForCurrentThread);
 };
+
+// This is analogous to ThreadTaskRunnerHandleOverrideForTesting but for
+// SequenceLocalStorageMaps.
+class BASE_EXPORT SequenceLocalStorageMapOverrideForTesting {
+ public:
+  explicit SequenceLocalStorageMapOverrideForTesting(
+      SequenceLocalStorageMap* sequence_local_storage);
+  ~SequenceLocalStorageMapOverrideForTesting();
+
+ private:
+  SequenceLocalStorageMap* const old_sls_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageMapOverrideForTesting);
+};
+
 }  // namespace internal
 }  // namespace base
 
diff --git a/base/threading/sequence_local_storage_map_unittest.cc b/base/threading/sequence_local_storage_map_unittest.cc
index a45bbc3..869b76c 100644
--- a/base/threading/sequence_local_storage_map_unittest.cc
+++ b/base/threading/sequence_local_storage_map_unittest.cc
@@ -113,5 +113,36 @@
   EXPECT_TRUE(set_on_destruction2);
 }
 
+TEST(SequenceLocalStorageMapTest, NestedSequenceLocalStorageMap) {
+  SequenceLocalStorageMap outer_sequence_local_storage_map;
+  SequenceLocalStorageMap::ValueDestructorPair outer_value_pair =
+      CreateValueDestructorPair<int>(5);
+  outer_sequence_local_storage_map.Set(kSlotId, std::move(outer_value_pair));
+
+  SequenceLocalStorageMap inner_sequence_local_storage_map;
+  SequenceLocalStorageMap::ValueDestructorPair inner_value_pair =
+      CreateValueDestructorPair<int>(6);
+  inner_sequence_local_storage_map.Set(kSlotId, std::move(inner_value_pair));
+
+  SequenceLocalStorageMapOverrideForTesting outer_override(
+      &outer_sequence_local_storage_map);
+  ASSERT_TRUE(SequenceLocalStorageMap::IsSetForCurrentThread());
+  EXPECT_EQ(*static_cast<int*>(
+                SequenceLocalStorageMap::GetForCurrentThread().Get(kSlotId)),
+            5);
+  {
+    SequenceLocalStorageMapOverrideForTesting inner_override(
+        &inner_sequence_local_storage_map);
+    ASSERT_TRUE(SequenceLocalStorageMap::IsSetForCurrentThread());
+    EXPECT_EQ(*static_cast<int*>(
+                  SequenceLocalStorageMap::GetForCurrentThread().Get(kSlotId)),
+              6);
+  }
+  ASSERT_TRUE(SequenceLocalStorageMap::IsSetForCurrentThread());
+  EXPECT_EQ(*static_cast<int*>(
+                SequenceLocalStorageMap::GetForCurrentThread().Get(kSlotId)),
+            5);
+}
+
 }  // namespace internal
 }  // namespace base
diff --git a/base/win/scoped_localalloc.h b/base/win/scoped_localalloc.h
new file mode 100644
index 0000000..0edd734
--- /dev/null
+++ b/base/win/scoped_localalloc.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 BASE_WIN_SCOPED_LOCALALLOC_H_
+#define BASE_WIN_SCOPED_LOCALALLOC_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/win/windows_types.h"
+
+namespace base {
+namespace win {
+
+// unique_ptr deleter for LocalAlloc memory.
+struct LocalAllocDeleter {
+  void operator()(void* ptr) const { ::LocalFree(ptr); }
+};
+
+template <typename T>
+using ScopedLocalAllocTyped = std::unique_ptr<T, LocalAllocDeleter>;
+
+using ScopedLocalAlloc = ScopedLocalAllocTyped<void>;
+
+// Make a typed ScopedLocalAlloc class and clear the original pointer.
+template <typename T>
+ScopedLocalAllocTyped<T> TakeLocalAlloc(T*& ptr) {
+  return ScopedLocalAllocTyped<T>(std::exchange(ptr, nullptr));
+}
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_SCOPED_LOCALALLOC_H_
diff --git a/base/win/scoped_localalloc_unittest.cc b/base/win/scoped_localalloc_unittest.cc
new file mode 100644
index 0000000..0a456b6
--- /dev/null
+++ b/base/win/scoped_localalloc_unittest.cc
@@ -0,0 +1,33 @@
+// 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 "base/win/scoped_localalloc.h"
+
+#include <windows.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+TEST(ScopedLocalAlloc, Transfer) {
+  HLOCAL ptr = ::LocalAlloc(LMEM_FIXED, 0x1000);
+  ASSERT_TRUE(ptr);
+  ScopedLocalAllocTyped<void> scoped_ptr = TakeLocalAlloc(ptr);
+  EXPECT_TRUE(scoped_ptr);
+  EXPECT_FALSE(ptr);
+  scoped_ptr.reset();
+  EXPECT_FALSE(scoped_ptr);
+
+  wchar_t* str_ptr = static_cast<wchar_t*>(::LocalAlloc(LMEM_FIXED, 0x1000));
+  ASSERT_TRUE(str_ptr);
+  ScopedLocalAllocTyped<wchar_t> scoped_str_ptr = TakeLocalAlloc(str_ptr);
+  EXPECT_TRUE(scoped_str_ptr);
+  EXPECT_FALSE(str_ptr);
+  scoped_str_ptr.reset();
+  EXPECT_FALSE(scoped_str_ptr);
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/security_util.cc b/base/win/security_util.cc
new file mode 100644
index 0000000..88139d66
--- /dev/null
+++ b/base/win/security_util.cc
@@ -0,0 +1,78 @@
+// 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 "base/win/security_util.h"
+
+#include <aclapi.h>
+#include <windows.h>
+
+#include <string>
+
+#include "base/check.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/optional.h"
+#include "base/win/scoped_localalloc.h"
+#include "base/win/win_util.h"
+
+namespace base {
+namespace win {
+
+bool GrantAccessToPath(const FilePath& path,
+                       const std::vector<Sid>& sids,
+                       DWORD access_mask,
+                       DWORD inheritance) {
+  DCHECK(!path.empty());
+  if (sids.empty())
+    return true;
+
+  std::wstring object_name = path.value();
+  PSECURITY_DESCRIPTOR sd = nullptr;
+  PACL dacl = nullptr;
+
+  // Get the existing DACL.
+  DWORD error = ::GetNamedSecurityInfo(object_name.c_str(), SE_FILE_OBJECT,
+                                       DACL_SECURITY_INFORMATION, nullptr,
+                                       nullptr, &dacl, nullptr, &sd);
+  if (error != ERROR_SUCCESS) {
+    ::SetLastError(error);
+    DPLOG(ERROR) << "Failed getting DACL for path \"" << path.value() << "\"";
+    return false;
+  }
+  auto sd_ptr = TakeLocalAlloc(sd);
+  std::vector<EXPLICIT_ACCESS> access_entries(sids.size());
+  auto entries_interator = access_entries.begin();
+  for (const Sid& sid : sids) {
+    EXPLICIT_ACCESS& new_access = *entries_interator++;
+    new_access.grfAccessMode = GRANT_ACCESS;
+    new_access.grfAccessPermissions = access_mask;
+    new_access.grfInheritance = inheritance;
+    ::BuildTrusteeWithSid(&new_access.Trustee, sid.GetPSID());
+  }
+
+  PACL new_dacl = nullptr;
+  error = ::SetEntriesInAcl(access_entries.size(), access_entries.data(), dacl,
+                            &new_dacl);
+  if (error != ERROR_SUCCESS) {
+    ::SetLastError(error);
+    DPLOG(ERROR) << "Failed adding ACEs to DACL for path \"" << path.value()
+                 << "\"";
+    return false;
+  }
+  auto new_dacl_ptr = TakeLocalAlloc(new_dacl);
+
+  error = ::SetNamedSecurityInfo(&object_name[0], SE_FILE_OBJECT,
+                                 DACL_SECURITY_INFORMATION, nullptr, nullptr,
+                                 new_dacl_ptr.get(), nullptr);
+  if (error != ERROR_SUCCESS) {
+    ::SetLastError(error);
+    DPLOG(ERROR) << "Failed setting DACL for path \"" << path.value() << "\"";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/security_util.h b/base/win/security_util.h
new file mode 100644
index 0000000..2dcbc36
--- /dev/null
+++ b/base/win/security_util.h
@@ -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.
+
+#ifndef BASE_WIN_SECURITY_UTIL_H_
+#define BASE_WIN_SECURITY_UTIL_H_
+
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/win/sid.h"
+#include "base/win/windows_types.h"
+
+namespace base {
+
+class FilePath;
+
+namespace win {
+
+// Adds allowed ACE entries to a file or directory |path| from a list of SIDs
+// with allowed |access_mask| and |inheritance| flags.
+BASE_EXPORT bool GrantAccessToPath(const FilePath& path,
+                                   const std::vector<Sid>& sids,
+                                   DWORD access_mask,
+                                   DWORD inheritance);
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_SECURITY_UTIL_H_
\ No newline at end of file
diff --git a/base/win/security_util_unittest.cc b/base/win/security_util_unittest.cc
new file mode 100644
index 0000000..edf8c212
--- /dev/null
+++ b/base/win/security_util_unittest.cc
@@ -0,0 +1,127 @@
+// 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 "base/win/security_util.h"
+
+#include <aclapi.h>
+#include <sddl.h>
+#include <windows.h>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/scoped_localalloc.h"
+#include "base/win/sid.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+constexpr wchar_t kBaseDacl[] = L"D:P(A;;FA;;;WD)";
+constexpr wchar_t kTest1Dacl[] = L"D:PAI(A;;FR;;;AU)(A;;FA;;;WD)";
+constexpr wchar_t kTest2Dacl[] = L"D:PAI(A;;FA;;;BA)(A;;FA;;;AU)(A;;FA;;;WD)";
+
+constexpr wchar_t kBaseDirDacl[] = L"D:P(A;OICI;FA;;;WD)";
+constexpr wchar_t kTest1InheritedDacl[] = L"D:(A;ID;FA;;;WD)";
+constexpr wchar_t kBaseDir2Dacl[] = L"D:PAI(A;OICI;FR;;;AU)(A;OICI;FA;;;WD)";
+constexpr wchar_t kTest2InheritedDacl[] = L"D:AI(A;ID;FR;;;AU)(A;ID;FA;;;WD)";
+
+constexpr wchar_t kNoWriteDacDacl[] = L"D:(D;;WD;;;OW)(A;;FRSD;;;WD)";
+
+constexpr wchar_t kAuthenticatedUsersSid[] = L"AU";
+
+std::wstring GetFileDacl(const FilePath& path) {
+  PSECURITY_DESCRIPTOR sd;
+  if (::GetNamedSecurityInfo(path.value().c_str(), SE_FILE_OBJECT,
+                             DACL_SECURITY_INFORMATION, nullptr, nullptr,
+                             nullptr, nullptr, &sd) != ERROR_SUCCESS) {
+    return std::wstring();
+  }
+  auto sd_ptr = TakeLocalAlloc(sd);
+  LPWSTR sddl;
+  if (!::ConvertSecurityDescriptorToStringSecurityDescriptor(
+          sd_ptr.get(), SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &sddl,
+          nullptr)) {
+    return std::wstring();
+  }
+  return TakeLocalAlloc(sddl).get();
+}
+
+bool CreateWithDacl(const FilePath& path, const wchar_t* sddl, bool directory) {
+  PSECURITY_DESCRIPTOR sd;
+  if (!::ConvertStringSecurityDescriptorToSecurityDescriptor(
+          sddl, SDDL_REVISION_1, &sd, nullptr)) {
+    return false;
+  }
+  auto sd_ptr = TakeLocalAlloc(sd);
+  SECURITY_ATTRIBUTES security_attr = {};
+  security_attr.nLength = sizeof(security_attr);
+  security_attr.lpSecurityDescriptor = sd_ptr.get();
+  if (directory)
+    return !!::CreateDirectory(path.value().c_str(), &security_attr);
+
+  return ScopedHandle(::CreateFile(path.value().c_str(), GENERIC_ALL, 0,
+                                   &security_attr, CREATE_ALWAYS, 0, nullptr))
+      .IsValid();
+}
+
+}  // namespace
+
+TEST(SecurityUtilTest, GrantAccessToPathErrorCase) {
+  ScopedTempDir temp_dir;
+  auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
+  ASSERT_TRUE(sids);
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FilePath path = temp_dir.GetPath().Append(L"test");
+  EXPECT_FALSE(
+      GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE));
+  ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
+  EXPECT_TRUE(
+      GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE));
+  path = temp_dir.GetPath().Append(L"test_nowritedac");
+  ASSERT_TRUE(CreateWithDacl(path, kNoWriteDacDacl, false));
+  EXPECT_FALSE(
+      GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE));
+}
+
+TEST(SecurityUtilTest, GrantAccessToPathFile) {
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FilePath path = temp_dir.GetPath().Append(L"test");
+  ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
+  EXPECT_EQ(kBaseDacl, GetFileDacl(path));
+  auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
+  ASSERT_TRUE(sids);
+  EXPECT_TRUE(
+      GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE));
+  EXPECT_EQ(kTest1Dacl, GetFileDacl(path));
+  auto sids2 = Sid::FromSddlStringVector({L"S-1-5-11", L"BA"});
+  ASSERT_TRUE(sids2);
+  EXPECT_TRUE(GrantAccessToPath(path, *sids2, GENERIC_ALL, NO_INHERITANCE));
+  EXPECT_EQ(kTest2Dacl, GetFileDacl(path));
+}
+
+TEST(SecurityUtilTest, GrantAccessToPathDirectory) {
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FilePath path = temp_dir.GetPath().Append(L"testdir");
+  ASSERT_TRUE(CreateWithDacl(path, kBaseDirDacl, true));
+  EXPECT_EQ(kBaseDirDacl, GetFileDacl(path));
+  FilePath file_path = path.Append(L"test");
+  File file(file_path, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
+  ASSERT_TRUE(file.IsValid());
+  file.Close();
+  EXPECT_EQ(kTest1InheritedDacl, GetFileDacl(file_path));
+  auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
+  ASSERT_TRUE(sids);
+  EXPECT_TRUE(GrantAccessToPath(path, *sids, FILE_GENERIC_READ,
+                                OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE));
+  EXPECT_EQ(kBaseDir2Dacl, GetFileDacl(path));
+  EXPECT_EQ(kTest2InheritedDacl, GetFileDacl(file_path));
+}
+
+}  // namespace win
+}  // namespace base
\ No newline at end of file
diff --git a/base/win/sid.cc b/base/win/sid.cc
new file mode 100644
index 0000000..fe179d3
--- /dev/null
+++ b/base/win/sid.cc
@@ -0,0 +1,304 @@
+// 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 "base/win/sid.h"
+
+#include <windows.h>
+
+#include <sddl.h>
+#include <stdlib.h>
+
+#include "base/check.h"
+#include "base/notreached.h"
+#include "base/rand_util.h"
+#include "base/stl_util.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/scoped_localalloc.h"
+#include "base/win/windows_version.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+Optional<DWORD> WellKnownCapabilityToRid(WellKnownCapability capability) {
+  switch (capability) {
+    case WellKnownCapability::kInternetClient:
+      return SECURITY_CAPABILITY_INTERNET_CLIENT;
+    case WellKnownCapability::kInternetClientServer:
+      return SECURITY_CAPABILITY_INTERNET_CLIENT_SERVER;
+    case WellKnownCapability::kPrivateNetworkClientServer:
+      return SECURITY_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER;
+    case WellKnownCapability::kPicturesLibrary:
+      return SECURITY_CAPABILITY_PICTURES_LIBRARY;
+    case WellKnownCapability::kVideosLibrary:
+      return SECURITY_CAPABILITY_VIDEOS_LIBRARY;
+    case WellKnownCapability::kMusicLibrary:
+      return SECURITY_CAPABILITY_MUSIC_LIBRARY;
+    case WellKnownCapability::kDocumentsLibrary:
+      return SECURITY_CAPABILITY_DOCUMENTS_LIBRARY;
+    case WellKnownCapability::kEnterpriseAuthentication:
+      return SECURITY_CAPABILITY_ENTERPRISE_AUTHENTICATION;
+    case WellKnownCapability::kSharedUserCertificates:
+      return SECURITY_CAPABILITY_SHARED_USER_CERTIFICATES;
+    case WellKnownCapability::kRemovableStorage:
+      return SECURITY_CAPABILITY_REMOVABLE_STORAGE;
+    case WellKnownCapability::kAppointments:
+      return SECURITY_CAPABILITY_APPOINTMENTS;
+    case WellKnownCapability::kContacts:
+      return SECURITY_CAPABILITY_CONTACTS;
+  }
+  return nullopt;
+}
+
+Optional<WELL_KNOWN_SID_TYPE> WellKnownSidToEnum(WellKnownSid sid) {
+  switch (sid) {
+    case WellKnownSid::kNull:
+      return WinNullSid;
+    case WellKnownSid::kWorld:
+      return WinWorldSid;
+    case WellKnownSid::kCreatorOwner:
+      return WinCreatorOwnerSid;
+    case WellKnownSid::kNetwork:
+      return WinNetworkSid;
+    case WellKnownSid::kBatch:
+      return WinBatchSid;
+    case WellKnownSid::kInteractive:
+      return WinInteractiveSid;
+    case WellKnownSid::kService:
+      return WinServiceSid;
+    case WellKnownSid::kAnonymous:
+      return WinAnonymousSid;
+    case WellKnownSid::kSelf:
+      return WinSelfSid;
+    case WellKnownSid::kAuthenticatedUser:
+      return WinAuthenticatedUserSid;
+    case WellKnownSid::kRestricted:
+      return WinRestrictedCodeSid;
+    case WellKnownSid::kLocalSystem:
+      return WinLocalSystemSid;
+    case WellKnownSid::kLocalService:
+      return WinLocalServiceSid;
+    case WellKnownSid::kNetworkService:
+      return WinNetworkServiceSid;
+    case WellKnownSid::kBuiltinAdministrators:
+      return WinBuiltinAdministratorsSid;
+    case WellKnownSid::kBuiltinUsers:
+      return WinBuiltinUsersSid;
+    case WellKnownSid::kBuiltinGuests:
+      return WinBuiltinGuestsSid;
+    case WellKnownSid::kUntrustedLabel:
+      return WinUntrustedLabelSid;
+    case WellKnownSid::kLowLabel:
+      return WinLowLabelSid;
+    case WellKnownSid::kMediumLabel:
+      return WinMediumLabelSid;
+    case WellKnownSid::kHighLabel:
+      return WinHighLabelSid;
+    case WellKnownSid::kSystemLabel:
+      return WinSystemLabelSid;
+    case WellKnownSid::kWriteRestricted:
+      return WinWriteRestrictedCodeSid;
+    case WellKnownSid::kCreatorOwnerRights:
+      return WinCreatorOwnerRightsSid;
+    case WellKnownSid::kAllApplicationPackages:
+      return WinBuiltinAnyPackageSid;
+    case WellKnownSid::kAllRestrictedApplicationPackages:
+      // This should be handled by FromKnownSid.
+      NOTREACHED();
+      break;
+  }
+  return nullopt;
+}
+
+Optional<Sid> FromSubAuthorities(PSID_IDENTIFIER_AUTHORITY identifier_authority,
+                                 BYTE sub_authority_count,
+                                 PDWORD sub_authorities) {
+  BYTE sid[SECURITY_MAX_SID_SIZE];
+  if (!::InitializeSid(sid, identifier_authority, sub_authority_count))
+    return nullopt;
+
+  for (DWORD index = 0; index < sub_authority_count; ++index) {
+    PDWORD sub_authority = ::GetSidSubAuthority(sid, index);
+    *sub_authority = sub_authorities[index];
+  }
+  return Sid::FromPSID(sid);
+}
+
+Optional<std::vector<Sid>> FromStringVector(
+    const std::vector<const wchar_t*>& strs,
+    decltype(Sid::FromSddlString)* create_sid) {
+  std::vector<Sid> converted_sids;
+  converted_sids.reserve(strs.size());
+  for (const wchar_t* str : strs) {
+    auto sid = create_sid(str);
+    if (!sid)
+      return nullopt;
+    converted_sids.push_back(std::move(*sid));
+  }
+  return converted_sids;
+}
+
+}  // namespace
+
+Sid::Sid(const void* sid, size_t length)
+    : sid_(static_cast<const char*>(sid),
+           static_cast<const char*>(sid) + length) {}
+
+Optional<Sid> Sid::FromKnownCapability(WellKnownCapability capability) {
+  Optional<DWORD> capability_rid = WellKnownCapabilityToRid(capability);
+  if (!capability_rid)
+    return nullopt;
+  SID_IDENTIFIER_AUTHORITY capability_authority = {
+      SECURITY_APP_PACKAGE_AUTHORITY};
+  DWORD sub_authorities[] = {SECURITY_CAPABILITY_BASE_RID, *capability_rid};
+  return FromSubAuthorities(&capability_authority, size(sub_authorities),
+                            sub_authorities);
+}
+
+Optional<Sid> Sid::FromNamedCapability(const wchar_t* capability_name) {
+  DCHECK_GE(GetVersion(), Version::WIN10);
+
+  if (!capability_name || !*capability_name)
+    return nullopt;
+
+  typedef decltype(
+      ::DeriveCapabilitySidsFromName)* DeriveCapabilitySidsFromNameFunc;
+  static const DeriveCapabilitySidsFromNameFunc derive_capability_sids =
+      []() -> DeriveCapabilitySidsFromNameFunc {
+    HMODULE module = GetModuleHandle(L"api-ms-win-security-base-l1-2-2.dll");
+    if (!module)
+      return nullptr;
+
+    return reinterpret_cast<DeriveCapabilitySidsFromNameFunc>(
+        ::GetProcAddress(module, "DeriveCapabilitySidsFromName"));
+  }();
+  if (!derive_capability_sids)
+    return nullopt;
+
+  // Pre-reserve some space for SID deleters.
+  std::vector<ScopedLocalAlloc> deleter_list;
+  deleter_list.reserve(16);
+
+  PSID* capability_groups = nullptr;
+  DWORD capability_group_count = 0;
+  PSID* capability_sids = nullptr;
+  DWORD capability_sid_count = 0;
+
+  if (!derive_capability_sids(capability_name, &capability_groups,
+                              &capability_group_count, &capability_sids,
+                              &capability_sid_count)) {
+    return nullopt;
+  }
+
+  deleter_list.emplace_back(capability_groups);
+  deleter_list.emplace_back(capability_sids);
+
+  for (DWORD i = 0; i < capability_group_count; ++i) {
+    deleter_list.emplace_back(capability_groups[i]);
+  }
+  for (DWORD i = 0; i < capability_sid_count; ++i) {
+    deleter_list.emplace_back(capability_sids[i]);
+  }
+
+  if (capability_sid_count < 1)
+    return nullopt;
+
+  return FromPSID(capability_sids[0]);
+}
+
+Optional<Sid> Sid::FromKnownSid(WellKnownSid type) {
+  if (type == WellKnownSid::kAllRestrictedApplicationPackages) {
+    SID_IDENTIFIER_AUTHORITY package_authority = {
+        SECURITY_APP_PACKAGE_AUTHORITY};
+    DWORD sub_authorities[] = {SECURITY_APP_PACKAGE_BASE_RID,
+                               SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE};
+    return FromSubAuthorities(&package_authority, 2, sub_authorities);
+  }
+
+  BYTE sid[SECURITY_MAX_SID_SIZE];
+  DWORD size_sid = SECURITY_MAX_SID_SIZE;
+  Optional<WELL_KNOWN_SID_TYPE> known_sid = WellKnownSidToEnum(type);
+  if (!known_sid)
+    return nullopt;
+  if (!::CreateWellKnownSid(*known_sid, nullptr, sid, &size_sid))
+    return nullopt;
+
+  return Sid(sid, size_sid);
+}
+
+Optional<Sid> Sid::FromSddlString(const wchar_t* sddl_sid) {
+  PSID psid = nullptr;
+  if (!::ConvertStringSidToSid(sddl_sid, &psid))
+    return nullopt;
+  return FromPSID(TakeLocalAlloc(psid).get());
+}
+
+Optional<Sid> Sid::FromPSID(PSID sid) {
+  DCHECK(sid);
+  if (!sid || !::IsValidSid(sid))
+    return nullopt;
+  return Sid(sid, ::GetLengthSid(sid));
+}
+
+Optional<Sid> Sid::GenerateRandomSid() {
+  SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_NULL_SID_AUTHORITY};
+  DWORD sub_authorities[4] = {};
+  RandBytes(&sub_authorities, sizeof(sub_authorities));
+  return FromSubAuthorities(&package_authority, _countof(sub_authorities),
+                            sub_authorities);
+}
+
+Optional<Sid> Sid::CurrentUser() {
+  // Get the current token.
+  HANDLE token = nullptr;
+  if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
+    return nullopt;
+  ScopedHandle token_scoped(token);
+
+  char user_buffer[sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE];
+  DWORD size = sizeof(user_buffer);
+
+  if (!::GetTokenInformation(token, TokenUser, user_buffer, size, &size))
+    return nullopt;
+
+  TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_buffer);
+  if (!user->User.Sid)
+    return nullopt;
+  return Sid::FromPSID(user->User.Sid);
+}
+
+Optional<Sid> Sid::FromIntegrityLevel(DWORD integrity_level) {
+  SID_IDENTIFIER_AUTHORITY package_authority = {
+      SECURITY_MANDATORY_LABEL_AUTHORITY};
+  return FromSubAuthorities(&package_authority, 1, &integrity_level);
+}
+
+Optional<std::vector<Sid>> Sid::FromSddlStringVector(
+    const std::vector<const wchar_t*>& sddl_sids) {
+  return FromStringVector(sddl_sids, Sid::FromSddlString);
+}
+
+Optional<std::vector<Sid>> Sid::FromNamedCapabilityVector(
+    const std::vector<const wchar_t*>& capability_names) {
+  return FromStringVector(capability_names, Sid::FromNamedCapability);
+}
+
+Sid::Sid(Sid&& sid) = default;
+Sid::~Sid() = default;
+
+PSID Sid::GetPSID() const {
+  return const_cast<char*>(sid_.data());
+}
+
+// Converts the SID to an SDDL format string.
+Optional<std::wstring> Sid::ToSddlString() const {
+  LPWSTR sid = nullptr;
+  if (!::ConvertSidToStringSid(GetPSID(), &sid))
+    return nullopt;
+  return TakeLocalAlloc(sid).get();
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/sid.h b/base/win/sid.h
new file mode 100644
index 0000000..1502da21
--- /dev/null
+++ b/base/win/sid.h
@@ -0,0 +1,120 @@
+// 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 BASE_WIN_SID_H_
+#define BASE_WIN_SID_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "base/win/windows_types.h"
+
+namespace base {
+namespace win {
+
+// Known capabilities defined in Windows 8.
+enum class WellKnownCapability {
+  kInternetClient,
+  kInternetClientServer,
+  kPrivateNetworkClientServer,
+  kPicturesLibrary,
+  kVideosLibrary,
+  kMusicLibrary,
+  kDocumentsLibrary,
+  kEnterpriseAuthentication,
+  kSharedUserCertificates,
+  kRemovableStorage,
+  kAppointments,
+  kContacts
+};
+
+// A subset of well known SIDs to create.
+enum class WellKnownSid {
+  kNull,
+  kWorld,
+  kCreatorOwner,
+  kNetwork,
+  kBatch,
+  kInteractive,
+  kService,
+  kAnonymous,
+  kSelf,
+  kAuthenticatedUser,
+  kRestricted,
+  kLocalSystem,
+  kLocalService,
+  kNetworkService,
+  kBuiltinAdministrators,
+  kBuiltinUsers,
+  kBuiltinGuests,
+  kUntrustedLabel,
+  kLowLabel,
+  kMediumLabel,
+  kHighLabel,
+  kSystemLabel,
+  kWriteRestricted,
+  kCreatorOwnerRights,
+  kAllApplicationPackages,
+  kAllRestrictedApplicationPackages
+};
+
+// This class is used to hold and generate SIDs.
+class BASE_EXPORT Sid {
+ public:
+  // Create a Sid from an AppContainer capability name. The name can be
+  // completely arbitrary. Only available on Windows 10 and above.
+  static Optional<Sid> FromNamedCapability(const wchar_t* capability_name);
+
+  // Create a Sid from a known capability enumeration value. The Sids
+  // match with the list defined in Windows 8.
+  static Optional<Sid> FromKnownCapability(WellKnownCapability capability);
+
+  // Create a SID from a well-known type.
+  static Optional<Sid> FromKnownSid(WellKnownSid type);
+
+  // Create a Sid from a SDDL format string, such as S-1-1-0.
+  static Optional<Sid> FromSddlString(const wchar_t* sddl_sid);
+
+  // Create a Sid from a PSID pointer.
+  static Optional<Sid> FromPSID(const PSID sid);
+
+  // Generate a random SID value.
+  static Optional<Sid> GenerateRandomSid();
+
+  // Create a SID for the current user.
+  static Optional<Sid> CurrentUser();
+
+  // Create a SID for an integrity level RID.
+  static Optional<Sid> FromIntegrityLevel(DWORD integrity_level);
+
+  // Create a vector of SIDs from a vector of SDDL format strings.
+  static Optional<std::vector<Sid>> FromSddlStringVector(
+      const std::vector<const wchar_t*>& sddl_sids);
+
+  // Create a vector of SIDs from a vector of capability names.
+  static Optional<std::vector<Sid>> FromNamedCapabilityVector(
+      const std::vector<const wchar_t*>& capability_names);
+
+  Sid(const Sid&) = delete;
+  Sid& operator=(const Sid&) = delete;
+  Sid(Sid&& sid);
+  ~Sid();
+
+  // Returns sid as a PSID. This should only be used temporarily while the Sid
+  // is still within scope.
+  PSID GetPSID() const;
+
+  // Converts the SID to a SDDL format string.
+  Optional<std::wstring> ToSddlString() const;
+
+ private:
+  Sid(const void* sid, size_t length);
+  std::vector<char> sid_;
+};
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_SID_H_
diff --git a/base/win/sid_unittest.cc b/base/win/sid_unittest.cc
new file mode 100644
index 0000000..85ddab04
--- /dev/null
+++ b/base/win/sid_unittest.cc
@@ -0,0 +1,292 @@
+// 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.
+
+// This file contains unit tests for the sid class.
+
+#include "base/win/sid.h"
+
+#include <algorithm>
+
+#include <windows.h>
+
+#include <sddl.h>
+
+#include "base/optional.h"
+#include "base/win/atl.h"
+#include "base/win/scoped_localalloc.h"
+#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+bool EqualSid(const Optional<Sid>& sid, const ATL::CSid& compare_sid) {
+  if (!sid)
+    return false;
+  return !!::EqualSid(sid->GetPSID(), const_cast<SID*>(compare_sid.GetPSID()));
+}
+
+bool EqualSid(const Sid& sid, const wchar_t* sddl_sid) {
+  PSID compare_sid;
+  if (!::ConvertStringSidToSid(sddl_sid, &compare_sid))
+    return false;
+  auto sid_ptr = TakeLocalAlloc(compare_sid);
+  return !!::EqualSid(sid.GetPSID(), sid_ptr.get());
+}
+
+bool EqualSid(const Optional<Sid>& sid, const wchar_t* sddl_sid) {
+  if (!sid)
+    return false;
+  return EqualSid(sid.value(), sddl_sid);
+}
+
+bool EqualSid(const Optional<Sid>& sid, const Optional<Sid>& compare_sid) {
+  if (!sid || !compare_sid)
+    return false;
+  return !!::EqualSid(sid->GetPSID(), compare_sid->GetPSID());
+}
+
+bool EqualSid(const Optional<Sid>& sid, WELL_KNOWN_SID_TYPE known_sid) {
+  if (!sid)
+    return false;
+  char known_sid_buffer[SECURITY_MAX_SID_SIZE] = {};
+  DWORD size = SECURITY_MAX_SID_SIZE;
+  if (!::CreateWellKnownSid(known_sid, nullptr, known_sid_buffer, &size))
+    return false;
+
+  return !!::EqualSid(sid->GetPSID(), known_sid_buffer);
+}
+
+bool TestSidVector(Optional<std::vector<Sid>> sids,
+                   const std::vector<const wchar_t*> sddl) {
+  if (!sids)
+    return false;
+  if (sids->size() != sddl.size())
+    return false;
+  return std::equal(
+      sids->begin(), sids->end(), sddl.begin(),
+      [](const Sid& sid, const wchar_t* sddl) { return EqualSid(sid, sddl); });
+}
+
+bool TestFromSddlStringVector(const std::vector<const wchar_t*> sddl) {
+  return TestSidVector(Sid::FromSddlStringVector(sddl), sddl);
+}
+
+struct KnownCapabilityTestEntry {
+  WellKnownCapability capability;
+  const wchar_t* sddl_sid;
+};
+
+struct NamedCapabilityTestEntry {
+  const wchar_t* capability_name;
+  const wchar_t* sddl_sid;
+};
+
+struct KnownSidTestEntry {
+  WellKnownSid sid;
+  WELL_KNOWN_SID_TYPE well_known_sid;
+};
+
+}  // namespace
+
+// Tests the creation of a Sid.
+TEST(SidTest, Initializers) {
+  ATL::CSid sid_world = ATL::Sids::World();
+  PSID sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
+
+  // Check the PSID constructor.
+  Optional<Sid> sid_sid_star = Sid::FromPSID(sid_world_pointer);
+  ASSERT_TRUE(EqualSid(sid_sid_star, sid_world));
+
+  char invalid_sid[16] = {};
+  ASSERT_FALSE(Sid::FromPSID(invalid_sid));
+
+  Optional<Sid> sid_sddl = Sid::FromSddlString(L"S-1-1-0");
+  ASSERT_TRUE(sid_sddl);
+  ASSERT_TRUE(EqualSid(sid_sddl, sid_world));
+}
+
+TEST(SidTest, KnownCapability) {
+  if (GetVersion() < Version::WIN8)
+    return;
+
+  const KnownCapabilityTestEntry capabilities[] = {
+      {WellKnownCapability::kInternetClient, L"S-1-15-3-1"},
+      {WellKnownCapability::kInternetClientServer, L"S-1-15-3-2"},
+      {WellKnownCapability::kPrivateNetworkClientServer, L"S-1-15-3-3"},
+      {WellKnownCapability::kPicturesLibrary, L"S-1-15-3-4"},
+      {WellKnownCapability::kVideosLibrary, L"S-1-15-3-5"},
+      {WellKnownCapability::kMusicLibrary, L"S-1-15-3-6"},
+      {WellKnownCapability::kDocumentsLibrary, L"S-1-15-3-7"},
+      {WellKnownCapability::kEnterpriseAuthentication, L"S-1-15-3-8"},
+      {WellKnownCapability::kSharedUserCertificates, L"S-1-15-3-9"},
+      {WellKnownCapability::kRemovableStorage, L"S-1-15-3-10"},
+      {WellKnownCapability::kAppointments, L"S-1-15-3-11"},
+      {WellKnownCapability::kContacts, L"S-1-15-3-12"},
+  };
+
+  for (auto capability : capabilities) {
+    EXPECT_TRUE(EqualSid(Sid::FromKnownCapability(capability.capability),
+                         capability.sddl_sid))
+        << "Known Capability: " << capability.sddl_sid;
+  }
+}
+
+TEST(SidTest, NamedCapability) {
+  if (GetVersion() < Version::WIN10)
+    return;
+
+  EXPECT_FALSE(Sid::FromNamedCapability(nullptr));
+  EXPECT_FALSE(Sid::FromNamedCapability(L""));
+
+  const NamedCapabilityTestEntry capabilities[] = {
+      {L"internetClient", L"S-1-15-3-1"},
+      {L"internetClientServer", L"S-1-15-3-2"},
+      {L"registryRead",
+       L"S-1-15-3-1024-1065365936-1281604716-3511738428-"
+       "1654721687-432734479-3232135806-4053264122-3456934681"},
+      {L"lpacCryptoServices",
+       L"S-1-15-3-1024-3203351429-2120443784-2872670797-"
+       "1918958302-2829055647-4275794519-765664414-2751773334"},
+      {L"enterpriseAuthentication", L"S-1-15-3-8"},
+      {L"privateNetworkClientServer", L"S-1-15-3-3"}};
+
+  for (auto capability : capabilities) {
+    EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name),
+                         capability.sddl_sid))
+        << "Named Capability: " << capability.sddl_sid;
+  }
+}
+
+TEST(SidTest, KnownSids) {
+  const KnownSidTestEntry known_sids[] = {
+      {WellKnownSid::kNull, ::WinNullSid},
+      {WellKnownSid::kWorld, ::WinWorldSid},
+      {WellKnownSid::kCreatorOwner, ::WinCreatorOwnerSid},
+      {WellKnownSid::kNetwork, ::WinNetworkSid},
+      {WellKnownSid::kBatch, ::WinBatchSid},
+      {WellKnownSid::kInteractive, ::WinInteractiveSid},
+      {WellKnownSid::kService, ::WinServiceSid},
+      {WellKnownSid::kAnonymous, ::WinAnonymousSid},
+      {WellKnownSid::kSelf, ::WinSelfSid},
+      {WellKnownSid::kAuthenticatedUser, ::WinAuthenticatedUserSid},
+      {WellKnownSid::kRestricted, ::WinRestrictedCodeSid},
+      {WellKnownSid::kLocalSystem, ::WinLocalSystemSid},
+      {WellKnownSid::kLocalService, ::WinLocalServiceSid},
+      {WellKnownSid::kNetworkService, ::WinNetworkServiceSid},
+      {WellKnownSid::kBuiltinAdministrators, ::WinBuiltinAdministratorsSid},
+      {WellKnownSid::kBuiltinUsers, ::WinBuiltinUsersSid},
+      {WellKnownSid::kBuiltinGuests, ::WinBuiltinGuestsSid},
+      {WellKnownSid::kUntrustedLabel, ::WinUntrustedLabelSid},
+      {WellKnownSid::kLowLabel, ::WinLowLabelSid},
+      {WellKnownSid::kMediumLabel, ::WinMediumLabelSid},
+      {WellKnownSid::kHighLabel, ::WinHighLabelSid},
+      {WellKnownSid::kSystemLabel, ::WinSystemLabelSid},
+      {WellKnownSid::kWriteRestricted, ::WinWriteRestrictedCodeSid},
+      {WellKnownSid::kCreatorOwnerRights, ::WinCreatorOwnerRightsSid}};
+
+  for (auto known_sid : known_sids) {
+    EXPECT_TRUE(
+        EqualSid(Sid::FromKnownSid(known_sid.sid), known_sid.well_known_sid))
+        << "Known Sid: " << static_cast<int>(known_sid.sid);
+  }
+
+  if (GetVersion() < Version::WIN8)
+    return;
+
+  EXPECT_TRUE(EqualSid(Sid::FromKnownSid(WellKnownSid::kAllApplicationPackages),
+                       ::WinBuiltinAnyPackageSid));
+
+  if (GetVersion() < Version::WIN10)
+    return;
+
+  EXPECT_TRUE(EqualSid(
+      Sid::FromKnownSid(WellKnownSid::kAllRestrictedApplicationPackages),
+      L"S-1-15-2-2"));
+}
+
+TEST(SidTest, SddlString) {
+  Optional<Sid> sid_sddl = Sid::FromSddlString(L"S-1-1-0");
+  ASSERT_TRUE(sid_sddl);
+  Optional<std::wstring> sddl_str = sid_sddl->ToSddlString();
+  ASSERT_TRUE(sddl_str);
+  ASSERT_EQ(L"S-1-1-0", *sddl_str);
+  ASSERT_FALSE(Sid::FromSddlString(L"X-1-1-0"));
+  ASSERT_FALSE(Sid::FromSddlString(L""));
+}
+
+TEST(SidTest, RandomSid) {
+  Optional<Sid> sid1 = Sid::GenerateRandomSid();
+  ASSERT_TRUE(sid1);
+  Optional<Sid> sid2 = Sid::GenerateRandomSid();
+  ASSERT_TRUE(sid2);
+  ASSERT_FALSE(EqualSid(sid1, sid2));
+}
+
+TEST(SidTest, CurrentUser) {
+  Optional<Sid> sid1 = Sid::CurrentUser();
+  ASSERT_TRUE(sid1);
+  std::wstring user_sid;
+  ASSERT_TRUE(GetUserSidString(&user_sid));
+  ASSERT_TRUE(EqualSid(sid1, user_sid.c_str()));
+}
+
+TEST(SidTest, FromIntegrityLevel) {
+  ASSERT_TRUE(EqualSid(
+      Sid::FromIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID), L"S-1-16-0"));
+  ASSERT_TRUE(EqualSid(Sid::FromIntegrityLevel(SECURITY_MANDATORY_LOW_RID),
+                       L"S-1-16-4096"));
+  ASSERT_TRUE(EqualSid(Sid::FromIntegrityLevel(SECURITY_MANDATORY_MEDIUM_RID),
+                       L"S-1-16-8192"));
+  ASSERT_TRUE(
+      EqualSid(Sid::FromIntegrityLevel(SECURITY_MANDATORY_MEDIUM_PLUS_RID),
+               L"S-1-16-8448"));
+  ASSERT_TRUE(EqualSid(Sid::FromIntegrityLevel(SECURITY_MANDATORY_HIGH_RID),
+                       L"S-1-16-12288"));
+  ASSERT_TRUE(EqualSid(Sid::FromIntegrityLevel(SECURITY_MANDATORY_SYSTEM_RID),
+                       L"S-1-16-16384"));
+  ASSERT_TRUE(EqualSid(Sid::FromIntegrityLevel(1234), L"S-1-16-1234"));
+}
+
+TEST(SidTest, FromSddlStringVector) {
+  ASSERT_TRUE(
+      TestFromSddlStringVector({L"S-1-1-0", L"S-1-15-2-2", L"S-1-15-3-2"}));
+  ASSERT_FALSE(
+      TestFromSddlStringVector({L"S-1-1-0", L"X-1-15-2-2", L"S-1-15-3-2"}));
+  ASSERT_FALSE(TestFromSddlStringVector({L""}));
+  ASSERT_FALSE(TestFromSddlStringVector({nullptr}));
+  ASSERT_FALSE(TestFromSddlStringVector({L"S-1-1-0", nullptr}));
+  ASSERT_TRUE(TestFromSddlStringVector({}));
+}
+
+TEST(SidTest, FromNamedCapabilityVector) {
+  if (GetVersion() < Version::WIN10)
+    return;
+  std::vector<const wchar_t*> capabilities = {L"internetClient",
+                                              L"internetClientServer",
+                                              L"registryRead",
+                                              L"lpacCryptoServices",
+                                              L"enterpriseAuthentication",
+                                              L"privateNetworkClientServer"};
+  std::vector<const wchar_t*> sddl_caps = {
+      L"S-1-15-3-1",
+      L"S-1-15-3-2",
+      L"S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-"
+      L"3232135806-4053264122-3456934681",
+      L"S-1-15-3-1024-3203351429-2120443784-2872670797-1918958302-2829055647-"
+      L"4275794519-765664414-2751773334",
+      L"S-1-15-3-8",
+      L"S-1-15-3-3"};
+  ASSERT_TRUE(
+      TestSidVector(Sid::FromNamedCapabilityVector(capabilities), sddl_caps));
+  ASSERT_FALSE(Sid::FromNamedCapabilityVector({L""}));
+  ASSERT_FALSE(Sid::FromNamedCapabilityVector({L"abc", nullptr}));
+  ASSERT_TRUE(Sid::FromNamedCapabilityVector({}));
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/windows_types.h b/base/win/windows_types.h
index 17a20aad..b1f30eb 100644
--- a/base/win/windows_types.h
+++ b/base/win/windows_types.h
@@ -122,6 +122,8 @@
 
 typedef PVOID PSID;
 
+typedef HANDLE HLOCAL;
+
 // Declare Chrome versions of some Windows structures. These are needed for
 // when we need a concrete type but don't want to pull in Windows.h. We can't
 // declare the Windows types so we declare our types and cast to the Windows
@@ -239,6 +241,9 @@
 WINBASEAPI BOOL WINAPI TerminateProcess(_In_ HANDLE hProcess,
                                         _In_ UINT uExitCode);
 
+// Support for a deleter for LocalAlloc memory.
+WINBASEAPI HLOCAL WINAPI LocalFree(_In_ HLOCAL hMem);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 57c55da..52195e9 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -108,6 +108,7 @@
 RENDER_TEST_MODEL_SDK_CONFIGS = {
     # Android x86 emulator.
     'Android SDK built for x86': [23],
+    'Pixel 2': [28],
 }
 
 _BATCH_SUFFIX = '_batch'
diff --git a/build/fuchsia/amber_repo.py b/build/fuchsia/amber_repo.py
index 5ec1532..3b057fd 100644
--- a/build/fuchsia/amber_repo.py
+++ b/build/fuchsia/amber_repo.py
@@ -10,7 +10,8 @@
 import subprocess
 import tempfile
 import time
-import urllib2
+
+from six.moves import urllib
 
 
 # Maximum amount of time to block while waiting for "pm serve" to come up.
@@ -58,9 +59,10 @@
     timeout = time.time() + _PM_SERVE_LIVENESS_TIMEOUT_SECS
     while True:
       try:
-        urllib2.urlopen('http://localhost:%d' % serve_port, timeout=1).read()
+        urllib.request.urlopen('http://localhost:%d' % serve_port,
+                               timeout=1).read()
         break
-      except urllib2.URLError:
+      except urllib.error.URLError:
         logging.info('Waiting until \'pm serve\' is up...')
 
       if time.time() >= timeout:
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 8747a79eb8..eb5f51e 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-4.20210429.1.1
+4.20210429.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 8747a79eb8..eb5f51e 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-4.20210429.1.1
+4.20210429.2.1
diff --git a/build/fuchsia/qemu_target.py b/build/fuchsia/qemu_target.py
index 057ea77..236c41d 100644
--- a/build/fuchsia/qemu_target.py
+++ b/build/fuchsia/qemu_target.py
@@ -7,8 +7,8 @@
 import boot_data
 import common
 import emu_target
+import hashlib
 import logging
-import md5
 import os
 import platform
 import qemu_image
@@ -195,7 +195,7 @@
     return qemu_command
 
 def _ComputeFileHash(filename):
-  hasher = md5.new()
+  hasher = hashlib.md5()
   with open(filename, 'rb') as f:
     buf = f.read(4096)
     while buf:
diff --git a/build/fuchsia/run_test_package.py b/build/fuchsia/run_test_package.py
index 609a4ed..eb4b0e1 100644
--- a/build/fuchsia/run_test_package.py
+++ b/build/fuchsia/run_test_package.py
@@ -86,8 +86,7 @@
 
     read_pipe, write_pipe = os.pipe()
 
-    # Disable buffering for the stream to make sure there is no delay in logs.
-    self._output_stream = os.fdopen(write_pipe, 'w', 0)
+    self._output_stream = os.fdopen(write_pipe, 'w', 1)
     self._thread = threading.Thread(target=self._Run)
     self._thread.start()
 
@@ -118,9 +117,11 @@
           primary_fd = None
 
       for fileno in rlist:
-        line = streams_by_fd[fileno].readline()
+        # TODO(chonggu): Encode streams with 'utf-8' instead of decoding each
+        # line read once we drop Python 2 support.
+        line = streams_by_fd[fileno].readline().decode('utf-8')
         if line:
-          self._output_stream.write(line + '\n')
+          self._output_stream.write(line)
         else:
           del streams_by_fd[fileno]
           if fileno == primary_fd:
@@ -136,9 +137,11 @@
         break
 
       for fileno in rlist:
-        line = streams_by_fd[fileno].readline()
+        # TODO(chonggu): Switch to encoding='utf-8' once we drop Python 2
+        # support.
+        line = streams_by_fd[fileno].readline().decode('utf-8')
         if line:
-          self._output_stream.write(line + '\n')
+          self._output_stream.write(line)
         else:
           del streams_by_fd[fileno]
 
diff --git a/build/fuchsia/symbolizer.py b/build/fuchsia/symbolizer.py
index 7db9fc9f..f9bf1e6 100644
--- a/build/fuchsia/symbolizer.py
+++ b/build/fuchsia/symbolizer.py
@@ -86,7 +86,9 @@
   symbolizer_proc = RunSymbolizer(input_file, subprocess.PIPE, build_ids_files)
 
   while True:
-    line = symbolizer_proc.stdout.readline()
+    # TODO(chonggu): Switch to encoding='utf-8' once we drop Python 2
+    # support.
+    line = symbolizer_proc.stdout.readline().decode('utf-8')
     if not line:
       break
 
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index 39f963f..ee494546 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -184,6 +184,7 @@
     chromeos_is_browser_only = false
     ozone_platform = "x11"
     ozone_platform_wayland = false
+    use_clang_coverage = false
   }
 }
 
diff --git a/build/util/lib/common/chrome_test_server_spawner.py b/build/util/lib/common/chrome_test_server_spawner.py
index 6fd6363..9810215e 100644
--- a/build/util/lib/common/chrome_test_server_spawner.py
+++ b/build/util/lib/common/chrome_test_server_spawner.py
@@ -9,7 +9,6 @@
 """
 # pylint: disable=W0702
 
-import BaseHTTPServer
 import json
 import logging
 import os
@@ -19,7 +18,8 @@
 import sys
 import threading
 import time
-import urlparse
+
+from six.moves import BaseHTTPServer, urllib
 
 
 SERVER_TYPES = {
@@ -399,7 +399,7 @@
       pass
 
   def do_POST(self):
-    parsed_path = urlparse.urlparse(self.path)
+    parsed_path = urllib.parse.urlparse(self.path)
     action = parsed_path.path
     _logger.info('Action for POST method is: %s.', action)
     if action == '/start':
@@ -409,9 +409,9 @@
       _logger.info('Encounter unknown request: %s.', action)
 
   def do_GET(self):
-    parsed_path = urlparse.urlparse(self.path)
+    parsed_path = urllib.parse.urlparse(self.path)
     action = parsed_path.path
-    params = urlparse.parse_qs(parsed_path.query, keep_blank_values=1)
+    params = urllib.parse.parse_qs(parsed_path.query, keep_blank_values=1)
     _logger.info('Action for GET method is: %s.', action)
     for param in params:
       _logger.info('%s=%s', param, params[param][0])
diff --git a/buildtools/reclient_cfgs/rewrapper_linux.cfg b/buildtools/reclient_cfgs/rewrapper_linux.cfg
index 042b4f7..86b91e2 100644
--- a/buildtools/reclient_cfgs/rewrapper_linux.cfg
+++ b/buildtools/reclient_cfgs/rewrapper_linux.cfg
@@ -2,4 +2,4 @@
 server_address=unix:///tmp/reproxy.sock
 labels=type=compile,compiler=clang,lang=cpp
 exec_strategy=remote_local_fallback
-inputs=third_party/llvm-build/Release+Asserts
+inputs=third_party/llvm-build/Release+Asserts/bin/clang,third_party/llvm-build/Release+Asserts/bin/clang++,third_party/llvm-build/Release+Asserts/bin/clang-cl,third_party/llvm-build/Release+Asserts/lib/libstdc++.so.6
diff --git a/chrome/VERSION b/chrome/VERSION
index b92db85..f5e7c49 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=92
 MINOR=0
-BUILD=4493
+BUILD=4494
 PATCH=0
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/read_later/ReadLaterContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/read_later/ReadLaterContextMenuTest.java
index 5b1f1dec..6e8f581 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/read_later/ReadLaterContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/read_later/ReadLaterContextMenuTest.java
@@ -43,6 +43,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
@@ -128,6 +129,7 @@
     @Test
     @MediumTest
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
+    @DisabledTest(message = "crbug.com/1204238")
     public void testContextMenuAddToOfflinePage() throws Throwable {
         String url = mTestServer.getServer().getURL(CONTEXT_MENU_TEST_URL);
         mActivityTestRule.loadUrlInNewTab(url);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index a816fdf..d0a02e08 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10461,6 +10461,16 @@
       </message>
     </if>
 
+    <!-- File Handling permission prompt -->
+    <if expr="not is_android">
+      <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT" desc="Permission request shown if the user is opening a file using a PWA with registered file handlers. Follows a prompt: 'This site would like to:'">
+        Open <ph name="FILE_EXTENSIONS">$1<ex>.txt, .csv, .md</ex></ph> files
+      </message>
+      <message name="IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR" desc="Text/punctuation that separates a list of file types/extensions, such as .txt or .csv." meaning="List separator for file extensions.">
+         , '''
+      </message>
+    </if>
+
     <!-- Font Access chooser -->
     <if expr="not is_android">
       <message name="IDS_FONT_ACCESS_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce Local Font Access chooser details to the user in a popup when it is from a website.">
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR.png.sha1
new file mode 100644
index 0000000..6ee6d61
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR.png.sha1
@@ -0,0 +1 @@
+aa286efbaee111ce1a8e37854ff384fa397f929e
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT.png.sha1
new file mode 100644
index 0000000..6ee6d61
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT.png.sha1
@@ -0,0 +1 @@
+aa286efbaee111ce1a8e37854ff384fa397f929e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 0eb84ee..eb66da5 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -2314,10 +2314,10 @@
     Automatically connect to cellular network
   </message>
   <message name="IDS_SETTINGS_INTERNET_NETWORK_MENU_REMOVE" desc="Settings > Internet > Network details > Dot menu: Label for the button to remove an eSIM cellular network">
-    Remove profile
+    Remove Profile
   </message>
   <message name="IDS_SETTINGS_INTERNET_NETWORK_MENU_RENAME" desc="Settings > Internet > Network details > Dot menu: Label for the button to rename an eSIM cellular network">
-    Rename
+    Rename Profile
   </message>
   <message name="IDS_SETTINGS_INTERNET_NETWORK_INSTALL_ERROR_DIALOG_TITLE" desc="Settings > Network > Mobile data > Download > Install error dialog: Title for the dialog prompting the user to enter the confirmation code required to activate the eSIM profile they are attempting to install">
     Set up new network
@@ -2559,6 +2559,9 @@
   <message name="IDS_SETTINGS_INTERNET_ESIM_MOBILE_DATA_NOT_ENABLED_ERROR_TOAST" desc="Message in toast displayed when user tries to set up an eSIM profile when mobile data is not enabled.">
     Enable mobile data to install an eSIM profile
   </message>
+  <message name="IDS_SETTINGS_INTERNET_ESIM_PROFILE_LIMIT_REACHED_ERROR_TOAST" desc="Message in toast displayed when user tries to set up an eSIM profile when they have reached the maximum number of allowed eSIM profiles installed.">
+    You can install up to <ph name="PROFILE_LIMIT">$1<ex>5</ex></ph> eSIM profiles on this device. To add another profile, first remove an existing profile.
+  </message>
 
   <!-- Users Page (OS Settings) -->
   <message name="IDS_SETTINGS_USERS_MODIFIED_BY_OWNER_LABEL" desc="Label saying settings may only be modified by the device owner.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_ESIM_PROFILE_LIMIT_REACHED_ERROR_TOAST.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_ESIM_PROFILE_LIMIT_REACHED_ERROR_TOAST.png.sha1
new file mode 100644
index 0000000..7338580b
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_ESIM_PROFILE_LIMIT_REACHED_ERROR_TOAST.png.sha1
@@ -0,0 +1 @@
+74595df385f9ea105ca2b8d96f53c5bf0b621d19
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_REMOVE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_REMOVE.png.sha1
index 9b8c9704..7712a172 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_REMOVE.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_REMOVE.png.sha1
@@ -1 +1 @@
-ce734260b9493623961fce7c20c73f25eac8096d
\ No newline at end of file
+8199ab7425f2905b7754152da4b7377efc1bbd2e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_RENAME.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_RENAME.png.sha1
index 9b8c9704..7712a172 100644
--- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_RENAME.png.sha1
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_MENU_RENAME.png.sha1
@@ -1 +1 @@
-ce734260b9493623961fce7c20c73f25eac8096d
\ No newline at end of file
+8199ab7425f2905b7754152da4b7377efc1bbd2e
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 5b9b02e..12311e68 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3185,12 +3185,6 @@
      flag_descriptions::kWebglDraftExtensionsName,
      flag_descriptions::kWebglDraftExtensionsDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kEnableWebGLDraftExtensions)},
-#if defined(OS_ANDROID)
-    {"enable-android-autofill-accessibility",
-     flag_descriptions::kAndroidAutofillAccessibilityName,
-     flag_descriptions::kAndroidAutofillAccessibilityDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(features::kAndroidAutofillAccessibility)},
-#endif  // OS_ANDROID
     {"enable-zero-copy", flag_descriptions::kZeroCopyName,
      flag_descriptions::kZeroCopyDescription, kOsAll,
      ENABLE_DISABLE_VALUE_TYPE(blink::switches::kEnableZeroCopy,
@@ -5510,11 +5504,6 @@
      flag_descriptions::kAllowScrollSettingsDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kAllowScrollSettings)},
 
-    {"enable-media-session-notifications",
-     flag_descriptions::kMediaSessionNotificationsName,
-     flag_descriptions::kMediaSessionNotificationsDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kMediaSessionNotification)},
-
     {"enable-neural-stylus-palm-rejection",
      flag_descriptions::kEnableNeuralStylusPalmRejectionName,
      flag_descriptions::kEnableNeuralStylusPalmRejectionDescription, kOsCrOS,
diff --git a/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc b/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
index 614c31f..1ee78ef 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
@@ -7,8 +7,15 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "chrome/browser/apps/app_service/app_platform_metrics.h"
+#include "chrome/browser/apps/app_service/app_platform_metrics_service.h"
 #include "chrome/browser/apps/app_service/app_service_metrics.h"
+#include "chrome/browser/apps/app_service/publishers/borealis_apps.h"
+#include "chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.h"
+#include "chrome/browser/apps/app_service/publishers/crostini_apps.h"
+#include "chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h"
+#include "chrome/browser/apps/app_service/publishers/plugin_vm_apps.h"
 #include "chrome/browser/apps/app_service/publishers/standalone_browser_apps.h"
+#include "chrome/browser/apps/app_service/publishers/web_apps_chromeos.h"
 #include "chrome/browser/apps/app_service/uninstall_dialog.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
@@ -21,7 +28,6 @@
 #include "components/services/app_service/app_service_impl.h"
 #include "components/services/app_service/public/cpp/app_capability_access_cache_wrapper.h"
 #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/user_manager/user.h"
 #include "extensions/common/constants.h"
 
diff --git a/chrome/browser/apps/app_service/app_service_proxy_chromeos.h b/chrome/browser/apps/app_service/app_service_proxy_chromeos.h
index 9b81e6dc..3e04fba 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_chromeos.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_chromeos.h
@@ -6,22 +6,37 @@
 #define CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_CHROMEOS_H_
 
 #include <map>
+#include <memory>
 #include <set>
+#include <string>
 
-#include "chrome/browser/apps/app_service/app_platform_metrics_service.h"
+#include "base/callback.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_base.h"
-#include "chrome/browser/apps/app_service/publishers/borealis_apps.h"
-#include "chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.h"
-#include "chrome/browser/apps/app_service/publishers/crostini_apps.h"
-#include "chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h"
-#include "chrome/browser/apps/app_service/publishers/plugin_vm_apps.h"
-#include "chrome/browser/apps/app_service/publishers/web_apps_chromeos.h"
+#include "chrome/browser/apps/app_service/paused_apps.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
+#include "components/services/app_service/public/mojom/app_service.mojom.h"
+#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "ui/gfx/native_widget_types.h"
+
+class Profile;
+
+namespace gfx {
+class ImageSkia;
+}  // namespace gfx
 
 namespace apps {
 
+class AppPlatformMetricsService;
+class BorealisApps;
+class BuiltInChromeOsApps;
+class CrostiniApps;
+class ExtensionAppsChromeOs;
+class PluginVmApps;
 class StandaloneBrowserApps;
 class UninstallDialog;
+class WebAppsChromeOs;
 
 struct PauseData {
   int hours = 0;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
index 8f21272..62d9c767 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
@@ -4,8 +4,14 @@
 
 #include "chrome/browser/apps/app_service/app_service_proxy_desktop.h"
 
+#include "chrome/browser/apps/app_service/publishers/extension_apps.h"
+#include "chrome/browser/apps/app_service/publishers/web_apps.h"
 #include "components/services/app_service/app_service_impl.h"
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chrome/browser/apps/app_service/fake_lacros_web_apps_host.h"
+#endif
+
 namespace apps {
 
 AppServiceProxy::AppServiceProxy(Profile* profile)
diff --git a/chrome/browser/apps/app_service/app_service_proxy_desktop.h b/chrome/browser/apps/app_service/app_service_proxy_desktop.h
index 9940374f..bd9028a 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_desktop.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_desktop.h
@@ -5,18 +5,25 @@
 #ifndef CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_DESKTOP_H_
 #define CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_DESKTOP_H_
 
-#include "chrome/browser/apps/app_service/app_service_proxy_base.h"
-#include "chrome/browser/apps/app_service/publishers/extension_apps.h"
-#include "chrome/browser/apps/app_service/publishers/web_apps.h"
+#include <memory>
+#include <string>
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "chrome/browser/apps/app_service/fake_lacros_web_apps_host.h"
-#endif
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_base.h"
+#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "ui/gfx/native_widget_types.h"
 
 class Profile;
 
 namespace apps {
 
+class ExtensionApps;
+class WebApps;
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+class FakeLacrosWebAppsHost;
+#endif
+
 // Singleton (per Profile) proxy and cache of an App Service's apps in Chrome
 // browser.
 //
diff --git a/chrome/browser/apps/app_service/notifications_browsertest.cc b/chrome/browser/apps/app_service/notifications_browsertest.cc
index c439ed2..367a31a 100644
--- a/chrome/browser/apps/app_service/notifications_browsertest.cc
+++ b/chrome/browser/apps/app_service/notifications_browsertest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
+#include "chrome/browser/badging/badge_manager.h"
 #include "chrome/browser/badging/badge_manager_factory.h"
 #include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h"
 #include "chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h"
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 56c6dc5f..c9da7df 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3156,7 +3156,9 @@
 }
 
 // TODO(crbug.com/994789): Flaky on MSan, Linux, and ChromeOS.
-#if defined(MEMORY_SANITIZER) || defined(OS_LINUX) || defined(OS_CHROMEOS)
+// TODO(crbug.com/1204299): Flaky on Windows. Consistently failing on Mac.
+#if defined(MEMORY_SANITIZER) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
+    defined(OS_WIN) || defined(OS_MAC)
 #define MAYBE_DownloadCookieIsolation_CrossSession \
   DISABLED_DownloadCookieIsolation_CrossSession
 #else
diff --git a/chrome/browser/ash/apps/intent_helper/common_apps_navigation_throttle.cc b/chrome/browser/ash/apps/intent_helper/common_apps_navigation_throttle.cc
index 1132e11..2b9aa66 100644
--- a/chrome/browser/ash/apps/intent_helper/common_apps_navigation_throttle.cc
+++ b/chrome/browser/ash/apps/intent_helper/common_apps_navigation_throttle.cc
@@ -22,20 +22,19 @@
 #include "chrome/browser/web_applications/components/web_app_id_constants.h"
 #include "chrome/browser/web_applications/components/web_app_tab_helper_base.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/grit/browser_resources.h"
 #include "components/policy/core/common/policy_pref_names.h"
+#include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/jstemplate_builder.h"
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/display/types/display_constants.h"
 
-#include "chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h"
-#include "chrome/grit/browser_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/resource/resource_bundle.h"
-
 namespace apps {
 
 namespace {
diff --git a/chrome/browser/ash/borealis/borealis_context_unittest.cc b/chrome/browser/ash/borealis/borealis_context_unittest.cc
index ccb46a1..a3c471d8 100644
--- a/chrome/browser/ash/borealis/borealis_context_unittest.cc
+++ b/chrome/browser/ash/borealis/borealis_context_unittest.cc
@@ -19,7 +19,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_chunneld_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/drive/drive_integration_service.cc b/chrome/browser/ash/drive/drive_integration_service.cc
index c1cbf59..4233f68 100644
--- a/chrome/browser/ash/drive/drive_integration_service.cc
+++ b/chrome/browser/ash/drive/drive_integration_service.cc
@@ -25,7 +25,6 @@
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "base/unguessable_token.h"
 #include "chrome/browser/ash/drive/drivefs_native_message_host.h"
 #include "chrome/browser/ash/drive/file_system_util.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -601,10 +600,6 @@
         blocking_task_runner_.get()));
   }
 
-  // PowerManagerClient is unset in unit tests.
-  if (chromeos::PowerManagerClient::Get()) {
-    power_manager_observation_.Observe(chromeos::PowerManagerClient::Get());
-  }
   SetEnabled(drive::util::IsDriveEnabledForProfile(profile));
 }
 
@@ -1037,20 +1032,6 @@
   profile_->GetPrefs()->SetBoolean(prefs::kDriveFsPinnedMigrated, true);
 }
 
-void DriveIntegrationService::SuspendImminent(
-    power_manager::SuspendImminent::Reason reason) {
-  // This may a bit racy since it doesn't prevent suspend until the unmount is
-  // completed, instead relying on something else to defer suspending long
-  // enough.
-  RemoveDriveMountPoint();
-}
-
-void DriveIntegrationService::SuspendDone(base::TimeDelta sleep_duration) {
-  if (is_enabled()) {
-    AddDriveMountPoint();
-  }
-}
-
 void DriveIntegrationService::GetQuickAccessItems(
     int max_number,
     GetQuickAccessItemsCallback callback) {
diff --git a/chrome/browser/ash/drive/drive_integration_service.h b/chrome/browser/ash/drive/drive_integration_service.h
index 0caece0a..0e279f5 100644
--- a/chrome/browser/ash/drive/drive_integration_service.h
+++ b/chrome/browser/ash/drive/drive_integration_service.h
@@ -16,9 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
-#include "base/scoped_observation.h"
 #include "chromeos/components/drivefs/drivefs_host.h"
-#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/drive/drive_notification_observer.h"
 #include "components/drive/file_errors.h"
 #include "components/drive/file_system_core_util.h"
@@ -91,8 +89,7 @@
 // that are used to integrate Drive to Chrome. The object of this class is
 // created per-profile.
 class DriveIntegrationService : public KeyedService,
-                                public drivefs::DriveFsHost::MountObserver,
-                                public chromeos::PowerManagerClient::Observer {
+                                public drivefs::DriveFsHost::MountObserver {
  public:
   class PreferenceWatcher;
   using DriveFsMojoListenerFactory = base::RepeatingCallback<
@@ -282,10 +279,6 @@
   // Pin all the files in |files_to_pin| with DriveFS.
   void PinFiles(const std::vector<base::FilePath>& files_to_pin);
 
-  // chromeos::PowerManagerClient::Observer overrides:
-  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
-  void SuspendDone(base::TimeDelta sleep_duration) override;
-
   void OnGetQuickAccessItems(
       GetQuickAccessItemsCallback callback,
       drive::FileError error,
@@ -322,10 +315,6 @@
 
   base::TimeTicks mount_start_;
 
-  base::ScopedObservation<chromeos::PowerManagerClient,
-                          chromeos::PowerManagerClient::Observer>
-      power_manager_observation_{this};
-
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<DriveIntegrationService> weak_ptr_factory_{this};
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 3bcdb7d..ae0c6fb 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path.cc
@@ -25,7 +25,7 @@
 #include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
 #include "chromeos/dbus/concierge/concierge_service.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 #include "components/arc/arc_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
index a1d4b5d..f937ca2 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
@@ -31,7 +31,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/dbus/seneschal/seneschal_service.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_stability_monitor.h b/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
index 7a0954a..3ce9590d 100644
--- a/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
+++ b/chrome/browser/ash/guest_os/guest_os_stability_monitor.h
@@ -10,7 +10,7 @@
 #include "chromeos/dbus/chunneld_client.h"
 #include "chromeos/dbus/cicerone/cicerone_client.h"
 #include "chromeos/dbus/concierge_client.h"
-#include "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 
 namespace guest_os {
 
diff --git a/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc b/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
index 771b15d0..c16cc78 100644
--- a/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_stability_monitor_unittest.cc
@@ -18,7 +18,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_chunneld_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
index 1a3da623..617fc1e 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
@@ -26,8 +26,8 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
 #include "chromeos/dbus/fake_vm_plugin_dispatcher_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import_unittest.cc b/chrome/browser/chromeos/crostini/crostini_export_import_unittest.cc
index a7711c5..6a227f01 100644
--- a/chrome/browser/chromeos/crostini/crostini_export_import_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_export_import_unittest.cc
@@ -17,7 +17,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/cicerone/fake_cicerone_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/dbus/seneschal/seneschal_service.pb.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_package_service_unittest.cc b/chrome/browser/chromeos/crostini/crostini_package_service_unittest.cc
index 2dad4d54..7d8f86f 100644
--- a/chrome/browser/chromeos/crostini/crostini_package_service_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_package_service_unittest.cc
@@ -26,7 +26,7 @@
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/exo/chrome_data_exchange_delegate_unittest.cc b/chrome/browser/chromeos/exo/chrome_data_exchange_delegate_unittest.cc
index 23316554..61abf54 100644
--- a/chrome/browser/chromeos/exo/chrome_data_exchange_delegate_unittest.cc
+++ b/chrome/browser/chromeos/exo/chrome_data_exchange_delegate_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 #include "components/exo/shell_surface_util.h"
 #include "content/public/common/drop_data.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/chromeos/full_restore/app_launch_handler_browsertest.cc b/chrome/browser/chromeos/full_restore/app_launch_handler_browsertest.cc
index ea9326a..6b0a47d 100644
--- a/chrome/browser/chromeos/full_restore/app_launch_handler_browsertest.cc
+++ b/chrome/browser/chromeos/full_restore/app_launch_handler_browsertest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ash/web_applications/system_web_app_integration_test.h"
 #include "chrome/browser/chromeos/full_restore/full_restore_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc
index a82cf503..0844ec3 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -183,9 +183,6 @@
 
 SmbService::~SmbService() {
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-  if (chromeos::PowerManagerClient::Get()) {
-    chromeos::PowerManagerClient::Get()->RemoveObserver(this);
-  }
 }
 
 void SmbService::Shutdown() {
@@ -821,9 +818,6 @@
                           base::Unretained(this))));
   RestoreMounts();
   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
-  if (chromeos::PowerManagerClient::Get()) {
-    chromeos::PowerManagerClient::Get()->AddObserver(this);
-  }
 
   if (setup_complete_callback_) {
     std::move(setup_complete_callback_).Run();
@@ -1027,64 +1021,5 @@
                            file_systems.size() + smbfs_shares_.size());
 }
 
-void SmbService::SuspendImminent(
-    power_manager::SuspendImminent::Reason reason) {
-  for (auto it = smbfs_shares_.begin(); it != smbfs_shares_.end(); ++it) {
-    SmbFsShare* share = it->second.get();
-
-    // For each share, block suspend until the unmount has completed, to ensure
-    // that no smbfs instances are active when the system goes to sleep.
-    auto token = base::UnguessableToken::Create();
-    chromeos::PowerManagerClient::Get()->BlockSuspend(token, "SmbService");
-    share->Unmount(
-        base::BindOnce(&SmbService::OnSuspendUnmountDone, AsWeakPtr(), token));
-  }
-}
-
-void SmbService::OnSuspendUnmountDone(
-    base::UnguessableToken power_manager_suspend_token,
-    chromeos::MountError result) {
-  LOG_IF(ERROR, result != chromeos::MountError::MOUNT_ERROR_NONE)
-      << "Could not unmount smbfs share during suspension: "
-      << static_cast<int>(result);
-  // Regardless of the outcome, unblock suspension for this share.
-  chromeos::PowerManagerClient::Get()->UnblockSuspend(
-      power_manager_suspend_token);
-}
-
-void SmbService::SuspendDone(base::TimeDelta sleep_duration) {
-  // Don't iterate directly over the share map during the remount
-  // process as shares can be removed on failure in OnSmbfsMountDone.
-  std::vector<std::string> mount_ids;
-  for (const auto& s : smbfs_shares_)
-    mount_ids.push_back(s.first);
-
-  for (const auto& mount_id : mount_ids) {
-    auto share_it = smbfs_shares_.find(mount_id);
-    if (share_it == smbfs_shares_.end()) {
-      LOG(WARNING) << "Smbfs mount id " << mount_id
-                   << " no longer present during remount after suspend";
-      continue;
-    }
-    SmbFsShare* share = share_it->second.get();
-
-    // Don't try to reconnect as we race the network stack in getting an IP
-    // address.
-    SmbFsShare::MountOptions options = share->options();
-    options.skip_connect = true;
-    // Observing power management changes from SmbService allows us to remove
-    // the share in OnSmbfsMountDone if remount fails.
-    share->Remount(
-        options, base::BindOnce(
-                     &SmbService::OnSmbfsMountDone, AsWeakPtr(), mount_id,
-                     base::BindOnce([](SmbMountResult result,
-                                       const base::FilePath& mount_path) {
-                       LOG_IF(ERROR, result != SmbMountResult::kSuccess)
-                           << "Error remounting smbfs share after suspension: "
-                           << static_cast<int>(result);
-                     })));
-  }
-}
-
 }  // namespace smb_client
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h
index a55b8db..64ec08a 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.h
+++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -25,7 +25,6 @@
 #include "chrome/browser/chromeos/smb_client/smb_task_queue.h"
 #include "chrome/browser/chromeos/smb_client/smbfs_share.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/smb_provider_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "net/base/network_change_notifier.h"
@@ -49,7 +48,6 @@
 // Creates and manages an smb file system.
 class SmbService : public KeyedService,
                    public net::NetworkChangeNotifier::NetworkChangeObserver,
-                   public chromeos::PowerManagerClient::Observer,
                    public base::SupportsWeakPtr<SmbService> {
  public:
   using MountResponse = base::OnceCallback<void(SmbMountResult result)>;
@@ -126,10 +124,6 @@
   void SetSmbFsMounterCreationCallbackForTesting(
       SmbFsShare::MounterCreationCallback callback);
 
-  // chromeos::PowerManagerClient::Observer overrides
-  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
-  void SuspendDone(base::TimeDelta sleep_duration) override;
-
  private:
   using MountInternalCallback =
       base::OnceCallback<void(SmbMountResult result,
@@ -168,11 +162,6 @@
                         MountInternalCallback callback,
                         SmbMountResult result);
 
-  // Callback passed to SmbFsShare::Unmount() during a power management
-  // suspension. Ensures that suspension is blocked until the unmount completes.
-  void OnSuspendUnmountDone(base::UnguessableToken power_manager_suspend_token,
-                            chromeos::MountError result);
-
   // Retrieves the mount_id for |file_system_info|.
   int32_t GetMountId(const ProvidedFileSystemInfo& info) const;
 
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index 6f7a2c7..d37e67bd 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -75,7 +75,6 @@
 #include "content/public/test/simple_url_loader_test_helper.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
-#include "content/public/test/url_loader_monitor.h"
 #include "extensions/browser/api/declarative_net_request/action_tracker.h"
 #include "extensions/browser/api/declarative_net_request/composite_matcher.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
@@ -126,6 +125,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/features.h"
 
 namespace extensions {
 namespace declarative_net_request {
@@ -179,7 +179,9 @@
       public ::testing::WithParamInterface<ExtensionLoadType> {
  public:
   DeclarativeNetRequestBrowserTest() {
-    feature_list_.InitAndEnableFeature(features::kFledgeInterestGroups);
+    feature_list_.InitWithFeatures({blink::features::kFledgeInterestGroups,
+                                    blink::features::kFledgeInterestGroupAPI},
+                                   {});
     net::test_server::RegisterDefaultHandlers(embedded_test_server());
   }
 
@@ -225,7 +227,7 @@
   // in test bodies.
   void MonitorRequest(const net::test_server::HttpRequest& request) {
     base::AutoLock lock(requests_to_server_lock_);
-    requests_to_server_.insert(request.GetURL());
+    requests_to_server_[request.GetURL()] = request;
     if (url_to_wait_for_ == request.GetURL()) {
       ASSERT_TRUE(wait_for_request_run_loop_);
       url_to_wait_for_ = GURL();
@@ -545,9 +547,9 @@
         browsertest_util::ScriptUserActivation::kDontActivate);
   }
 
-  std::set<GURL> GetAndResetRequestsToServer() {
+  std::map<GURL, net::test_server::HttpRequest> GetAndResetRequestsToServer() {
     base::AutoLock lock(requests_to_server_lock_);
-    std::set<GURL> results = requests_to_server_;
+    auto results = std::move(requests_to_server_);
     requests_to_server_.clear();
     return results;
   }
@@ -793,7 +795,8 @@
   // Requests observed by the EmbeddedTestServer. This is accessed on both the
   // UI and the EmbeddedTestServer's IO thread. Access is protected by
   // `requests_to_server_lock_`.
-  std::set<GURL> requests_to_server_ GUARDED_BY(requests_to_server_lock_);
+  std::map<GURL, net::test_server::HttpRequest> requests_to_server_
+      GUARDED_BY(requests_to_server_lock_);
   // URL that `wait_for_request_run_loop_` is currently waiting to observe.
   GURL url_to_wait_for_ GUARDED_BY(requests_to_server_lock_);
   // RunLoop to quit when a request for `url_to_wait_for_` is observed.
@@ -2604,7 +2607,8 @@
     const GURL redirected_script_url =
         embedded_test_server()->GetURL("/subresources/script.js");
 
-    std::set<GURL> seen_requests = GetAndResetRequestsToServer();
+    std::map<GURL, net::test_server::HttpRequest> seen_requests =
+        GetAndResetRequestsToServer();
     EXPECT_EQ(!expect_script_redirected,
               base::Contains(seen_requests, requested_script_url));
     EXPECT_EQ(expect_script_redirected,
@@ -4658,7 +4662,8 @@
                                        : "/page_with_two_frames.html");
     ui_test_utils::NavigateToURL(browser(), page_url);
 
-    const std::set<GURL> requests_seen = GetAndResetRequestsToServer();
+    std::map<GURL, net::test_server::HttpRequest> requests_seen =
+        GetAndResetRequestsToServer();
 
     for (const auto& path : paths_seen) {
       GURL expected_request_url = embedded_test_server()->GetURL(path);
@@ -5982,8 +5987,6 @@
       LoadExtensionWithRules({custom_response_header_rule}, "test_extension",
                              {URLPattern::kAllUrlsPattern}));
 
-  content::URLLoaderMonitor monitor;
-
   std::string run_auction_command = content::JsReplace(
       R"(
          (async function() {
@@ -6009,18 +6012,18 @@
   WaitForRequest(bidder_report_url);
   WaitForRequest(decision_report_url);
   // Clear observed URLs.
-  GetAndResetRequestsToServer();
+  std::map<GURL, net::test_server::HttpRequest> requests =
+      GetAndResetRequestsToServer();
 
   // Make sure the add headers rule was applied to all requests related to the
   // auction.
   for (const GURL& expected_url : {bidding_logic_url, decision_logic_url,
                                    bidder_report_url, decision_report_url}) {
-    base::Optional<network::ResourceRequest> request =
-        monitor.GetRequestInfo(expected_url);
-    ASSERT_TRUE(request);
-    std::string header_value;
-    ASSERT_TRUE(request->headers.GetHeader(kAddedHeaderName, &header_value));
-    EXPECT_EQ(kAddedHeaderValue, header_value);
+    auto request = requests.find(expected_url);
+    ASSERT_NE(request, requests.end());
+    auto added_header = request->second.headers.find(kAddedHeaderName);
+    ASSERT_NE(added_header, request->second.headers.end());
+    EXPECT_EQ(kAddedHeaderValue, added_header->second);
   }
 
   // Now there are no pending requests for the auction. Add a rule to block the
diff --git a/chrome/browser/extensions/content_script_tracker_browsertest.cc b/chrome/browser/extensions/content_script_tracker_browsertest.cc
index f70f367..8e1223c 100644
--- a/chrome/browser/extensions/content_script_tracker_browsertest.cc
+++ b/chrome/browser/extensions/content_script_tracker_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/ui/browser.h"
@@ -24,6 +25,7 @@
 #include "extensions/browser/browsertest_util.h"
 #include "extensions/browser/content_script_tracker.h"
 #include "extensions/browser/process_manager.h"
+#include "extensions/common/extension_features.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/test_extension_dir.h"
 #include "net/dns/mock_host_resolver.h"
@@ -302,6 +304,98 @@
       *first_tab->GetMainFrame()->GetProcess(), extension->id()));
 }
 
+class ContentScriptTrackerMatchOriginAsFallbackBrowserTest
+    : public ContentScriptTrackerBrowserTest {
+ public:
+  ContentScriptTrackerMatchOriginAsFallbackBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        extensions_features::kContentScriptsMatchOriginAsFallback);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Covers detecting content script injection into a 'data:...' URL.
+IN_PROC_BROWSER_TEST_F(
+    ContentScriptTrackerMatchOriginAsFallbackBrowserTest,
+    ContentScriptDeclarationInExtensionManifest_DataUrlIframe) {
+  // Install a test extension.
+  TestExtensionDir dir;
+  const char kManifestTemplate[] = R"(
+      {
+        "name": "ContentScriptTrackerBrowserTest - Declarative",
+        "version": "1.0",
+        "manifest_version": 2,
+        "permissions": [ "tabs", "<all_urls>" ],
+        "content_scripts": [{
+          "all_frames": true,
+          "match_about_blank": true,
+          "match_origin_as_fallback": true,
+          "matches": ["*://bar.com/*"],
+          "js": ["content_script.js"]
+        }]
+      } )";
+  dir.WriteManifest(kManifestTemplate);
+  dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), R"(
+                document.body.innerText = 'content script has run';
+                chrome.test.sendMessage('Hello from content script!'); )");
+  const Extension* extension = LoadExtension(dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+
+  // Navigate to a test page that *is* covered by `content_scripts.matches`
+  // manifest entry above.
+  {
+    GURL injected_url =
+        embedded_test_server()->GetURL("bar.com", "/title1.html");
+    ExtensionTestMessageListener listener("Hello from content script!", false);
+    ui_test_utils::NavigateToURL(browser(), injected_url);
+    ASSERT_TRUE(listener.WaitUntilSatisfied());
+  }
+
+  // Verify that ContentScriptTracker properly covered the initial frame.
+  content::WebContents* first_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_EQ("content script has run",
+            content::EvalJs(first_tab, "document.body.innerText"));
+  EXPECT_TRUE(ContentScriptTracker::DidProcessRunContentScriptFromExtension(
+      *first_tab->GetMainFrame()->GetProcess(), extension->id()));
+
+  // Add a new subframe with a `data:...` URL.  This will verify that the
+  // browser-side ContentScriptTracker correctly accounts for the renderer-side
+  // support for injecting contents scripts into data: URLs (see r793302).
+  {
+    ExtensionTestMessageListener listener("Hello from content script!", false);
+    const char kScript[] = R"(
+        let iframe = document.createElement('iframe');
+        iframe.src = 'data:text/html,contents';
+        document.body.appendChild(iframe);
+    )";
+    ExecuteScriptAsync(first_tab, kScript);
+    ASSERT_TRUE(listener.WaitUntilSatisfied());
+  }
+
+  // Verify that ContentScriptTracker properly covered the new child frame (and
+  // continues to correctly cover the initial frame).
+  //
+  // The verification below is a bit redundant, because `main_frame` and
+  // `child_frame` are currently hosted in the same process, but this kind of
+  // verification is important if 1( we ever consider going back to per-frame
+  // tracking or 2) we start isolating opaque-origin/sandboxed frames into a
+  // separate process (tracked in https://crbug.com/510122).
+  content::RenderFrameHost* main_frame = first_tab->GetMainFrame();
+  content::RenderFrameHost* child_frame = content::ChildFrameAt(main_frame, 0);
+  ASSERT_TRUE(child_frame);
+  EXPECT_EQ("content script has run",
+            content::EvalJs(main_frame, "document.body.innerText"));
+  EXPECT_EQ("content script has run",
+            content::EvalJs(child_frame, "document.body.innerText"));
+  EXPECT_TRUE(ContentScriptTracker::DidProcessRunContentScriptFromExtension(
+      *main_frame->GetProcess(), extension->id()));
+  EXPECT_TRUE(ContentScriptTracker::DidProcessRunContentScriptFromExtension(
+      *child_frame->GetProcess(), extension->id()));
+}
+
 // Covers detecting content script injection into 'about:blank'.
 IN_PROC_BROWSER_TEST_F(
     ContentScriptTrackerBrowserTest,
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
index c6356175..7b6dd24 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroController.java
@@ -108,12 +108,31 @@
                 ChromeFeatureList.WEB_FEED, PARAM_DAILY_VISIT_MIN, DEFAULT_DAILY_VISIT_MIN);
         mTabObserver = new EmptyTabObserver() {
             @Override
-            public void onPageLoadFinished(Tab tab, GURL url) {
-                mPageLoadTime = mClock.currentTimeMillis();
-                if (tab.isIncognito()) {
-                    mIsRecommended = false;
+            public void onPageLoadStarted(Tab tab, GURL url) {
+                clearPageInfo();
+                mWebFeedFollowIntroView.dismissBubble();
+            }
+
+            @Override
+            public void onContentViewScrollOffsetChanged(int verticalScrollDelta) {
+                if (verticalScrollDelta > 0) {
+                    maybeShowFollowIntro();
+                }
+            }
+
+            @Override
+            public void didFirstVisuallyNonEmptyPaint(Tab tab) {
+                // Note that we're using didFirstVisuallyNonEmptyPaint as a proxy for a page load
+                // event because some pages never fully load even though they are perfectly
+                // interactive.
+                GURL url = tab.getUrl();
+                if (tab.isIncognito()
+                        || !(url.getScheme().equals("http") || url.getScheme().equals("https"))) {
                     return;
                 }
+
+                mPageLoadTime = mClock.currentTimeMillis();
+
                 webFeedBridge.getVisitCountsToHost(url,
                         result
                         -> mMeetsVisitRequirement = result.visits >= numVisitMin
@@ -132,31 +151,25 @@
                     mUrl = url;
                 });
             }
-
-            @Override
-            public void onPageLoadStarted(Tab tab, GURL url) {
-                mIntroShown = false;
-                mIsRecommended = false;
-                mAcceleratorPressed = false;
-                mMeetsVisitRequirement = false;
-                mWebFeedFollowIntroView.dismissBubble();
-            }
-
-            @Override
-            public void onContentViewScrollOffsetChanged(int verticalScrollDelta) {
-                if (verticalScrollDelta > 0) {
-                    maybeShowFollowIntro();
-                }
-            }
         };
-        mCurrentTabObserver =
-                new CurrentTabObserver(tabSupplier, mTabObserver, /*swapCallback=*/null);
+        mCurrentTabObserver = new CurrentTabObserver(tabSupplier, mTabObserver, this::swapTabs);
     }
 
     public void destroy() {
         mCurrentTabObserver.destroy();
     }
 
+    private void swapTabs(Tab tab) {
+        clearPageInfo();
+    }
+
+    private void clearPageInfo() {
+        mIntroShown = false;
+        mIsRecommended = false;
+        mAcceleratorPressed = false;
+        mMeetsVisitRequirement = false;
+    }
+
     private void maybeShowFollowIntro() {
         if (!shouldShowFollowIntro()) {
             return;
diff --git a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
index 13d12dc9..e20ab3c 100644
--- a/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
+++ b/chrome/browser/feed/android/javatests/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
@@ -65,6 +65,8 @@
     private Tracker mTracker;
     @Mock
     private WebFeedBridge mWebFeedBridge;
+    @Mock
+    private Tab mTab;
 
     private static final GURL sTestUrl = new GURL("https://www.example.com");
     private static final byte[] sWebFeedId = "webFeedId".getBytes();
@@ -80,12 +82,15 @@
 
     @Before
     public void setUp() {
+        // TODO(harringtond): See if we can make this a robolectric test.
         MockitoAnnotations.initMocks(this);
         mActivityTestRule.startMainActivityOnBlankPage();
         mActivity = mActivityTestRule.getActivity();
         mClock = new FakeClock();
         when(mTracker.shouldTriggerHelpUI(FeatureConstants.IPH_WEB_FEED_FOLLOW_FEATURE))
                 .thenReturn(true);
+        when(mTab.getUrl()).thenReturn(sTestUrl);
+        when(mTab.isIncognito()).thenReturn(false);
         TrackerFactory.setTrackerForTests(mTracker);
         mNumVisitMin = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
                 ChromeFeatureList.WEB_FEED, PARAM_NUM_VISIT_MIN, DEFAULT_NUM_VISIT_MIN);
@@ -249,8 +254,9 @@
                 .when(mWebFeedBridge)
                 .getWebFeedMetadataForPage(eq(sTestUrl), any(Callback.class));
 
-        mEmptyTabObserver.onPageLoadStarted(mActivity.getActivityTab(), sTestUrl);
-        mEmptyTabObserver.onPageLoadFinished(mActivity.getActivityTab(), sTestUrl);
+        mEmptyTabObserver.onPageLoadStarted(mTab, sTestUrl);
+        mEmptyTabObserver.didFirstVisuallyNonEmptyPaint(mTab);
+        mEmptyTabObserver.onPageLoadFinished(mTab, sTestUrl);
     }
 
     private void performScrollUpAfterDelay(long delay) {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index ed10425..80b748c 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1276,11 +1276,6 @@
     "expiry_milestone": 88
   },
   {
-    "name": "enable-android-autofill-accessibility",
-    "owners": [ "ftirelo" ],
-    "expiry_milestone": 73
-  },
-  {
     "name": "enable-android-dark-search",
     "owners": [ "wylieb", "twellington", "fgorski" ],
     "expiry_milestone": 95
@@ -2070,11 +2065,6 @@
     "expiry_milestone": 92
   },
   {
-    "name": "enable-media-session-notifications",
-    "owners": [ "beccahughes", "media-dev" ],
-    "expiry_milestone": 82
-  },
-  {
     "name": "enable-media-session-service",
     "owners": [ "beccahughes", "media-dev" ],
     "expiry_milestone": 82
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f41ad02..4282971 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -776,8 +776,7 @@
 const char kDesktopPWAsRunOnOsLoginName[] = "Desktop PWAs run on OS login";
 const char kDesktopPWAsRunOnOsLoginDescription[] =
     "Enable installed PWAs to be configured to automatically start when the OS "
-    "user logs in. Launching a PWA while the browser is not running is known "
-    "to cause a failure to restore sessions. See https://crbug.com/938759.";
+    "user logs in.";
 
 const char kDesktopPWAsProtocolHandlingName[] = "Desktop PWA Protocol handling";
 const char kDesktopPWAsProtocolHandlingDescription[] =
@@ -2771,10 +2770,6 @@
     " This feature is only available for android P+ devices. Disabling it also "
     " disables SurfaceControl.";
 
-const char kAndroidAutofillAccessibilityName[] = "Autofill Accessibility";
-const char kAndroidAutofillAccessibilityDescription[] =
-    "Enable accessibility for autofill popup.";
-
 const char kAndroidDetailedLanguageSettingsName[] =
     "Detailed Language Settings";
 const char kAndroidDetailedLanguageSettingsDescription[] =
@@ -4693,11 +4688,6 @@
     "Use chrome://media-app as the default handler for video. Hides the "
     "deprecated VideoPlayer chrome app as a file handler.";
 
-const char kMediaSessionNotificationsName[] = "Media session notifications";
-const char kMediaSessionNotificationsDescription[] =
-    "Shows notifications for media sessions showing the currently playing "
-    "media and providing playback controls";
-
 const char kMeteredShowToggleName[] = "Show Metered Toggle";
 const char kMeteredShowToggleDescription[] =
     "Shows a Metered toggle in the Network settings UI for WiFI and Cellular. "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 42ea06e6..fc0189c9 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1608,9 +1608,6 @@
 extern const char kAImageReaderName[];
 extern const char kAImageReaderDescription[];
 
-extern const char kAndroidAutofillAccessibilityName[];
-extern const char kAndroidAutofillAccessibilityDescription[];
-
 extern const char kAndroidDetailedLanguageSettingsName[];
 extern const char kAndroidDetailedLanguageSettingsDescription[];
 
@@ -2732,9 +2729,6 @@
 extern const char kMediaAppVideoName[];
 extern const char kMediaAppVideoDescription[];
 
-extern const char kMediaSessionNotificationsName[];
-extern const char kMediaSessionNotificationsDescription[];
-
 extern const char kMeteredShowToggleName[];
 extern const char kMeteredShowToggleDescription[];
 
diff --git a/chrome/browser/interest_group/interest_group_permissions_browsertest.cc b/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
index b6df8536..65604c9 100644
--- a/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
+++ b/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
@@ -14,17 +14,20 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/features.h"
 
 namespace interest_group {
 
 class FledgePermissionsBrowserTest : public InProcessBrowserTest {
  public:
   FledgePermissionsBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeature(features::kFledgeInterestGroups);
+    scoped_feature_list_.InitWithFeatures(
+        {blink::features::kFledgeInterestGroups,
+         blink::features::kFledgeInterestGroupAPI},
+        {});
   }
 
   void SetUpOnMainThread() override {
@@ -238,7 +241,8 @@
  public:
   FledgePermissionBrowserTestBaseFeatureDisabled() {
     scoped_feature_list_.Reset();
-    scoped_feature_list_.InitAndDisableFeature(features::kFledgeInterestGroups);
+    scoped_feature_list_.InitAndDisableFeature(
+        blink::features::kFledgeInterestGroups);
   }
 };
 
diff --git a/chrome/browser/media/history/media_history_browsertest.cc b/chrome/browser/media/history/media_history_browsertest.cc
index 0c315d41..04dbf8b 100644
--- a/chrome/browser/media/history/media_history_browsertest.cc
+++ b/chrome/browser/media/history/media_history_browsertest.cc
@@ -30,11 +30,13 @@
 #include "content/public/browser/media_session.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browsing_data_remover_test_util.h"
+#include "content/public/test/prerender_test_util.h"
 #include "content/public/test/test_utils.h"
 #include "media/base/media_switches.h"
 #include "net/dns/mock_host_resolver.h"
 #include "services/media_session/public/cpp/media_metadata.h"
 #include "services/media_session/public/cpp/test/mock_media_session.h"
+#include "third_party/blink/public/common/features.h"
 
 namespace media_history {
 
@@ -1139,4 +1141,74 @@
   EXPECT_TRUE(playbacks.empty());
 }
 
+class MediaHistoryForPrerenderBrowserTest : public MediaHistoryBrowserTest {
+ public:
+  MediaHistoryForPrerenderBrowserTest()
+      : prerender_helper_(base::BindRepeating(
+            &MediaHistoryForPrerenderBrowserTest::web_contents,
+            base::Unretained(this))) {
+    feature_list_.InitAndEnableFeature(blink::features::kPrerender2);
+  }
+  void SetUpOnMainThread() override {
+    web_contents_ = browser()->tab_strip_model()->GetActiveWebContents();
+    prerender_helper_.SetUpOnMainThread(embedded_test_server());
+    MediaHistoryBrowserTest::SetUpOnMainThread();
+  }
+
+  content::WebContents* web_contents() { return web_contents_; }
+
+ protected:
+  content::WebContents* web_contents_ = nullptr;
+  content::test::PrerenderTestHelper prerender_helper_;
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(MediaHistoryForPrerenderBrowserTest,
+                       KeepRecordingMediaSession) {
+  // Start a page and wait for significant playback so we record watchtime.
+  ASSERT_TRUE(SetupPageAndStartPlaying(browser(), GetTestURL()));
+  EXPECT_TRUE(SetMediaMetadata(browser()));
+
+  media_session::MediaMetadata expected_metadata = GetExpectedMetadata();
+
+  {
+    media_session::test::MockMediaSessionMojoObserver observer(
+        *GetMediaSession(browser()));
+    observer.WaitForState(
+        media_session::mojom::MediaSessionInfo::SessionState::kActive);
+    observer.WaitForExpectedMetadata(expected_metadata);
+  }
+  EXPECT_TRUE(WaitForSignificantPlayback(browser()));
+
+  GURL prerender_url = embedded_test_server()->GetURL("/title1.html");
+
+  // We should not fetch the URL while prerendering.
+  prerender_helper_.AddPrerenderWithTestUtilJS(prerender_url);
+
+  EXPECT_TRUE(SetMediaMetadataWithArtwork(browser()));
+  auto expected_artwork = GetExpectedArtwork();
+  {
+    media_session::test::MockMediaSessionMojoObserver observer(
+        *GetMediaSession(browser()));
+    observer.WaitForExpectedImagesOfType(
+        media_session::mojom::MediaSessionImageType::kArtwork,
+        expected_artwork);
+  }
+
+  SimulateNavigationToCommit(browser());
+
+  // Verify the session in the database.
+  auto sessions = GetPlaybackSessionsSync(GetMediaHistoryService(browser()), 1);
+
+  EXPECT_EQ(1u, sessions.size());
+  EXPECT_EQ(GetTestURL(), sessions[0]->url);
+  EXPECT_EQ(kTestClipDuration, sessions[0]->duration);
+  EXPECT_LT(base::TimeDelta(), sessions[0]->position);
+  EXPECT_EQ(expected_metadata.title, sessions[0]->metadata.title);
+  EXPECT_EQ(expected_metadata.artist, sessions[0]->metadata.artist);
+  EXPECT_EQ(expected_metadata.album, sessions[0]->metadata.album);
+  EXPECT_EQ(expected_metadata.source_title, sessions[0]->metadata.source_title);
+  EXPECT_EQ(expected_artwork, sessions[0]->artwork);
+}
+
 }  // namespace media_history
diff --git a/chrome/browser/media/history/media_history_contents_observer.cc b/chrome/browser/media/history/media_history_contents_observer.cc
index 1bab51c1..3d8481e4 100644
--- a/chrome/browser/media/history/media_history_contents_observer.cc
+++ b/chrome/browser/media/history/media_history_contents_observer.cc
@@ -32,7 +32,7 @@
 
 void MediaHistoryContentsObserver::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->IsInMainFrame())
+  if (!navigation_handle->IsInPrimaryMainFrame())
     return;
 
   frozen_ = true;
@@ -40,7 +40,7 @@
 
 void MediaHistoryContentsObserver::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->IsInMainFrame())
+  if (!navigation_handle->IsInPrimaryMainFrame())
     return;
 
   MaybeCommitMediaSession();
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc
index 0b36b982..d937387 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -104,6 +104,15 @@
          uarch == "Broadwell" || uarch == "Kabylake" || uarch == "Tigerlake";
 }
 
+// Returns if a kernel release properly flushes PEBS on a context switch. The
+// fix landed in kernel 5.12 upstream, but it was backported to CrOS kernels
+// 4.14, 4.19, 5.4 and 5.10.
+bool KernelReleaseHasPEBSFlushingFix(const std::string& release) {
+  int32_t major, minor, bugfix;
+  ExtractVersionNumbers(release, &major, &minor, &bugfix);
+  return major >= 5 || (major == 4 && minor >= 14);
+}
+
 // Returns if a micro-architecture supports LBR callgraph profiling.
 bool MicroarchitectureHasLBRCallgraph(const std::string& uarch) {
   return uarch == "Haswell" || uarch == "Broadwell" || uarch == "Skylake" ||
@@ -120,10 +129,18 @@
 // Hopefully we never need a space in a command argument.
 const char kPerfCommandDelimiter[] = " ";
 
-// Collect precise=3 (:ppp) cycle events on microarchitectures that support it.
+// Collect precise=3 (:ppp) cycle events on microarchitectures and kernels that
+// support it.
+const char kPerfCyclesPPPCmd[] = "perf record -a -e cycles:ppp -c 1000003";
+
 const char kPerfFPCallgraphPPPCmd[] =
     "perf record -a -e cycles:ppp -g -c 4000037";
 
+const char kPerfLBRCallgraphPPPCmd[] =
+    "perf record -a -e cycles:ppp -c 4000037 --call-graph lbr";
+
+const char kPerfCyclesPPPHGCmd[] = "perf record -a -e cycles:pppHG -c 1000003";
+
 const char kPerfFPCallgraphPPPHGCmd[] =
     "perf record -a -e cycles:pppHG -g -c 4000037";
 
@@ -210,8 +227,18 @@
   }
   if (MicroarchitectureHasCyclesPPPEvent(cpu_uarch)) {
     fp_callgraph_cmd = kPerfFPCallgraphPPPCmd;
-    if (base::FeatureList::IsEnabled(kCWPCollectionOnHostAndGuest))
+    if (base::FeatureList::IsEnabled(kCWPCollectionOnHostAndGuest)) {
       fp_callgraph_cmd = kPerfFPCallgraphPPPHGCmd;
+    }
+    // Enable precise events for cycles.flat and cycles.lbr only if the kernel
+    // has the fix for flushing PEBS on context switch.
+    if (KernelReleaseHasPEBSFlushingFix(cpuid.release)) {
+      cycles_cmd = kPerfCyclesPPPCmd;
+      lbr_callgraph_cmd = kPerfLBRCallgraphPPPCmd;
+      if (base::FeatureList::IsEnabled(kCWPCollectionOnHostAndGuest)) {
+        cycles_cmd = kPerfCyclesPPPHGCmd;
+      }
+    }
   }
 
   cmds.emplace_back(WeightAndValue(50.0, cycles_cmd));
diff --git a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
index ebefe8e1..96b4db29 100644
--- a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
@@ -42,10 +42,14 @@
     "perf record -a -e cycles:HG -g -c 4000037";
 const char kPerfLBRCallgraphCmd[] =
     "perf record -a -e cycles -c 4000037 --call-graph lbr";
+const char kPerfCyclesPPPCmd[] = "perf record -a -e cycles:ppp -c 1000003";
+const char kPerfCyclesPPPHGCmd[] = "perf record -a -e cycles:pppHG -c 1000003";
 const char kPerfFPCallgraphPPPCmd[] =
     "perf record -a -e cycles:ppp -g -c 4000037";
 const char kPerfFPCallgraphPPPHGCmd[] =
     "perf record -a -e cycles:pppHG -g -c 4000037";
+const char kPerfLBRCallgraphPPPCmd[] =
+    "perf record -a -e cycles:ppp -c 4000037 --call-graph lbr";
 const char kPerfLBRCmd[] = "perf record -a -e r20c4 -b -c 200011";
 const char kPerfLBRCmdAtom[] = "perf record -a -e rc4 -b -c 300001";
 const char kPerfITLBMissCyclesCmdIvyBridge[] =
@@ -599,11 +603,11 @@
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 3UL);
-  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
   // We have both FP and LBR based callstacks.
   EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
-  EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphCmd);
+  EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
@@ -637,11 +641,11 @@
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 3UL);
-  EXPECT_EQ(cmds[0].value, kPerfCyclesHGCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesPPPHGCmd);
   // We have both FP and LBR based callstacks.
   EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPHGCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
-  EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphCmd);
+  EXPECT_EQ(cmds[2].value, kPerfLBRCallgraphPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
 }
 
@@ -691,11 +695,11 @@
   cpuid.family = 0x06;
   cpuid.model = 0x7a;  // GoldmontPlus
   cpuid.model_name = "";
-  cpuid.release = "4.4.196";
+  cpuid.release = "4.14.214";
   std::vector<RandomSelector::WeightAndValue> cmds =
       internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
   EXPECT_EQ(cmds[1].value, kPerfFPCallgraphPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
diff --git a/chrome/browser/permissions/permission_manager_factory.cc b/chrome/browser/permissions/permission_manager_factory.cc
index 4012e39..3811b0d 100644
--- a/chrome/browser/permissions/permission_manager_factory.cc
+++ b/chrome/browser/permissions/permission_manager_factory.cc
@@ -32,7 +32,6 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/permissions/contexts/clipboard_read_write_permission_context.h"
 #include "components/permissions/contexts/clipboard_sanitized_write_permission_context.h"
-#include "components/permissions/contexts/file_handling_permission_context.h"
 #include "components/permissions/contexts/font_access_permission_context.h"
 #include "components/permissions/contexts/midi_permission_context.h"
 #include "components/permissions/contexts/midi_sysex_permission_context.h"
@@ -51,6 +50,7 @@
 #include "components/permissions/contexts/nfc_permission_context_android.h"
 #else
 #include "chrome/browser/geolocation/geolocation_permission_context_delegate.h"
+#include "chrome/browser/web_applications/components/file_handling_permission_context.h"
 #include "components/permissions/contexts/geolocation_permission_context.h"
 #include "components/permissions/contexts/nfc_permission_context.h"
 #endif
@@ -141,8 +141,10 @@
       std::make_unique<FontAccessPermissionContext>(profile);
   permission_contexts[ContentSettingsType::DISPLAY_CAPTURE] =
       std::make_unique<DisplayCapturePermissionContext>(profile);
+#if !defined(OS_ANDROID)  // File Handling is not available on Android.
   permission_contexts[ContentSettingsType::FILE_HANDLING] =
       std::make_unique<FileHandlingPermissionContext>(profile);
+#endif  // !defined(OS_ANDROID)
   return permission_contexts;
 }
 }  // namespace
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index e2d3347..1724ac9 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -257,6 +257,7 @@
 #include "ash/components/audio/audio_devices_pref_handler_impl.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/ash_prefs.h"
+#include "chrome/browser/apps/app_service/app_platform_metrics_service.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h"
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
index 0405dce..d9fa0af8 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -177,6 +177,7 @@
     "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_components/chromeos/cellular_setup:cellular_types.m",
+    "//ui/webui/resources/cr_components/chromeos/cellular_setup:esim_manager_utils.m",
     "//ui/webui/resources/cr_components/chromeos/network:cellular_utils.m",
     "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider.m",
     "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior.m",
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
index e2ab7cd..647deff 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/cellular_setup_icons.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/cellular_types.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/cellular_utils.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/mojo_interface_provider.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_listener_behavior.html">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
index a48fc735..363f74d 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
@@ -6,6 +6,9 @@
 
 const mojom = chromeos.networkConfig.mojom;
 
+/** @type {number} */
+const ESIM_PROFILE_LIMIT = 5;
+
 /**
  * @fileoverview
  * 'settings-internet-page' is the settings page containing internet
@@ -439,20 +442,33 @@
       this.showCellularSetupDialog_ = true;
       this.cellularSetupDialogPageName_ = pageName;
     } else {
-      // isConnectedToNonCellularNetwork_ may
-      // not be fetched yet if the page just opened, fetch it explicitly.
-      this.updateIsConnectedToNonCellularNetwork_().then(
-          ((isConnected) => {
-            this.showCellularSetupDialog_ = isConnected;
-            if (!isConnected) {
-              this.showErrorToast_(this.i18n('eSimNoConnectionErrorToast'));
-              return;
-            }
-            this.cellularSetupDialogPageName_ = pageName;
-          }).bind(this));
+      this.attemptShowESimSetupDialog_();
     }
   },
 
+  /** @private */
+  async attemptShowESimSetupDialog_() {
+    const numProfiles = await cellular_setup.getNumESimProfiles();
+    if (numProfiles >= ESIM_PROFILE_LIMIT) {
+      this.showErrorToast_(
+          this.i18n('eSimProfileLimitReachedErrorToast', ESIM_PROFILE_LIMIT));
+      return;
+    }
+    // isConnectedToNonCellularNetwork_ may
+    // not be fetched yet if the page just opened, fetch it
+    // explicitly.
+    this.updateIsConnectedToNonCellularNetwork_().then(
+        ((isConnected) => {
+          this.showCellularSetupDialog_ = isConnected;
+          if (!isConnected) {
+            this.showErrorToast_(this.i18n('eSimNoConnectionErrorToast'));
+            return;
+          }
+          this.cellularSetupDialogPageName_ =
+              cellularSetup.CellularSetupPageName.ESIM_FLOW_UI;
+        }).bind(this));
+  },
+
   /**
    * @param {!CustomEvent<string>} event
    * @private
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index d9b0f1a..05568e3 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/page_break_app_item.h"
 #include "chrome/browser/ui/app_list/page_break_constants.h"
+#include "chrome/browser/web_applications/components/app_registrar.h"
 #include "chrome/browser/web_applications/components/web_app_id_constants.h"
 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
index 6944e16a7..aa91cd0d 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -53,6 +53,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/settings/cros_settings_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/mojom/types.mojom-shared.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_browsertest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_browsertest.cc
index 9a747a4e..c7e2a3f 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_browsertest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_browsertest.cc
@@ -368,35 +368,6 @@
     return drive_integration_service_;
   }
 
-  void WaitForVolumeUnmountIfNeeded() {
-    // Drive fs gets unmounted on suspend, and the fake cros disks client
-    // deletes the mount point on unmount event - wait for the drive mount point
-    // to get deleted from file system.
-    if (GetParam() != FileSystemType::kDriveFs)
-      return;
-
-    // Clear the list of predefined test files, as they are getting deleted with
-    // the mount point dir.
-    predefined_test_files_.clear();
-
-    const base::FilePath mount_path = GetTestMountPoint();
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    if (!base::PathExists(mount_path))
-      return;
-
-    base::RunLoop waiter_loop;
-    base::FilePathWatcher watcher;
-    watcher.Watch(mount_path, base::FilePathWatcher::Type::kNonRecursive,
-                  base::BindRepeating(
-                      [](const base::RepeatingClosure& callback,
-                         const base::FilePath& path, bool error) {
-                        if (!base::PathExists(path))
-                          callback.Run();
-                      },
-                      waiter_loop.QuitClosure()));
-    waiter_loop.Run();
-  }
-
   drive::DriveIntegrationService* drive_integration_service() {
     return drive_integration_service_;
   }
@@ -482,11 +453,6 @@
   // Holding space model gets cleared on suspend.
   EXPECT_TRUE(holding_space_model->items().empty());
 
-  // Wait for test volume unmount to finish, if necessary for the test file
-  // system - for example, the drive fs will be unmounted, and fake cros disks
-  // client will delete the backing directory from files system.
-  WaitForVolumeUnmountIfNeeded();
-
   EnsurePredefinedTestFiles();
   // Verify that holding space model gets restored on resume.
   chromeos::FakePowerManagerClient::Get()->SendSuspendDone();
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
index 5a9917c..8019fcf 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
@@ -35,6 +35,7 @@
 #include "components/arc/compat_mode/arc_splash_screen_dialog_view.h"
 #include "components/exo/shell_surface_base.h"
 #include "components/exo/shell_surface_util.h"
+#include "extensions/common/constants.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
index 7d9bc320..8018985e 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_test_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
index fe542682..06bb5ed 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
@@ -44,6 +44,7 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/context_menu_params.h"
+#include "extensions/browser/extension_prefs.h"
 #include "ui/display/scoped_display_for_new_windows.h"
 #include "ui/gfx/vector_icon_types.h"
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 068035b..f047cb0 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -139,12 +139,6 @@
   return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id);
 }
 
-std::unique_ptr<views::InkDrop> CreateBookmarkButtonInkDrop(
-    std::unique_ptr<views::InkDropImpl> ink_drop) {
-  ink_drop->SetShowHighlightOnFocus(false);
-  return std::move(ink_drop);
-}
-
 std::unique_ptr<LabelButtonBorder> CreateBookmarkButtonBorder() {
   auto border = std::make_unique<LabelButtonBorder>();
   border->set_insets(ChromeLayoutProvider::Get()->GetInsetsMetric(
@@ -193,19 +187,6 @@
   }
 
   // LabelButton:
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    return CreateBookmarkButtonInkDrop(CreateDefaultFloodFillInkDropImpl());
-  }
-
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override {
-    return CreateToolbarInkDropHighlight(this);
-  }
-
-  SkColor GetInkDropBaseColor() const override {
-    return GetToolbarInkDropBaseColor(this);
-  }
-
   void OnThemeChanged() override {
     LabelButton::OnThemeChanged();
     ToolbarButton::UpdateFocusRingColor(this, focus_ring());
@@ -311,19 +292,6 @@
   BookmarkMenuButtonBase& operator=(const BookmarkMenuButtonBase&) = delete;
 
   // MenuButton:
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    return CreateBookmarkButtonInkDrop(CreateDefaultFloodFillInkDropImpl());
-  }
-
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override {
-    return CreateToolbarInkDropHighlight(this);
-  }
-
-  SkColor GetInkDropBaseColor() const override {
-    return GetToolbarInkDropBaseColor(this);
-  }
-
   void OnThemeChanged() override {
     MenuButton::OnThemeChanged();
     ToolbarButton::UpdateFocusRingColor(this, focus_ring());
diff --git a/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc b/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc
index 0e9ffc7..fe750d7 100644
--- a/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc
@@ -118,6 +118,7 @@
   }
 
   bool GetHasFocusedOnNonWebView() { return has_focused_on_non_webview_; }
+  int GetFocusChangeCount() { return focus_change_count; }
 
  private:
   // Inherited from views::FocusChangeListener
@@ -130,10 +131,12 @@
         // Focused views could be destroyed. Track what we want to test for when
         // OnDidChangeFocus is called.
         has_focused_on_non_webview_ = true;
+    focus_change_count++;
   }
 
   views::FocusManager* focus_manager_;
   bool has_focused_on_non_webview_ = false;
+  int focus_change_count = 0;
 };
 
 // Switching tabs does not focus views unexpectedly.
@@ -161,4 +164,5 @@
 
   // Everything that was focused on must be a WebView.
   EXPECT_FALSE(focus_change_recorder.GetHasFocusedOnNonWebView());
+  EXPECT_EQ(focus_change_recorder.GetFocusChangeCount(), 2);
 }
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
index 98374d4..0ad7747 100644
--- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -296,9 +296,10 @@
 std::unique_ptr<views::Background>
 PaymentHandlerWebFlowViewController::GetHeaderBackground(
     views::View* header_view) {
+  DCHECK(header_view);
   auto default_header_background =
       PaymentRequestSheetController::GetHeaderBackground(header_view);
-  if (web_contents()) {
+  if (web_contents() && header_view->GetWidget()) {
     return views::CreateSolidBackground(color_utils::GetResultingPaintColor(
         web_contents()->GetThemeColor().value_or(SK_ColorTRANSPARENT),
         default_header_background->get_color()));
diff --git a/chrome/browser/ui/views/read_later/read_later_button.cc b/chrome/browser/ui/views/read_later/read_later_button.cc
index d866eac..5e19d744 100644
--- a/chrome/browser/ui/views/read_later/read_later_button.cc
+++ b/chrome/browser/ui/views/read_later/read_later_button.cc
@@ -34,7 +34,6 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/accessibility/view_accessibility.h"
-#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_impl.h"
@@ -144,22 +143,6 @@
     webui_bubble_manager_->CloseBubble();
 }
 
-std::unique_ptr<views::InkDrop> ReadLaterButton::CreateInkDrop() {
-  std::unique_ptr<views::InkDropImpl> ink_drop =
-      CreateDefaultFloodFillInkDropImpl();
-  ink_drop->SetShowHighlightOnFocus(false);
-  return std::move(ink_drop);
-}
-
-std::unique_ptr<views::InkDropHighlight>
-ReadLaterButton::CreateInkDropHighlight() const {
-  return CreateToolbarInkDropHighlight(this);
-}
-
-SkColor ReadLaterButton::GetInkDropBaseColor() const {
-  return GetToolbarInkDropBaseColor(this);
-}
-
 void ReadLaterButton::OnThemeChanged() {
   LabelButton::OnThemeChanged();
 
diff --git a/chrome/browser/ui/views/read_later/read_later_button.h b/chrome/browser/ui/views/read_later/read_later_button.h
index 72b3e94f3..66d64b0 100644
--- a/chrome/browser/ui/views/read_later/read_later_button.h
+++ b/chrome/browser/ui/views/read_later/read_later_button.h
@@ -78,10 +78,6 @@
   };
 
   // LabelButton:
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override;
-  SkColor GetInkDropBaseColor() const override;
   void OnThemeChanged() override;
   void Layout() override;
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index 3d9ce13..729c68b 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -111,15 +111,6 @@
   return button_controller()->IsTriggerableEventType(event);
 }
 
-SkColor ToolbarActionView::GetInkDropBaseColor() const {
-  return GetToolbarInkDropBaseColor(this);
-}
-
-std::unique_ptr<views::InkDropHighlight>
-ToolbarActionView::CreateInkDropHighlight() const {
-  return CreateToolbarInkDropHighlight(this);
-}
-
 bool ToolbarActionView::OnKeyPressed(const ui::KeyEvent& event) {
   if (event.key_code() == ui::VKEY_DOWN) {
     context_menu_controller()->ShowContextMenuForView(this, gfx::Point(),
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index 9eefcb7..c6703488 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -62,9 +62,6 @@
   std::unique_ptr<views::LabelButtonBorder> CreateDefaultBorder()
       const override;
   bool IsTriggerableEvent(const ui::Event& event) override;
-  SkColor GetInkDropBaseColor() const override;
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
 
   // ToolbarActionViewDelegateViews:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index 0108f7e..dcb36dd 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -159,6 +159,7 @@
       trigger_menu_on_long_press_(trigger_menu_on_long_press),
       highlight_color_animation_(this) {
   ConfigureInkDropForToolbar(this);
+
   set_context_menu_controller(this);
 
   if (base::FeatureList::IsEnabled(views::kInstallableInkDropFeature)) {
@@ -559,13 +560,6 @@
   return views::LabelButton::CreateInkDrop();
 }
 
-std::unique_ptr<views::InkDropHighlight> ToolbarButton::CreateInkDropHighlight()
-    const {
-  // Ensure this doesn't get called when InstallableInkDrops are enabled.
-  DCHECK(!base::FeatureList::IsEnabled(views::kInstallableInkDropFeature));
-  return CreateToolbarInkDropHighlight(this);
-}
-
 std::unique_ptr<views::InkDropMask> ToolbarButton::CreateInkDropMask() const {
   if (has_in_product_help_promo_) {
     // This gets the latest ink drop insets. |SetTrailingMargin()| is called
@@ -591,7 +585,7 @@
       highlight_color_animation_.GetInkDropBaseColor();
   if (drop_base_color)
     return *drop_base_color;
-  return GetToolbarInkDropBaseColor(this);
+  return LabelButton::GetInkDropBaseColor();
 }
 
 views::InkDrop* ToolbarButton::GetInkDrop() {
@@ -843,10 +837,10 @@
     // TODO(crbug.com/967317): Change the highlight opacity to 4% to match the
     // mocks, if needed.
     bg_color = color_utils::GetResultingPaintColor(
-        /*fg=*/SkColorSetA(*highlight_color_,
-                           SkColorGetA(*highlight_color_) *
-                               kToolbarInkDropHighlightVisibleOpacity),
-        /*bg=*/bg_color);
+        /*foreground=*/SkColorSetA(*highlight_color_,
+                                   SkColorGetA(*highlight_color_) *
+                                       kToolbarInkDropHighlightVisibleOpacity),
+        /*background=*/bg_color);
   }
   return FadeWithAnimation(bg_color, highlight_color_animation_);
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index 9eccccc..2213449a 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -116,8 +116,6 @@
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   std::u16string GetTooltipText(const gfx::Point& p) const override;
   std::unique_ptr<views::InkDrop> CreateInkDrop() override;
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override;
   std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
   views::InkDrop* GetInkDrop() override;
   SkColor GetInkDropBaseColor() const override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.cc b/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.cc
index 2dc2176..4b1d0a8 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.cc
@@ -39,6 +39,7 @@
     return path;
   }
 };
+
 }  // namespace
 
 gfx::Insets GetToolbarInkDropInsets(const views::View* host_view) {
@@ -59,13 +60,6 @@
   return inkdrop_insets;
 }
 
-std::unique_ptr<views::InkDropHighlight> CreateToolbarInkDropHighlight(
-    const views::InkDropHostView* host_view) {
-  auto highlight = host_view->views::InkDropHostView::CreateInkDropHighlight();
-  highlight->set_visible_opacity(kToolbarInkDropHighlightVisibleOpacity);
-  return highlight;
-}
-
 SkColor GetToolbarInkDropBaseColor(const views::View* host_view) {
   const auto* theme_provider = host_view->GetThemeProvider();
   // There may be no theme provider in unit tests.
@@ -90,4 +84,6 @@
   host->SetInkDropMode(views::InkDropHostView::InkDropMode::ON);
   host->SetInkDropVisibleOpacity(kToolbarInkDropVisibleOpacity);
   host->SetInkDropHighlightOpacity(kToolbarInkDropHighlightVisibleOpacity);
+  host->SetInkDropBaseColorCallback(
+      base::BindRepeating(&GetToolbarInkDropBaseColor, host));
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h b/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h
index cfaa5c35..102f3ac 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h
@@ -13,8 +13,6 @@
 
 namespace views {
 class Button;
-class InkDropHighlight;
-class InkDropHostView;
 class View;
 struct InstallableInkDropConfig;
 }  // namespace views
@@ -27,11 +25,8 @@
 // the resulting mask or inkdrop has the desired inkdrop size.
 gfx::Insets GetToolbarInkDropInsets(const views::View* host_view);
 
-// Creates the default inkdrop highlight but using the toolbar visible opacity.
-std::unique_ptr<views::InkDropHighlight> CreateToolbarInkDropHighlight(
-    const views::InkDropHostView* host_view);
-
 // Returns the ink drop base color that should be used by all toolbar buttons.
+// This is only needed if you can't use ConfigureInkDropForToolbar().
 SkColor GetToolbarInkDropBaseColor(const views::View* host_view);
 
 views::InstallableInkDropConfig GetToolbarInstallableInkDropConfig(
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
index 0b200c69..5b7d8c4 100644
--- a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
+++ b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
@@ -612,7 +612,6 @@
 void WebUITabCounterButton::OnThemeChanged() {
   views::Button::OnThemeChanged();
   UpdateColors();
-  SetInkDropBaseColor(GetToolbarInkDropBaseColor(this));
 }
 
 void WebUITabCounterButton::Layout() {
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
index a7411d3..91f75e3 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
@@ -29,6 +29,8 @@
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "extensions/browser/app_sorting.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc
index a77a56e..363d651c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc
@@ -729,6 +729,8 @@
        IDS_SETTINGS_INTERNET_ESIM_NO_CONNECTION_ERROR_TOAST},
       {"eSimMobileDataNotEnabledErrorToast",
        IDS_SETTINGS_INTERNET_ESIM_MOBILE_DATA_NOT_ENABLED_ERROR_TOAST},
+      {"eSimProfileLimitReachedErrorToast",
+       IDS_SETTINGS_INTERNET_ESIM_PROFILE_LIMIT_REACHED_ERROR_TOAST},
       {"eSimInstallErrorDialogTitle",
        IDS_SETTINGS_INTERNET_NETWORK_INSTALL_ERROR_DIALOG_TITLE},
       {"eSimInstallErrorDialogConfirmationCodeMessage",
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn
index f432609..bbf26dcd6 100644
--- a/chrome/browser/web_applications/components/BUILD.gn
+++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -24,6 +24,10 @@
     "externally_managed_app_manager.h",
     "file_handler_manager.cc",
     "file_handler_manager.h",
+    "file_handling_permission_context.cc",
+    "file_handling_permission_context.h",
+    "file_handling_permission_request_impl.cc",
+    "file_handling_permission_request_impl.h",
     "install_bounce_metric.cc",
     "install_bounce_metric.h",
     "install_finalizer.cc",
@@ -181,6 +185,7 @@
     "//chrome/common",
     "//components/crx_file",
     "//components/keyed_service/content",
+    "//components/permissions:permissions",
     "//components/pref_registry",
     "//components/services/app_service/public/cpp:protocol_handling",
     "//components/services/app_service/public/mojom",
diff --git a/chrome/browser/web_applications/components/file_handling_permission_context.cc b/chrome/browser/web_applications/components/file_handling_permission_context.cc
new file mode 100644
index 0000000..1d344b77
--- /dev/null
+++ b/chrome/browser/web_applications/components/file_handling_permission_context.cc
@@ -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.
+
+#include "chrome/browser/web_applications/components/file_handling_permission_context.h"
+
+#include <string>
+
+#include "chrome/browser/web_applications/components/file_handling_permission_request_impl.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_context_base.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
+
+FileHandlingPermissionContext::FileHandlingPermissionContext(
+    content::BrowserContext* browser_context)
+    : PermissionContextBase(browser_context,
+                            ContentSettingsType::FILE_HANDLING,
+                            blink::mojom::PermissionsPolicyFeature::kNotFound) {
+}
+
+FileHandlingPermissionContext::~FileHandlingPermissionContext() = default;
+
+bool FileHandlingPermissionContext::IsRestrictedToSecureOrigins() const {
+  return true;
+}
+
+std::unique_ptr<permissions::PermissionRequest>
+FileHandlingPermissionContext::CreatePermissionRequest(
+    const GURL& request_origin,
+    ContentSettingsType content_settings_type,
+    bool has_gesture,
+    content::WebContents* web_contents,
+    permissions::PermissionRequestImpl::PermissionDecidedCallback
+        permission_decided_callback,
+    base::OnceClosure delete_callback) const {
+  return std::make_unique<permissions::FileHandlingPermissionRequestImpl>(
+      request_origin, content_settings_type, has_gesture, web_contents,
+      std::move(permission_decided_callback), std::move(delete_callback));
+}
diff --git a/chrome/browser/web_applications/components/file_handling_permission_context.h b/chrome/browser/web_applications/components/file_handling_permission_context.h
new file mode 100644
index 0000000..6c65928c
--- /dev/null
+++ b/chrome/browser/web_applications/components/file_handling_permission_context.h
@@ -0,0 +1,38 @@
+// 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_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
+
+#include "components/permissions/permission_context_base.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+class FileHandlingPermissionContext
+    : public permissions::PermissionContextBase {
+ public:
+  explicit FileHandlingPermissionContext(
+      content::BrowserContext* browser_context);
+  ~FileHandlingPermissionContext() override;
+
+  FileHandlingPermissionContext(const FileHandlingPermissionContext&) = delete;
+  FileHandlingPermissionContext& operator=(
+      const FileHandlingPermissionContext&) = delete;
+
+ protected:
+  // PermissionContextBase:
+  bool IsRestrictedToSecureOrigins() const override;
+  std::unique_ptr<permissions::PermissionRequest> CreatePermissionRequest(
+      const GURL& request_origin,
+      ContentSettingsType content_settings_type,
+      bool has_gesture,
+      content::WebContents* web_contents,
+      permissions::PermissionRequestImpl::PermissionDecidedCallback
+          permission_decided_callback,
+      base::OnceClosure delete_callback) const override;
+};
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/web_applications/components/file_handling_permission_request_impl.cc b/chrome/browser/web_applications/components/file_handling_permission_request_impl.cc
new file mode 100644
index 0000000..c47de69c
--- /dev/null
+++ b/chrome/browser/web_applications/components/file_handling_permission_request_impl.cc
@@ -0,0 +1,51 @@
+// 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/web_applications/components/file_handling_permission_request_impl.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/components/web_app_utils.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace permissions {
+
+FileHandlingPermissionRequestImpl::FileHandlingPermissionRequestImpl(
+    const GURL& request_origin,
+    ContentSettingsType content_settings_type,
+    bool has_gesture,
+    content::WebContents* web_contents,
+    PermissionDecidedCallback permission_decided_callback,
+    base::OnceClosure delete_callback)
+    : PermissionRequestImpl(request_origin,
+                            content_settings_type,
+                            has_gesture,
+                            std::move(permission_decided_callback),
+                            std::move(delete_callback)) {
+  auto* browser = web_contents->GetBrowserContext();
+  if (!browser) {
+    return;
+  }
+  Profile* profile = Profile::FromBrowserContext(browser);
+  DCHECK(profile);
+
+  std::u16string extensions_list =
+      web_app::GetFileExtensionsHandledByWebAppDisplayedAsList(
+          profile, web_contents->GetLastCommittedURL());
+  message_text_fragment_ = l10n_util::GetStringFUTF16(
+      IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT, extensions_list);
+}
+
+FileHandlingPermissionRequestImpl::~FileHandlingPermissionRequestImpl() =
+    default;
+
+std::u16string FileHandlingPermissionRequestImpl::GetMessageTextFragment()
+    const {
+  return message_text_fragment_;
+}
+
+}  // namespace permissions
diff --git a/chrome/browser/web_applications/components/file_handling_permission_request_impl.h b/chrome/browser/web_applications/components/file_handling_permission_request_impl.h
new file mode 100644
index 0000000..c1287e2
--- /dev/null
+++ b/chrome/browser/web_applications/components/file_handling_permission_request_impl.h
@@ -0,0 +1,36 @@
+// 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_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_REQUEST_IMPL_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_REQUEST_IMPL_H_
+
+#include <string>
+#include "components/permissions/permission_request_impl.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace permissions {
+
+// Provides a custom message text fragment that differs based on file handlers
+// requested by a web app.
+class FileHandlingPermissionRequestImpl : public PermissionRequestImpl {
+ public:
+  FileHandlingPermissionRequestImpl(
+      const GURL& request_origin,
+      ContentSettingsType content_settings_type,
+      bool has_gesture,
+      content::WebContents* web_contents,
+      PermissionDecidedCallback permission_decided_callback,
+      base::OnceClosure delete_callback);
+  ~FileHandlingPermissionRequestImpl() override;
+
+ private:
+  std::u16string GetMessageTextFragment() const override;
+  std::u16string message_text_fragment_;
+};
+}  // namespace permissions
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_FILE_HANDLING_PERMISSION_REQUEST_IMPL_H_
diff --git a/chrome/browser/web_applications/components/web_app_utils.cc b/chrome/browser/web_applications/components/web_app_utils.cc
index 5f91d23f..dde204b 100644
--- a/chrome/browser/web_applications/components/web_app_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_utils.cc
@@ -5,10 +5,18 @@
 #include "chrome/browser/web_applications/components/web_app_utils.h"
 
 #include "base/files/file_path.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/components/app_registrar.h"
+#include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/common/chrome_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/services/app_service/public/cpp/file_handler.h"
 #include "components/site_engagement/content/site_engagement_service.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/feature_list.h"
@@ -131,4 +139,25 @@
 #endif
 }
 
+std::vector<std::string> GetFileExtensionsHandledByWebApp(Profile* profile,
+                                                          const GURL& url) {
+  auto* provider = WebAppProviderBase::GetProviderBase(profile);
+  const AppRegistrar& registrar = provider->registrar();
+  const apps::FileHandlers* handlers =
+      registrar.GetAppFileHandlers(*registrar.FindAppWithUrlInScope(url));
+  DCHECK(handlers);
+  std::set<std::string> extensions =
+      apps::GetFileExtensionsFromFileHandlers(*handlers);
+  return std::vector<std::string>(extensions.begin(), extensions.end());
+}
+
+std::u16string GetFileExtensionsHandledByWebAppDisplayedAsList(
+    Profile* profile,
+    const GURL& url) {
+  return base::UTF8ToUTF16(base::JoinString(
+      GetFileExtensionsHandledByWebApp(profile, url),
+      l10n_util::GetStringUTF8(
+          IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR)));
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_utils.h b/chrome/browser/web_applications/components/web_app_utils.h
index 6955d1b..a083f0f1 100644
--- a/chrome/browser/web_applications/components/web_app_utils.h
+++ b/chrome/browser/web_applications/components/web_app_utils.h
@@ -6,9 +6,11 @@
 #define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_UTILS_H_
 
 #include <string>
+#include <vector>
 
 #include "chrome/browser/web_applications/components/web_app_id.h"
 
+class GURL;
 class Profile;
 
 namespace base {
@@ -69,6 +71,18 @@
 // Returns true if the WebApp should have `web_app::WebAppChromeOsData()`.
 bool IsChromeOs();
 
+// Returns a vector of file extensions of the form ".csv" which are handled by
+// the app for `url`. It is an error to call this with a URL that doesn't
+// correspond to an app in `profile`.
+std::vector<std::string> GetFileExtensionsHandledByWebApp(Profile* profile,
+                                                          const GURL& url);
+
+// Returns a display-ready string that holds all the file extensions handled by
+// the app for `url`. It is an error to call this with a URL that doesn't
+// correspond to an app in `profile`.
+std::u16string GetFileExtensionsHandledByWebAppDisplayedAsList(Profile* profile,
+                                                               const GURL& url);
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_UTILS_H_
diff --git a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc
index cc8d6da..a91abc6 100644
--- a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc
@@ -69,6 +69,7 @@
 #include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "components/policy/core/common/policy_pref_names.h"
+#include "components/prefs/scoped_user_pref_update.h"
 #endif
 
 namespace {
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 014d6e1..1636e6d6 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1619708235-7e1e7e3636eed85ed74cd7563556a99c585fc339.profdata
+chrome-win64-master-1619740759-58a57fa30c345013ca92b76ecb2dc6a0fb51c11b.profdata
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json
index d5e059f..4341e398 100644
--- a/chrome/common/extensions/api/_manifest_features.json
+++ b/chrome/common/extensions/api/_manifest_features.json
@@ -42,14 +42,6 @@
     "channel": "stable",
     "extension_types": "all"
   },
-  "automation": [{
-    "channel": "dev",
-    "extension_types": ["extension", "legacy_packaged_app", "platform_app"]
-  }, {
-    "channel": "stable",
-    "extension_types": ["extension", "legacy_packaged_app"],
-    "allowlist": [ "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E" ]
-  }],
   "browser_action": {
     "channel": "stable",
     "extension_types": ["extension"],
diff --git a/chrome/common/extensions/chrome_manifest_handlers.cc b/chrome/common/extensions/chrome_manifest_handlers.cc
index 57ba6fb..f52df2f 100644
--- a/chrome/common/extensions/chrome_manifest_handlers.cc
+++ b/chrome/common/extensions/chrome_manifest_handlers.cc
@@ -25,7 +25,6 @@
 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
 #include "chrome/common/extensions/manifest_handlers/theme_handler.h"
 #include "extensions/common/manifest_handlers/app_isolation_info.h"
-#include "extensions/common/manifest_handlers/automation.h"
 #include "extensions/common/manifest_handlers/options_page_info.h"
 #include "extensions/common/manifest_url_handlers.h"
 
@@ -49,7 +48,6 @@
   registry->RegisterHandler(std::make_unique<AppThemeColorHandler>());
   registry->RegisterHandler(std::make_unique<AppIsolationHandler>());
   registry->RegisterHandler(std::make_unique<AppLaunchManifestHandler>());
-  registry->RegisterHandler(std::make_unique<AutomationHandler>());
   registry->RegisterHandler(std::make_unique<CommandsHandler>());
   registry->RegisterHandler(std::make_unique<DevToolsPageHandler>());
   registry->RegisterHandler(std::make_unique<HomepageURLHandler>());
diff --git a/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc b/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc
index 5c6e01e..4b5592c 100644
--- a/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc
+++ b/chrome/services/speech/cros_speech_recognition_recognizer_impl.cc
@@ -46,14 +46,12 @@
           std::move(options),
           binary_path,
           config_path),
-      enable_soda_(base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption)),
       binary_path_(binary_path),
       languagepack_path_(config_path) {
   recognition_event_callback_ = base::BindRepeating(
       &CrosSpeechRecognitionRecognizerImpl::OnRecognitionEvent,
       weak_factory_.GetWeakPtr());
-  DCHECK(enable_soda_) << "This class is only expected to run with soda "
-                          "enabled, but it can without.";
+  // The superclass handles speech recognition when soda is not enabled.
   if (enable_soda_) {
     cros_soda_client_ = std::make_unique<soda::CrosSodaClient>();
   }
@@ -63,9 +61,8 @@
     SendAudioToSpeechRecognitionServiceInternal(
         media::mojom::AudioDataS16Ptr buffer) {
   if (!enable_soda_) {
-    // Defer to the superclass.
-    LOG(DFATAL) << "This class is only expected to be used when soda is "
-                   "enabled; Deferring to superclass.";
+    // This class is only expected to be used when soda is enabled; deferring to
+    // superclass.
     SpeechRecognitionRecognizerImpl::
         SendAudioToSpeechRecognitionServiceInternal(std::move(buffer));
     return;
diff --git a/chrome/services/speech/cros_speech_recognition_recognizer_impl.h b/chrome/services/speech/cros_speech_recognition_recognizer_impl.h
index b29f28f8..ba8e5ab8 100644
--- a/chrome/services/speech/cros_speech_recognition_recognizer_impl.h
+++ b/chrome/services/speech/cros_speech_recognition_recognizer_impl.h
@@ -62,7 +62,6 @@
   // recognition event client remote.
   OnRecognitionEventCallback recognition_event_callback_;
 
-  const bool enable_soda_;
   const base::FilePath binary_path_, languagepack_path_;
 
   base::WeakPtrFactory<CrosSpeechRecognitionRecognizerImpl> weak_factory_{this};
diff --git a/chrome/services/speech/speech_recognition_recognizer_impl.cc b/chrome/services/speech/speech_recognition_recognizer_impl.cc
index 0d31b82..f3f5822 100644
--- a/chrome/services/speech/speech_recognition_recognizer_impl.cc
+++ b/chrome/services/speech/speech_recognition_recognizer_impl.cc
@@ -149,7 +149,8 @@
     media::mojom::SpeechRecognitionOptionsPtr options,
     const base::FilePath& binary_path,
     const base::FilePath& config_path)
-    : client_remote_(std::move(remote)),
+    : enable_soda_(base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption)),
+      client_remote_(std::move(remote)),
       config_path_(config_path),
       options_(std::move(options)) {
   recognition_event_callback_ = media::BindToCurrentLoop(
@@ -159,18 +160,17 @@
       media::BindToCurrentLoop(base::BindRepeating(
           &SpeechRecognitionRecognizerImpl::OnLanguageIdentificationEvent,
           weak_factory_.GetWeakPtr()));
-  // On Chrome OS Ash, soda_client_ is not used, so don't try to create it
-  // here because it exists at a different location. Instead,
-  // CrosSpeechRecognitionRecognizerImpl has its own CrosSodaClient.
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-  enable_soda_ = base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption);
-#endif
   if (enable_soda_) {
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+    // On Chrome OS Ash, soda_client_ is not used, so don't try to create it
+    // here because it exists at a different location. Instead,
+    // CrosSpeechRecognitionRecognizerImpl has its own CrosSodaClient.
     DCHECK(base::PathExists(binary_path));
     soda_client_ = std::make_unique<::soda::SodaClient>(binary_path);
     if (!soda_client_->BinaryLoadedSuccessfully()) {
       OnSpeechRecognitionError();
     }
+#endif
   } else {
     cloud_client_ = std::make_unique<CloudSpeechRecognitionClient>(
         recognition_event_callback(),
diff --git a/chrome/services/speech/speech_recognition_recognizer_impl.h b/chrome/services/speech/speech_recognition_recognizer_impl.h
index 5259436c..ca25fe7 100644
--- a/chrome/services/speech/speech_recognition_recognizer_impl.h
+++ b/chrome/services/speech/speech_recognition_recognizer_impl.h
@@ -83,6 +83,8 @@
       const std::string& language,
       const media::mojom::ConfidenceLevel confidence_level);
 
+  const bool enable_soda_;
+
  private:
   void OnCaptionBubbleClosed() final;
 
@@ -99,7 +101,6 @@
   // the speech recognition service back to the renderer.
   mojo::Remote<media::mojom::SpeechRecognitionRecognizerClient> client_remote_;
 
-  bool enable_soda_ = false;
   std::unique_ptr<soda::SodaClient> soda_client_;
 
   std::unique_ptr<CloudSpeechRecognitionClient> cloud_client_;
diff --git a/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js b/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
index 1ca26283..a95feb1 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/fake_network_health_provider_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {NetworkListObserver} from 'chrome://diagnostics/diagnostics_types.js';
-import {fakeNetworkGuids} from 'chrome://diagnostics/fake_data.js';
+import {fakeNetworkGuidInfoList} from 'chrome://diagnostics/fake_data.js';
 import {FakeNetworkHealthProvider} from 'chrome://diagnostics/fake_network_health_provider.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
 
@@ -23,8 +23,8 @@
 
   test('ObserveNetworkListTwiceWithTrigger', () => {
     // The fake needs to have at least 2 samples.
-    assertTrue(fakeNetworkGuids.length >= 2);
-    provider.setFakeNetworkGuids(fakeNetworkGuids);
+    assertTrue(fakeNetworkGuidInfoList.length >= 2);
+    provider.setFakeNetworkGuidInfo(fakeNetworkGuidInfoList);
 
     // Keep track of which observation we should get.
     let whichSample = 0;
@@ -37,7 +37,7 @@
         // Only expect 2 calls.
         assertTrue(whichSample >= 0);
         assertTrue(whichSample <= 1);
-        assertDeepEquals(fakeNetworkGuids[whichSample], networkGuids);
+        assertDeepEquals(fakeNetworkGuidInfoList[whichSample], networkGuids);
 
         if (whichSample === 0) {
           firstResolver.resolve();
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js
index 35db6b2..f4c2c548 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js
@@ -256,4 +256,25 @@
 
     assertEquals(2, deviceState.simLockStatus.retriesLeft);
   });
+
+  test('Close dialog on cancel event pressed', async function() {
+    // cancel event can be triggered by pressing the Escape key
+    const mojom = chromeos.networkConfig.mojom;
+    simLockDialog.deviceState = {
+      type: mojom.NetworkType.kCellular,
+      deviceState: chromeos.networkConfig.mojom.DeviceStateType.kEnabled,
+      simInfos: [{slot_id: 0, iccid: '1111111111111111'}],
+      simLockStatus: {lockEnabled: false, lockType: '', retriesLeft: 3}
+    };
+
+    await flushAsync();
+    const enterPinDialog = simLockDialog.$$('#enterPinDialog');
+    assertTrue(!!enterPinDialog);
+    assertTrue(enterPinDialog.open);
+    assertTrue(simLockDialog.isDialogOpen);
+    enterPinDialog.fire('cancel');
+    await flushAsync();
+    assertFalse(enterPinDialog.open);
+    assertFalse(simLockDialog.isDialogOpen);
+  });
 });
\ No newline at end of file
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
index c5e0de2..6b947cb2 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
@@ -46,9 +46,6 @@
     mojoApi_ = new FakeNetworkConfig();
     network_config.MojoInterfaceProviderImpl.getInstance().remote_ = mojoApi_;
 
-    eSimManagerRemote = new cellular_setup.FakeESimManagerRemote();
-    cellular_setup.setESimManagerRemoteForTesting(eSimManagerRemote);
-
     // Disable animations so sub-pages open within one event loop.
     testing.Test.disableAnimationsAndTransitions();
   });
@@ -90,6 +87,9 @@
   }
 
   setup(function() {
+    eSimManagerRemote = new cellular_setup.FakeESimManagerRemote();
+    cellular_setup.setESimManagerRemoteForTesting(eSimManagerRemote);
+
     PolymerTest.clearBody();
     internetPage = document.createElement('settings-internet-page');
     assertTrue(!!internetPage);
@@ -442,6 +442,37 @@
         assertFalse(!!internetPage.$$('#cellularSetupDialog'));
       });
 
+  test(
+      'Show profile limit reached toast if route params' +
+          'contains showCellularSetup, does not contain showPsimFlow,' +
+          'connected to a non-cellular network, cellular enabled,' +
+          'but profile limit is reached',
+      async function() {
+        loadTimeData.overrideValues({
+          updatedCellularActivationUi: true,
+        });
+        eSimManagerRemote.addEuiccForTest(/*numProfiles=*/ 5);
+
+        const mojom = chromeos.networkConfig.mojom;
+        const wifiNetwork =
+            OncMojo.getDefaultNetworkState(mojom.NetworkType.kWiFi, 'wifi');
+        wifiNetwork.connectionState = mojom.ConnectionStateType.kOnline;
+        mojoApi_.addNetworksForTest([wifiNetwork]);
+        await flushAsync();
+
+        const cellularSetupDialog = internetPage.$$('#cellularSetupDialog');
+        assertFalse(!!cellularSetupDialog);
+
+        await navigateToCellularSetupDialog(
+            /*showPSimFlow=*/ false, /*isCellularEnabled=*/ true);
+
+        assertTrue(internetPage.$.errorToast.open);
+        assertEquals(
+            internetPage.$.errorToastMessage.innerHTML,
+            internetPage.i18n('eSimProfileLimitReachedErrorToast', 5));
+        assertFalse(!!internetPage.$$('#cellularSetupDialog'));
+      });
+
   test('Show sim lock dialog through URL parameters', async () => {
     loadTimeData.overrideValues({
       updatedCellularActivationUi: true,
@@ -471,6 +502,7 @@
       'Show no connection toast if receive show-cellular-setup' +
           'event and not connected to non-cellular network',
       async function() {
+        eSimManagerRemote.addEuiccForTest(/*numProfiles=*/ 1);
         mojoApi_.setNetworkTypeEnabledState(
             chromeos.networkConfig.mojom.NetworkType.kCellular, true);
         await flushAsync();
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 40b68352..92b4d4e0 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -310,6 +310,8 @@
       "cast_content_window_aura.cc",
       "cast_content_window_aura.h",
       "cast_web_service_aura.cc",
+      "display_configurator_observer.cc",
+      "display_configurator_observer.h",
     ]
 
     deps += [
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index ffe5ccf..307152c 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -616,6 +616,9 @@
         std::make_unique<RoundedWindowCornersManager>(window_manager_.get());
   }
 
+  display_change_observer_ = std::make_unique<DisplayConfiguratorObserver>(
+      cast_browser_process_->display_configurator(), window_manager_.get());
+
 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
   cast_browser_process_->SetAccessibilityManager(
       std::make_unique<AccessibilityManagerImpl>(window_manager_.get()));
@@ -765,14 +768,19 @@
   // Android does not use native main MessageLoop.
   NOTREACHED();
 #else
-  cast_browser_process_->cast_service()->Finalize();
-  cast_browser_process_->cast_browser_metrics()->Finalize();
-  cast_browser_process_.reset();
 
 #if defined(USE_AURA)
   rounded_window_corners_manager_.reset();
+  // Reset display change observer here to ensure it is deleted before
+  // display_configurator since display_configurator is deleted when
+  // cast_browser_process is reset below.
+  display_change_observer_.reset();
 #endif
 
+  cast_browser_process_->cast_service()->Finalize();
+  cast_browser_process_->cast_browser_metrics()->Finalize();
+  cast_browser_process_.reset();
+
   window_manager_.reset();
 #if defined(USE_AURA)
   display::Screen::SetScreenInstance(nullptr);
diff --git a/chromecast/browser/cast_browser_main_parts.h b/chromecast/browser/cast_browser_main_parts.h
index e4b7be6..dd51c86 100644
--- a/chromecast/browser/cast_browser_main_parts.h
+++ b/chromecast/browser/cast_browser_main_parts.h
@@ -12,6 +12,7 @@
 #include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
+#include "chromecast/browser/display_configurator_observer.h"
 #include "chromecast/chromecast_buildflags.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_main_parts.h"
@@ -105,6 +106,7 @@
   std::unique_ptr<CastScreen> cast_screen_;
   std::unique_ptr<CastWindowManagerAura> window_manager_;
   std::unique_ptr<RoundedWindowCornersManager> rounded_window_corners_manager_;
+  std::unique_ptr<DisplayConfiguratorObserver> display_change_observer_;
 #else
   std::unique_ptr<CastWindowManager> window_manager_;
 #endif  //  defined(USE_AURA)
diff --git a/chromecast/browser/cast_display_configurator.cc b/chromecast/browser/cast_display_configurator.cc
index bfbaac8..5eefbfa 100644
--- a/chromecast/browser/cast_display_configurator.cc
+++ b/chromecast/browser/cast_display_configurator.cc
@@ -141,6 +141,7 @@
   config_request.push_back(std::move(display_config_params));
 
   delegate_->Configure(config_request, std::move(callback));
+  NotifyObservers();
 }
 
 void CastDisplayConfigurator::DisableDisplay(
@@ -167,6 +168,7 @@
   if (!delegate_ || !display_)
     return;
   delegate_->SetColorMatrix(display_->display_id(), color_matrix);
+  NotifyObservers();
 }
 
 void CastDisplayConfigurator::SetGammaCorrection(
@@ -176,6 +178,12 @@
     return;
 
   delegate_->SetGammaCorrection(display_->display_id(), degamma_lut, gamma_lut);
+  NotifyObservers();
+}
+
+void CastDisplayConfigurator::NotifyObservers() {
+  for (Observer& observer : observers_)
+    observer.OnDisplayStateChanged();
 }
 
 void CastDisplayConfigurator::ForceInitialConfigure() {
@@ -265,5 +273,13 @@
   touch_device_manager_->OnDisplayConfigured(display_id, rotation, bounds);
 }
 
+void CastDisplayConfigurator::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void CastDisplayConfigurator::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 }  // namespace shell
 }  // namespace chromecast
diff --git a/chromecast/browser/cast_display_configurator.h b/chromecast/browser/cast_display_configurator.h
index 0c45c3b..d9c6791 100644
--- a/chromecast/browser/cast_display_configurator.h
+++ b/chromecast/browser/cast_display_configurator.h
@@ -11,6 +11,7 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "ui/display/display.h"
 #include "ui/display/types/display_configuration_params.h"
 #include "ui/display/types/native_display_delegate.h"
@@ -40,6 +41,12 @@
 // doesn't really do anything when using OzonePlatformCast.
 class CastDisplayConfigurator : public display::NativeDisplayObserver {
  public:
+  class Observer {
+   public:
+    virtual ~Observer() = default;
+    virtual void OnDisplayStateChanged() = 0;
+  };
+
   explicit CastDisplayConfigurator(CastScreen* screen);
   ~CastDisplayConfigurator() override;
 
@@ -50,6 +57,9 @@
   void EnableDisplay(display::ConfigureCallback callback);
   void DisableDisplay(display::ConfigureCallback callback);
 
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
   void ConfigureDisplayFromCommandLine();
   void SetColorMatrix(const std::vector<float>& color_matrix);
   void SetGammaCorrection(
@@ -58,6 +68,7 @@
 
  private:
   void ForceInitialConfigure();
+  void NotifyObservers();
   void OnDisplaysAcquired(
       bool force_initial_configure,
       const std::vector<display::DisplaySnapshot*>& displays);
@@ -70,6 +81,8 @@
                     float device_scale_factor,
                     display::Display::Rotation rotation);
 
+  base::ObserverList<Observer>::Unchecked observers_;
+
   std::unique_ptr<display::NativeDisplayDelegate> delegate_;
   std::unique_ptr<CastTouchDeviceManager> touch_device_manager_;
   display::DisplaySnapshot* display_;
diff --git a/chromecast/browser/display_configurator_observer.cc b/chromecast/browser/display_configurator_observer.cc
new file mode 100644
index 0000000..48dd539
--- /dev/null
+++ b/chromecast/browser/display_configurator_observer.cc
@@ -0,0 +1,27 @@
+// 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 "display_configurator_observer.h"
+
+namespace chromecast {
+
+DisplayConfiguratorObserver::DisplayConfiguratorObserver(
+    chromecast::shell::CastDisplayConfigurator* display_configurator,
+    chromecast::CastWindowManagerAura* manager)
+    : display_configurator_(display_configurator), window_manager_(manager) {
+  display_configurator_->AddObserver(this);
+}
+
+DisplayConfiguratorObserver::~DisplayConfiguratorObserver() {
+  display_configurator_->RemoveObserver(this);
+}
+
+void DisplayConfiguratorObserver::OnDisplayStateChanged() {
+  window_manager_->GetRootWindow()
+      ->GetHost()
+      ->compositor()
+      ->ScheduleFullRedraw();
+}
+
+}  // namespace chromecast
diff --git a/chromecast/browser/display_configurator_observer.h b/chromecast/browser/display_configurator_observer.h
new file mode 100644
index 0000000..6f33bc19
--- /dev/null
+++ b/chromecast/browser/display_configurator_observer.h
@@ -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.
+
+#ifndef CHROMECAST_BROWSER_DISPLAY_CONFIGURATOR_OBSERVER_H_
+#define CHROMECAST_BROWSER_DISPLAY_CONFIGURATOR_OBSERVER_H_
+
+#include <memory>
+
+#include "chromecast/browser/cast_display_configurator.h"
+#include "chromecast/graphics/cast_window_manager_aura.h"
+
+namespace chromecast {
+
+// Observer class that can respond to Display Configurator state changes.
+// Forces a repaint to ensure content is refreshed post display configuration
+// change.
+class DisplayConfiguratorObserver
+    : public shell::CastDisplayConfigurator::Observer {
+ public:
+  DisplayConfiguratorObserver(
+      shell::CastDisplayConfigurator* display_configurator,
+      CastWindowManagerAura* manager);
+
+  ~DisplayConfiguratorObserver() override;
+
+  DisplayConfiguratorObserver(const DisplayConfiguratorObserver&) = delete;
+
+  DisplayConfiguratorObserver& operator=(const DisplayConfiguratorObserver&) =
+      delete;
+
+  // CastDisplayConfigurator::Observer
+  void OnDisplayStateChanged() override;
+
+ private:
+  shell::CastDisplayConfigurator* display_configurator_;
+  CastWindowManagerAura* window_manager_;
+};
+
+}  // namespace chromecast
+
+#endif  // CHROMECAST_BROWSER_DISPLAY_CONFIGURATOR_OBSERVER_H_
diff --git a/chromecast/common/cast_extensions_api_provider.cc b/chromecast/common/cast_extensions_api_provider.cc
index 7f312f3..0686b4cf 100644
--- a/chromecast/common/cast_extensions_api_provider.cc
+++ b/chromecast/common/cast_extensions_api_provider.cc
@@ -14,7 +14,6 @@
 #include "chromecast/common/extensions_api/generated_schemas.h"
 #include "extensions/common/features/json_feature_provider_source.h"
 #include "extensions/common/manifest_handler.h"
-#include "extensions/common/manifest_handlers/automation.h"
 #include "extensions/common/permissions/permissions_info.h"
 #include "extensions/shell/grit/app_shell_resources.h"
 
@@ -65,8 +64,6 @@
   // TODO(devlin): Pass in |registry| rather than Get()ing it.
   ManifestHandlerRegistry* registry = ManifestHandlerRegistry::Get();
 
-  // TODO(crbug/837773) De-dupe later.
-  registry->RegisterHandler(std::make_unique<AutomationHandler>());
   registry->RegisterHandler(
       std::make_unique<chromecast::CastRedirectHandler>());
 }
diff --git a/chromecast/common/extensions_api/_manifest_features.json b/chromecast/common/extensions_api/_manifest_features.json
index c183c0a..21e0462c 100644
--- a/chromecast/common/extensions_api/_manifest_features.json
+++ b/chromecast/common/extensions_api/_manifest_features.json
@@ -3,15 +3,6 @@
 // found in the LICENSE file.
 
 {
-  // TODO(crbug/837773) De-dupe automation later.
-  "automation": [{
-    "channel": "dev",
-    "extension_types": ["extension", "legacy_packaged_app", "platform_app"]
-  }, {
-    "channel": "stable",
-    "extension_types": ["extension", "legacy_packaged_app"],
-    "allowlist": [ "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E" ]
-  }],
   "cast_redirect": {
     "channel": "stable",
     "extension_types": ["platform_app"]
diff --git a/chromecast/ui/display_settings/color_temperature_animation.cc b/chromecast/ui/display_settings/color_temperature_animation.cc
index 9878441..d7e4e0e 100644
--- a/chromecast/ui/display_settings/color_temperature_animation.cc
+++ b/chromecast/ui/display_settings/color_temperature_animation.cc
@@ -9,10 +9,6 @@
 
 #include "base/numerics/ranges.h"
 #include "base/time/time.h"
-#include "chromecast/graphics/cast_window_manager.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/compositor/compositor.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 
 #if defined(USE_AURA)
@@ -39,19 +35,16 @@
 }  // namespace
 
 ColorTemperatureAnimation::ColorTemperatureAnimation(
-    CastWindowManager* window_manager,
     shell::CastDisplayConfigurator* display_configurator,
     const DisplaySettingsManager::ColorTemperatureConfig& config)
     : gfx::LinearAnimation(kManualAnimationDuration,
                            kAnimationFrameRate,
                            nullptr),
-      window_manager_(window_manager),
       display_configurator_(display_configurator),
       config_(config),
       start_temperature_(config.neutral_temperature),
       current_temperature_(config.neutral_temperature),
       target_temperature_(config_.neutral_temperature) {
-  DCHECK(window_manager_);
 #if defined(USE_AURA)
   DCHECK(display_configurator_);
 #endif  // defined(USE_AURA)
@@ -123,12 +116,6 @@
     std::vector<float> color_matrix = {red_scale, 0, 0, 0,         green_scale,
                                        0,         0, 0, blue_scale};
     display_configurator_->SetColorMatrix(color_matrix);
-    // The CTM is applied on the next swap buffers, so we need to make sure the
-    // root window triggers a swap buffer otherwise the content will not update.
-    window_manager_->GetRootWindow()
-        ->GetHost()
-        ->compositor()
-        ->ScheduleFullRedraw();
 #endif  // defined(USE_AURA)
   }
 }
diff --git a/chromecast/ui/display_settings/color_temperature_animation.h b/chromecast/ui/display_settings/color_temperature_animation.h
index f92d797..8d4aeb8d 100644
--- a/chromecast/ui/display_settings/color_temperature_animation.h
+++ b/chromecast/ui/display_settings/color_temperature_animation.h
@@ -13,8 +13,6 @@
 
 namespace chromecast {
 
-class CastWindowManager;
-
 namespace shell {
 class CastDisplayConfigurator;
 }
@@ -24,7 +22,6 @@
 class ColorTemperatureAnimation : public gfx::LinearAnimation {
  public:
   ColorTemperatureAnimation(
-      CastWindowManager* window_manager,
       shell::CastDisplayConfigurator* display_configurator,
       const DisplaySettingsManager::ColorTemperatureConfig& config);
   ColorTemperatureAnimation(const ColorTemperatureAnimation&) = delete;
@@ -47,7 +44,6 @@
 
   void ApplyValuesToDisplay();
 
-  CastWindowManager* const window_manager_;
   shell::CastDisplayConfigurator* const display_configurator_;
 
   const DisplaySettingsManager::ColorTemperatureConfig config_;
diff --git a/chromecast/ui/display_settings/gamma_configurator.cc b/chromecast/ui/display_settings/gamma_configurator.cc
index 427eb22..639f48fe 100644
--- a/chromecast/ui/display_settings/gamma_configurator.cc
+++ b/chromecast/ui/display_settings/gamma_configurator.cc
@@ -7,10 +7,6 @@
 #include <limits>
 
 #include "chromecast/browser/cast_display_configurator.h"
-#include "chromecast/graphics/cast_window_manager.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/compositor/compositor.h"
 
 namespace chromecast {
 namespace {
@@ -45,11 +41,8 @@
 }  // namespace
 
 GammaConfigurator::GammaConfigurator(
-    CastWindowManager* window_manager,
     shell::CastDisplayConfigurator* display_configurator)
-    : window_manager_(window_manager),
-      display_configurator_(display_configurator) {
-  DCHECK(window_manager_);
+    : display_configurator_(display_configurator) {
   DCHECK(display_configurator_);
 }
 
@@ -69,13 +62,6 @@
     display_configurator_->SetGammaCorrection({}, InvertGammaLut(gamma_lut_));
   else
     display_configurator_->SetGammaCorrection({}, gamma_lut_);
-
-  // The LUT is applied on the next swap buffers, so we need to make sure the
-  // root window triggers a swap buffer otherwise the content will not update.
-  window_manager_->GetRootWindow()
-      ->GetHost()
-      ->compositor()
-      ->ScheduleFullRedraw();
 }
 
 void GammaConfigurator::SetColorInversion(bool invert) {
diff --git a/chromecast/ui/display_settings/gamma_configurator.h b/chromecast/ui/display_settings/gamma_configurator.h
index dcf53f97..9b29bcd 100644
--- a/chromecast/ui/display_settings/gamma_configurator.h
+++ b/chromecast/ui/display_settings/gamma_configurator.h
@@ -11,16 +11,14 @@
 
 namespace chromecast {
 
-class CastWindowManager;
-
 namespace shell {
 class CastDisplayConfigurator;
 }  // namespace shell
 
 class GammaConfigurator {
  public:
-  GammaConfigurator(CastWindowManager* window_manager,
-                    shell::CastDisplayConfigurator* display_configurator);
+  explicit GammaConfigurator(
+      shell::CastDisplayConfigurator* display_configurator);
   GammaConfigurator(const GammaConfigurator&) = delete;
   GammaConfigurator& operator=(const GammaConfigurator&) = delete;
   ~GammaConfigurator();
@@ -33,7 +31,6 @@
  private:
   void ApplyGammaLut();
 
-  CastWindowManager* const window_manager_;
   shell::CastDisplayConfigurator* display_configurator_;
 
   bool is_initialized_ = false;
diff --git a/chromecast/ui/display_settings_manager_impl.cc b/chromecast/ui/display_settings_manager_impl.cc
index 156dd26..b5a1d63 100644
--- a/chromecast/ui/display_settings_manager_impl.cc
+++ b/chromecast/ui/display_settings_manager_impl.cc
@@ -17,8 +17,6 @@
 #include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/cast_display_configurator.h"
 #include "chromecast/ui/display_settings/gamma_configurator.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
 #endif  // defined(USE_AURA)
 
 namespace chromecast {
@@ -42,15 +40,13 @@
       display_configurator_(
           shell::CastBrowserProcess::GetInstance()->display_configurator()),
       gamma_configurator_(
-          std::make_unique<GammaConfigurator>(window_manager_,
-                                              display_configurator_)),
+          std::make_unique<GammaConfigurator>(display_configurator_)),
 #else
       display_configurator_(nullptr),
 #endif  // defined(USE_AURA)
       brightness_(-1.0f),
       screen_power_controller_(ScreenPowerController::Create(this)),
       color_temperature_animation_(std::make_unique<ColorTemperatureAnimation>(
-          window_manager_,
           display_configurator_,
           color_temperature_config)),
       weak_factory_(this) {
@@ -100,9 +96,7 @@
 
 void DisplaySettingsManagerImpl::SetScreenPowerOn(PowerToggleCallback callback) {
 #if defined(USE_AURA)
-  display_configurator_->EnableDisplay(
-      base::BindOnce(&DisplaySettingsManagerImpl::OnScreenEnabled,
-                     weak_factory_.GetWeakPtr(), std::move(callback)));
+  display_configurator_->EnableDisplay(std::move(callback));
 #endif  // defined(USE_AURA)
 }
 
@@ -196,17 +190,4 @@
     brightness_animation_->AnimateToNewValue(brightness, duration);
 }
 
-void DisplaySettingsManagerImpl::OnScreenEnabled(PowerToggleCallback callback,
-                                                 bool status) {
-#if defined(USE_AURA)
-  // Force a swap buffers otherwise we might be stuck showing the modeset
-  // buffer.
-  window_manager_->GetRootWindow()
-      ->GetHost()
-      ->compositor()
-      ->ScheduleFullRedraw();
-#endif  // defined(USE_AURA)
-  std::move(callback).Run(status);
-}
-
 }  // namespace chromecast
diff --git a/chromecast/ui/display_settings_manager_impl.h b/chromecast/ui/display_settings_manager_impl.h
index f1398e3..ec0bef59 100644
--- a/chromecast/ui/display_settings_manager_impl.h
+++ b/chromecast/ui/display_settings_manager_impl.h
@@ -80,8 +80,6 @@
 
   void UpdateBrightness(float brightness, base::TimeDelta duration);
 
-  void OnScreenEnabled(PowerToggleCallback callback, bool status);
-
   CastWindowManager* const window_manager_;
   shell::CastDisplayConfigurator* const display_configurator_;
 
diff --git a/chromeos/components/diagnostics_ui/resources/fake_data.js b/chromeos/components/diagnostics_ui/resources/fake_data.js
index de9e8b5..8a0b20e 100644
--- a/chromeos/components/diagnostics_ui/resources/fake_data.js
+++ b/chromeos/components/diagnostics_ui/resources/fake_data.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BatteryChargeStatus, BatteryHealth, BatteryInfo, CpuUsage, ExternalPowerSource, MemoryUsage, PowerRoutineResult, RoutineType, StandardRoutineResult, SystemInfo} from './diagnostics_types.js'
+import {BatteryChargeStatus, BatteryHealth, BatteryInfo, CpuUsage, ExternalPowerSource, MemoryUsage, NetworkGuidInfo, PowerRoutineResult, RoutineType, StandardRoutineResult, SystemInfo} from './diagnostics_types.js'
 import {stringToMojoString16} from './mojo_utils.js';
 
 /** @type {!Array<!BatteryChargeStatus>} */
@@ -253,17 +253,20 @@
   ],
 ]);
 
-export const fakeNetworkGuids = [
-  {
-    networkGuids: ['guid_1', 'guid_2'],
-    activeGuid: 'active_guid',
-  },
-  {
-    networkGuids: ['guid_1'],
-    activeGuid: 'active_guid',
-  },
-  {
-    networkGuids: ['guid_1', 'guid_3'],
-    activeGuid: '',
-  },
-]
+/** @type {!NetworkGuidInfo} */
+export const fakeAllNetworksAvailable = {
+  networkGuids: ['wifiGuid', 'ethernetGuid', 'cellularGuid'],
+  activeGuid: 'ethernetGuid',
+};
+
+/** @type {!NetworkGuidInfo} */
+export const fakeWifiAndCellularNetworksAvailable = {
+  networkGuids: ['cellularGuid', 'wifiGuid'],
+  activeGuid: 'wifiGuid',
+};
+
+/** @type {!Array<!NetworkGuidInfo>} */
+export const fakeNetworkGuidInfoList = [
+  fakeAllNetworksAvailable,
+  fakeWifiAndCellularNetworksAvailable,
+];
diff --git a/chromeos/components/diagnostics_ui/resources/fake_network_health_provider.js b/chromeos/components/diagnostics_ui/resources/fake_network_health_provider.js
index ece112ec..084021a 100644
--- a/chromeos/components/diagnostics_ui/resources/fake_network_health_provider.js
+++ b/chromeos/components/diagnostics_ui/resources/fake_network_health_provider.js
@@ -37,11 +37,11 @@
 
   /**
    * Sets the values that will be observed from observeNetworkList.
-   * @param {!Array<!NetworkGuidInfo>} networkGuidList
+   * @param {!Array<!NetworkGuidInfo>} networkGuidInfoList
    */
-  setFakeNetworkGuids(networkGuidList) {
+  setFakeNetworkGuidInfo(networkGuidInfoList) {
     this.observables_.setObservableData(
-        ON_NETWORK_LIST_CHANGED_METHOD_NAME, networkGuidList);
+        ON_NETWORK_LIST_CHANGED_METHOD_NAME, networkGuidInfoList);
   }
 
   /**
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index b600b6b..d4ae2343 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -19,6 +19,7 @@
     "//chromeos/dbus/constants",
     "//chromeos/dbus/debug_daemon",
     "//chromeos/dbus/lorgnette_manager",
+    "//chromeos/dbus/seneschal",
     "//chromeos/dbus/shill",
     "//dbus",
   ]
@@ -31,7 +32,6 @@
     ":oobe_config_proto",
     ":plugin_vm_service_proto",
     ":runtime_probe_proto",
-    ":seneschal_proto",
     ":smbprovider_proto",
     ":update_engine_proto",
     ":vm_applications_apps_proto",
@@ -84,8 +84,6 @@
     "fake_oobe_configuration_client.h",
     "fake_runtime_probe_client.cc",
     "fake_runtime_probe_client.h",
-    "fake_seneschal_client.cc",
-    "fake_seneschal_client.h",
     "fake_smb_provider_client.cc",
     "fake_smb_provider_client.h",
     "fake_update_engine_client.cc",
@@ -104,8 +102,6 @@
     "oobe_configuration_client.h",
     "runtime_probe_client.cc",
     "runtime_probe_client.h",
-    "seneschal_client.cc",
-    "seneschal_client.h",
     "smb_provider_client.cc",
     "smb_provider_client.h",
     "update_engine_client.cc",
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc
index 84deb1a6..755f73c 100644
--- a/chromeos/dbus/dbus_clients_browser.cc
+++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -38,7 +38,6 @@
 #include "chromeos/dbus/fake_image_loader_client.h"
 #include "chromeos/dbus/fake_oobe_configuration_client.h"
 #include "chromeos/dbus/fake_runtime_probe_client.h"
-#include "chromeos/dbus/fake_seneschal_client.h"
 #include "chromeos/dbus/fake_smb_provider_client.h"
 #include "chromeos/dbus/fake_virtual_file_provider_client.h"
 #include "chromeos/dbus/fake_vm_plugin_dispatcher_client.h"
@@ -49,7 +48,8 @@
 #include "chromeos/dbus/lorgnette_manager/lorgnette_manager_client.h"
 #include "chromeos/dbus/oobe_configuration_client.h"
 #include "chromeos/dbus/runtime_probe_client.h"
-#include "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/smb_provider_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "chromeos/dbus/virtual_file_provider_client.h"
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index bed50f0..bf20e69 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -33,7 +33,7 @@
 #include "chromeos/dbus/image_loader_client.h"
 #include "chromeos/dbus/lorgnette_manager/lorgnette_manager_client.h"
 #include "chromeos/dbus/runtime_probe_client.h"
-#include "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 #include "chromeos/dbus/shill/modem_messaging_client.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
diff --git a/chromeos/dbus/seneschal/BUILD.gn b/chromeos/dbus/seneschal/BUILD.gn
new file mode 100644
index 0000000..a3662ca0
--- /dev/null
+++ b/chromeos/dbus/seneschal/BUILD.gn
@@ -0,0 +1,23 @@
+# 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.
+
+assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+
+component("seneschal") {
+  defines = [ "IS_CHROMEOS_DBUS_IMPL" ]
+  deps = [
+    "//base",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus:seneschal_proto",
+    "//chromeos/dbus/cicerone",
+    "//dbus",
+  ]
+
+  sources = [
+    "fake_seneschal_client.cc",
+    "fake_seneschal_client.h",
+    "seneschal_client.cc",
+    "seneschal_client.h",
+  ]
+}
diff --git a/chromeos/dbus/fake_seneschal_client.cc b/chromeos/dbus/seneschal/fake_seneschal_client.cc
similarity index 96%
rename from chromeos/dbus/fake_seneschal_client.cc
rename to chromeos/dbus/seneschal/fake_seneschal_client.cc
index 911738d..7636eebc 100644
--- a/chromeos/dbus/fake_seneschal_client.cc
+++ b/chromeos/dbus/seneschal/fake_seneschal_client.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 "chromeos/dbus/fake_seneschal_client.h"
+#include "chromeos/dbus/seneschal/fake_seneschal_client.h"
 
 #include <utility>
 
diff --git a/chromeos/dbus/fake_seneschal_client.h b/chromeos/dbus/seneschal/fake_seneschal_client.h
similarity index 91%
rename from chromeos/dbus/fake_seneschal_client.h
rename to chromeos/dbus/seneschal/fake_seneschal_client.h
index b4e85e1a..a027554 100644
--- a/chromeos/dbus/fake_seneschal_client.h
+++ b/chromeos/dbus/seneschal/fake_seneschal_client.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_FAKE_SENESCHAL_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SENESCHAL_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SENESCHAL_FAKE_SENESCHAL_CLIENT_H_
+#define CHROMEOS_DBUS_SENESCHAL_FAKE_SENESCHAL_CLIENT_H_
 
 #include "base/observer_list.h"
-#include "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 
 namespace chromeos {
 
@@ -76,4 +76,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SENESCHAL_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SENESCHAL_FAKE_SENESCHAL_CLIENT_H_
diff --git a/chromeos/dbus/seneschal_client.cc b/chromeos/dbus/seneschal/seneschal_client.cc
similarity index 98%
rename from chromeos/dbus/seneschal_client.cc
rename to chromeos/dbus/seneschal/seneschal_client.cc
index fee027bc..ce3d8d8f 100644
--- a/chromeos/dbus/seneschal_client.cc
+++ b/chromeos/dbus/seneschal/seneschal_client.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 "chromeos/dbus/seneschal_client.h"
+#include "chromeos/dbus/seneschal/seneschal_client.h"
 
 #include <memory>
 
diff --git a/chromeos/dbus/seneschal_client.h b/chromeos/dbus/seneschal/seneschal_client.h
similarity index 93%
rename from chromeos/dbus/seneschal_client.h
rename to chromeos/dbus/seneschal/seneschal_client.h
index 42a37dba..725949cd 100644
--- a/chromeos/dbus/seneschal_client.h
+++ b/chromeos/dbus/seneschal/seneschal_client.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 CHROMEOS_DBUS_SENESCHAL_CLIENT_H_
-#define CHROMEOS_DBUS_SENESCHAL_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SENESCHAL_SENESCHAL_CLIENT_H_
+#define CHROMEOS_DBUS_SENESCHAL_SENESCHAL_CLIENT_H_
 
 #include "base/component_export.h"
 #include "base/observer_list.h"
@@ -69,4 +69,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SENESCHAL_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SENESCHAL_SENESCHAL_CLIENT_H_
diff --git a/chromeos/network/cellular_connection_handler.cc b/chromeos/network/cellular_connection_handler.cc
index 2c697130..88988db 100644
--- a/chromeos/network/cellular_connection_handler.cc
+++ b/chromeos/network/cellular_connection_handler.cc
@@ -404,7 +404,12 @@
     HermesResponseStatus status) {
   DCHECK_EQ(state_, ConnectionState::kEnablingProfile);
 
-  if (status != HermesResponseStatus::kSuccess) {
+  // If we try to enable and "fail" with an already-enabled error, count this as
+  // a success.
+  bool success = status == HermesResponseStatus::kSuccess ||
+                 status == HermesResponseStatus::kErrorAlreadyEnabled;
+
+  if (!success) {
     NET_LOG(ERROR) << "eSIM connection flow failed to enable profile";
     CompleteConnectionAttempt(NetworkConnectionHandler::kErrorESimProfileIssue);
     return;
diff --git a/chromeos/network/cellular_connection_handler_unittest.cc b/chromeos/network/cellular_connection_handler_unittest.cc
index 0a07416..bc681585 100644
--- a/chromeos/network/cellular_connection_handler_unittest.cc
+++ b/chromeos/network/cellular_connection_handler_unittest.cc
@@ -159,20 +159,25 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void AddProfile(int profile_num, int euicc_num, bool add_service = true) {
+  void AddProfile(int profile_num,
+                  int euicc_num,
+                  bool add_service = true,
+                  bool already_enabled = false) {
     auto add_profile_behavior =
         add_service
             ? HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
                   kAddProfileWithService
             : HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
                   kAddDelayedProfileWithoutService;
+    auto state = already_enabled ? hermes::profile::State::kActive
+                                 : hermes::profile::State::kInactive;
     std::string iccid = CreateTestIccid(profile_num);
 
     helper_.hermes_euicc_test()->AddCarrierProfile(
         dbus::ObjectPath(CreateTestProfilePath(profile_num)),
         dbus::ObjectPath(CreateTestEuiccPath(euicc_num)), iccid,
         CreateTestName(profile_num), "service_provider", "activation_code",
-        CreateTestServicePath(profile_num), hermes::profile::State::kInactive,
+        CreateTestServicePath(profile_num), state,
         hermes::profile::ProfileClass::kOperational, add_profile_behavior);
 
     if (!add_service) {
@@ -344,6 +349,24 @@
   ExpectServiceConnectable(/*profile_num=*/1);
 }
 
+TEST_F(CellularConnectionHandlerTest, Success_AlreadyEnabled) {
+  AddCellularDevice();
+  AddEuicc(/*euicc_num=*/1);
+  AddProfile(/*profile_num=*/1,
+             /*euicc_num=*/1,
+             /*add_service=*/true,
+             /*already_enabled=*/true);
+  SetServiceEid(/*profile_num=*/1, /*euicc_num=*/1);
+  SetServiceIccid(/*profile_num=*/1);
+
+  base::RunLoop run_loop;
+  ExpectSuccess(CreateTestServicePath(/*profile_num=*/1), &run_loop);
+  CallPrepareExistingCellularNetworkForConnection(/*profile_num=*/1);
+  SetServiceConnectable(/*profile_num=*/1);
+  run_loop.Run();
+  ExpectServiceConnectable(/*profile_num=*/1);
+}
+
 TEST_F(CellularConnectionHandlerTest, ConnectToStub) {
   AddCellularDevice();
   AddEuicc(/*euicc_num=*/1);
diff --git a/chromeos/network/cellular_esim_uninstall_handler.cc b/chromeos/network/cellular_esim_uninstall_handler.cc
index d9e482d..b5202ace 100644
--- a/chromeos/network/cellular_esim_uninstall_handler.cc
+++ b/chromeos/network/cellular_esim_uninstall_handler.cc
@@ -278,12 +278,20 @@
 void CellularESimUninstallHandler::TransitionUninstallStateOnHermesSuccess(
     UninstallState next_state,
     HermesResponseStatus status) {
-  if (status != HermesResponseStatus::kSuccess) {
+  bool success = status == HermesResponseStatus::kSuccess;
+
+  // If we try to disable and "fail" with an already-disabled error, count this
+  // as a success.
+  if (state_ == UninstallState::kDisablingProfile)
+    success |= status == HermesResponseStatus::kErrorAlreadyDisabled;
+
+  if (!success) {
     NET_LOG(ERROR) << "Hermes error on uninstallation state=" << state_
                    << " status=" << static_cast<int>(status);
     TransitionToUninstallState(UninstallState::kFailure);
     return;
   }
+
   TransitionToUninstallState(next_state);
 }
 
diff --git a/chromeos/network/cellular_esim_uninstall_handler_unittest.cc b/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
index 36c04d2a..a9cd715 100644
--- a/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
+++ b/chromeos/network/cellular_esim_uninstall_handler_unittest.cc
@@ -84,7 +84,6 @@
         std::make_unique<FakeStubCellularNetworksProvider>();
     network_state_handler_->set_stub_cellular_networks_provider(
         stub_cellular_networks_provider_.get());
-    SetupNetwork();
   }
 
   void TearDown() override {
@@ -100,6 +99,39 @@
     shill_clients::Shutdown();
   }
 
+  void Init(bool is_first_profile_active = true) {
+    auto first_profile_state = is_first_profile_active
+                                   ? hermes::profile::State::kActive
+                                   : hermes::profile::State::kInactive;
+
+    ShillDeviceClient::Get()->GetTestInterface()->AddDevice(
+        kDefaultCellularDevicePath, shill::kTypeCellular, "cellular1");
+    HermesManagerClient::Get()->GetTestInterface()->AddEuicc(
+        dbus::ObjectPath(kDefaultEuiccPath), kDefaultEid, /*is_active=*/true,
+        /*physical_slot=*/0);
+    HermesEuiccClient::Get()->GetTestInterface()->AddCarrierProfile(
+        dbus::ObjectPath(kTestCarrierProfilePath),
+        dbus::ObjectPath(kDefaultEuiccPath), kTestCellularIccid,
+        kTestProfileName, kTestServiceProvider, "", kTestNetworkServicePath,
+        first_profile_state, hermes::profile::ProfileClass::kOperational,
+        HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
+            kAddProfileWithService);
+    HermesEuiccClient::Get()->GetTestInterface()->AddCarrierProfile(
+        dbus::ObjectPath(kTestCarrierProfilePath2),
+        dbus::ObjectPath(kDefaultEuiccPath), kTestCellularIccid2,
+        kTestProfileName, kTestServiceProvider, "", kTestNetworkServicePath2,
+        hermes::profile::State::kInactive,
+        hermes::profile::ProfileClass::kOperational,
+        HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
+            kAddProfileWithService);
+    base::RunLoop().RunUntilIdle();
+
+    ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty(
+        kTestNetworkServicePath, shill::kStateProperty,
+        base::Value(shill::kStateOnline));
+    base::RunLoop().RunUntilIdle();
+  }
+
   void UninstallESim(base::RunLoop& run_loop,
                      const std::string& carrier_profile_path,
                      bool& status) {
@@ -142,36 +174,6 @@
   }
 
  private:
-  void SetupNetwork() {
-    ShillDeviceClient::Get()->GetTestInterface()->AddDevice(
-        kDefaultCellularDevicePath, shill::kTypeCellular, "cellular1");
-    HermesManagerClient::Get()->GetTestInterface()->AddEuicc(
-        dbus::ObjectPath(kDefaultEuiccPath), kDefaultEid, /*is_active=*/true,
-        /*physical_slot=*/0);
-    HermesEuiccClient::Get()->GetTestInterface()->AddCarrierProfile(
-        dbus::ObjectPath(kTestCarrierProfilePath),
-        dbus::ObjectPath(kDefaultEuiccPath), kTestCellularIccid,
-        kTestProfileName, kTestServiceProvider, "", kTestNetworkServicePath,
-        hermes::profile::State::kActive,
-        hermes::profile::ProfileClass::kOperational,
-        HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
-            kAddProfileWithService);
-    HermesEuiccClient::Get()->GetTestInterface()->AddCarrierProfile(
-        dbus::ObjectPath(kTestCarrierProfilePath2),
-        dbus::ObjectPath(kDefaultEuiccPath), kTestCellularIccid2,
-        kTestProfileName, kTestServiceProvider, "", kTestNetworkServicePath2,
-        hermes::profile::State::kInactive,
-        hermes::profile::ProfileClass::kOperational,
-        HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
-            kAddProfileWithService);
-    base::RunLoop().RunUntilIdle();
-
-    ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty(
-        kTestNetworkServicePath, shill::kStateProperty,
-        base::Value(shill::kStateOnline));
-    base::RunLoop().RunUntilIdle();
-  }
-
   base::test::SingleThreadTaskEnvironment task_environment_;
 
   std::unique_ptr<NetworkStateHandler> network_state_handler_;
@@ -188,7 +190,30 @@
 };
 
 TEST_F(CellularESimUninstallHandlerTest, Success) {
+  Init();
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
+
+  base::RunLoop run_loop;
+  bool status;
+  UninstallESim(run_loop, kTestCarrierProfilePath, status);
+  HandleNetworkDisconnect(/*should_fail=*/false);
+  run_loop.Run();
+
+  // Verify that the esim profile and shill service configuration are removed
+  // properly.
+  HermesEuiccClient::Properties* euicc_properties =
+      HermesEuiccClient::Get()->GetProperties(
+          dbus::ObjectPath(kDefaultEuiccPath));
+  ASSERT_TRUE(euicc_properties);
+  EXPECT_EQ(1u, euicc_properties->installed_carrier_profiles().value().size());
+  EXPECT_FALSE(ESimServiceConfigExists(kTestNetworkServicePath));
+  EXPECT_TRUE(status);
+}
+
+TEST_F(CellularESimUninstallHandlerTest, Success_AlreadyDisabled) {
+  Init(/*is_first_profile_active=*/false);
+  EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
+
   base::RunLoop run_loop;
   bool status;
   UninstallESim(run_loop, kTestCarrierProfilePath, status);
@@ -207,7 +232,9 @@
 }
 
 TEST_F(CellularESimUninstallHandlerTest, DisconnectFailure) {
+  Init();
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
+
   bool status;
   base::RunLoop run_loop;
   UninstallESim(run_loop, kTestCarrierProfilePath, status);
@@ -218,7 +245,9 @@
 }
 
 TEST_F(CellularESimUninstallHandlerTest, HermesFailure) {
+  Init();
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
+
   HermesEuiccClient::Get()->GetTestInterface()->QueueHermesErrorStatus(
       HermesResponseStatus::kErrorUnknown);
   bool status;
@@ -231,6 +260,7 @@
 }
 
 TEST_F(CellularESimUninstallHandlerTest, MultipleRequests) {
+  Init();
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath2));
 
@@ -260,6 +290,8 @@
 }
 
 TEST_F(CellularESimUninstallHandlerTest, StubCellularNetwork) {
+  Init();
+
   // Remove shill eSIM service and add a corresponding stub service.
   ShillServiceClient::Get()->GetTestInterface()->RemoveService(
       kTestNetworkServicePath);
@@ -275,6 +307,7 @@
 }
 
 TEST_F(CellularESimUninstallHandlerTest, RemovesShillOnlyServices) {
+  Init();
   EXPECT_TRUE(ESimServiceConfigExists(kTestNetworkServicePath));
 
   // Remove profile without removing service.
diff --git a/chromeos/services/cellular_setup/BUILD.gn b/chromeos/services/cellular_setup/BUILD.gn
index bf7ce6d9..d9a3fb9f 100644
--- a/chromeos/services/cellular_setup/BUILD.gn
+++ b/chromeos/services/cellular_setup/BUILD.gn
@@ -47,6 +47,7 @@
     "//chromeos/services/cellular_setup/public/mojom",
     "//components/device_event_log",
     "//components/qr_code_generator",
+    "//components/user_manager",
     "//dbus",
   ]
 }
@@ -113,6 +114,7 @@
     "//chromeos/dbus/shill",
     "//chromeos/network:test_support",
     "//chromeos/services/cellular_setup/public/cpp:test_support",
+    "//components/user_manager:test_support",
     "//dbus",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/chromeos/services/cellular_setup/DEPS b/chromeos/services/cellular_setup/DEPS
index 12c8534..82f84ccb 100644
--- a/chromeos/services/cellular_setup/DEPS
+++ b/chromeos/services/cellular_setup/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+dbus/object_path.h",
   "+components/qr_code_generator/qr_code_generator.h",
+  "+components/user_manager",
   "+mojo/public",
 ]
diff --git a/chromeos/services/cellular_setup/esim_profile.cc b/chromeos/services/cellular_setup/esim_profile.cc
index 5d4d182..72aedec 100644
--- a/chromeos/services/cellular_setup/esim_profile.cc
+++ b/chromeos/services/cellular_setup/esim_profile.cc
@@ -25,6 +25,7 @@
 #include "chromeos/services/cellular_setup/public/mojom/esim_manager.mojom-shared.h"
 #include "chromeos/services/cellular_setup/public/mojom/esim_manager.mojom.h"
 #include "components/device_event_log/device_event_log.h"
+#include "components/user_manager/user_manager.h"
 #include "dbus/object_path.h"
 
 namespace chromeos {
@@ -32,6 +33,11 @@
 
 namespace {
 
+bool IsGuestModeActive() {
+  return user_manager::UserManager::Get()->IsLoggedInAsGuest() ||
+         user_manager::UserManager::Get()->IsLoggedInAsPublicAccount();
+}
+
 bool IsESimProfilePropertiesEqualToState(
     const mojom::ESimProfilePropertiesPtr& properties,
     const CellularESimProfile& esim_profile_state) {
@@ -118,6 +124,12 @@
 }
 
 void ESimProfile::UninstallProfile(UninstallProfileCallback callback) {
+  if (IsGuestModeActive()) {
+    NET_LOG(ERROR) << "Cannot uninstall profile in guest mode.";
+    std::move(callback).Run(mojom::ESimOperationResult::kFailure);
+    return;
+  }
+
   if (!IsProfileInstalled()) {
     NET_LOG(ERROR) << "Profile uninstall failed: Profile is not installed.";
     std::move(callback).Run(mojom::ESimOperationResult::kFailure);
@@ -175,6 +187,12 @@
 
 void ESimProfile::SetProfileNickname(const std::u16string& nickname,
                                      SetProfileNicknameCallback callback) {
+  if (IsGuestModeActive()) {
+    NET_LOG(ERROR) << "Cannot rename profile in guest mode.";
+    std::move(callback).Run(mojom::ESimOperationResult::kFailure);
+    return;
+  }
+
   if (set_profile_nickname_callback_) {
     NET_LOG(ERROR) << "Set Profile Nickname already in progress.";
     std::move(callback).Run(mojom::ESimOperationResult::kFailure);
diff --git a/chromeos/services/cellular_setup/esim_profile_unittest.cc b/chromeos/services/cellular_setup/esim_profile_unittest.cc
index ec8c2656..dc20b0ac 100644
--- a/chromeos/services/cellular_setup/esim_profile_unittest.cc
+++ b/chromeos/services/cellular_setup/esim_profile_unittest.cc
@@ -13,6 +13,7 @@
 #include "chromeos/services/cellular_setup/esim_test_base.h"
 #include "chromeos/services/cellular_setup/esim_test_utils.h"
 #include "chromeos/services/cellular_setup/public/mojom/esim_manager.mojom-shared.h"
+#include "components/user_manager/fake_user_manager.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
@@ -29,6 +30,20 @@
 const char kPendingProfileInstallHistogram[] =
     "Network.Cellular.ESim.InstallPendingProfile.Result";
 
+class TestUserManager : public user_manager::FakeUserManager {
+ public:
+  TestUserManager(bool is_guest) : is_guest_(is_guest) {
+    user_manager::UserManager::SetInstance(this);
+  }
+  ~TestUserManager() override = default;
+
+  // user_manager::UserManager:
+  bool IsLoggedInAsGuest() const override { return is_guest_; }
+
+ private:
+  const bool is_guest_;
+};
+
 mojom::ESimOperationResult UninstallProfile(
     const mojo::Remote<mojom::ESimProfile>& esim_profile) {
   mojom::ESimOperationResult uninstall_result;
@@ -117,6 +132,10 @@
         /*connected_after_enable=*/false);
   }
 
+  void SetIsGuest(bool is_guest) {
+    test_user_manager_ = std::make_unique<TestUserManager>(is_guest);
+  }
+
   mojo::Remote<mojom::ESimProfile> GetESimProfileForIccid(
       const std::string& eid,
       const std::string& iccid) {
@@ -172,9 +191,14 @@
     run_loop.Run();
     return out_install_result;
   }
+
+ private:
+  std::unique_ptr<TestUserManager> test_user_manager_;
 };
 
 TEST_F(ESimProfileTest, GetProperties) {
+  SetIsGuest(false);
+
   HermesEuiccClient::TestInterface* euicc_test =
       HermesEuiccClient::Get()->GetTestInterface();
   dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
@@ -195,6 +219,7 @@
 }
 
 TEST_F(ESimProfileTest, InstallProfile) {
+  SetIsGuest(false);
   base::HistogramTester histogram_tester;
 
   HermesEuiccClient::TestInterface* euicc_test =
@@ -245,6 +270,8 @@
 }
 
 TEST_F(ESimProfileTest, InstallProfileAlreadyConnected) {
+  SetIsGuest(false);
+
   dbus::ObjectPath profile_path =
       HermesEuiccClient::Get()->GetTestInterface()->AddFakeCarrierProfile(
           dbus::ObjectPath(ESimTestBase::kTestEuiccPath),
@@ -266,6 +293,8 @@
 }
 
 TEST_F(ESimProfileTest, InstallConnectFailure) {
+  SetIsGuest(false);
+
   HermesEuiccClient::TestInterface* euicc_test =
       HermesEuiccClient::Get()->GetTestInterface();
   dbus::ObjectPath profile_path = euicc_test->AddFakeCarrierProfile(
@@ -287,6 +316,8 @@
 }
 
 TEST_F(ESimProfileTest, UninstallProfile) {
+  SetIsGuest(false);
+
   base::HistogramTester histogram_tester;
 
   HermesEuiccClient::TestInterface* euicc_test =
@@ -348,6 +379,25 @@
                                      true, 1);
 }
 
+TEST_F(ESimProfileTest, CannotUninstallProfileAsGuest) {
+  SetIsGuest(true);
+
+  HermesEuiccClient::TestInterface* euicc_test =
+      HermesEuiccClient::Get()->GetTestInterface();
+  dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
+      dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
+      HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
+          kAddProfileWithService);
+  HermesProfileClient::Properties* active_profile_dbus_properties =
+      HermesProfileClient::Get()->GetProperties(active_profile_path);
+  mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
+      ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
+
+  mojom::ESimOperationResult result = UninstallProfile(active_esim_profile);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
+}
+
 TEST_F(ESimProfileTest, EnableProfile) {
   HermesEuiccClient::TestInterface* euicc_test =
       HermesEuiccClient::Get()->GetTestInterface();
@@ -395,6 +445,8 @@
 }
 
 TEST_F(ESimProfileTest, DisableProfile) {
+  SetIsGuest(false);
+
   HermesEuiccClient::TestInterface* euicc_test =
       HermesEuiccClient::Get()->GetTestInterface();
   dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
@@ -440,6 +492,8 @@
 }
 
 TEST_F(ESimProfileTest, SetProfileNickName) {
+  SetIsGuest(false);
+
   const std::u16string test_nickname = u"Test nickname";
   base::HistogramTester histogram_tester;
 
@@ -488,5 +542,25 @@
   EXPECT_EQ(test_nickname, active_profile_mojo_properties->nickname);
 }
 
+TEST_F(ESimProfileTest, CannotSetProfileNickNameAsGuest) {
+  SetIsGuest(true);
+
+  HermesEuiccClient::TestInterface* euicc_test =
+      HermesEuiccClient::Get()->GetTestInterface();
+  dbus::ObjectPath active_profile_path = euicc_test->AddFakeCarrierProfile(
+      dbus::ObjectPath(kTestEuiccPath), hermes::profile::State::kActive, "",
+      HermesEuiccClient::TestInterface::AddCarrierProfileBehavior::
+          kAddProfileWithService);
+  HermesProfileClient::Properties* active_profile_dbus_properties =
+      HermesProfileClient::Get()->GetProperties(active_profile_path);
+  mojo::Remote<mojom::ESimProfile> active_esim_profile = GetESimProfileForIccid(
+      ESimTestBase::kTestEid, active_profile_dbus_properties->iccid().value());
+
+  mojom::ESimOperationResult result =
+      SetProfileNickname(active_esim_profile, u"Nickname");
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(mojom::ESimOperationResult::kFailure, result);
+}
+
 }  // namespace cellular_setup
 }  // namespace chromeos
diff --git a/components/messages/android/messages_feature.cc b/components/messages/android/messages_feature.cc
index f1ffb9f..8c41e951 100644
--- a/components/messages/android/messages_feature.cc
+++ b/components/messages/android/messages_feature.cc
@@ -30,7 +30,7 @@
 
 bool IsSafetyTipMessagesUiEnabled() {
   return base::FeatureList::IsEnabled(kMessagesForAndroidInfrastructure) &&
-         base::FeatureList::IsEnabled(kMessagesForAndroidPopupBlocked);
+         base::FeatureList::IsEnabled(kMessagesForAndroidSafetyTip);
 }
 
 }  // namespace messages
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn
index 44a59ca..7639bb1 100644
--- a/components/permissions/BUILD.gn
+++ b/components/permissions/BUILD.gn
@@ -21,8 +21,6 @@
     "contexts/clipboard_read_write_permission_context.h",
     "contexts/clipboard_sanitized_write_permission_context.cc",
     "contexts/clipboard_sanitized_write_permission_context.h",
-    "contexts/file_handling_permission_context.cc",
-    "contexts/file_handling_permission_context.h",
     "contexts/font_access_permission_context.cc",
     "contexts/font_access_permission_context.h",
     "contexts/geolocation_permission_context.cc",
diff --git a/components/permissions/contexts/file_handling_permission_context.cc b/components/permissions/contexts/file_handling_permission_context.cc
deleted file mode 100644
index c1f7d2b..0000000
--- a/components/permissions/contexts/file_handling_permission_context.cc
+++ /dev/null
@@ -1,21 +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.
-
-#include "components/permissions/contexts/file_handling_permission_context.h"
-
-#include "components/content_settings/core/common/content_settings_types.h"
-#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
-
-FileHandlingPermissionContext::FileHandlingPermissionContext(
-    content::BrowserContext* browser_context)
-    : PermissionContextBase(browser_context,
-                            ContentSettingsType::FILE_HANDLING,
-                            blink::mojom::PermissionsPolicyFeature::kNotFound) {
-}
-
-FileHandlingPermissionContext::~FileHandlingPermissionContext() = default;
-
-bool FileHandlingPermissionContext::IsRestrictedToSecureOrigins() const {
-  return true;
-}
diff --git a/components/permissions/contexts/file_handling_permission_context.h b/components/permissions/contexts/file_handling_permission_context.h
deleted file mode 100644
index 16442e7..0000000
--- a/components/permissions/contexts/file_handling_permission_context.h
+++ /dev/null
@@ -1,26 +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.
-
-#ifndef COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
-#define COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
-
-#include "components/permissions/permission_context_base.h"
-
-class FileHandlingPermissionContext
-    : public permissions::PermissionContextBase {
- public:
-  explicit FileHandlingPermissionContext(
-      content::BrowserContext* browser_context);
-  ~FileHandlingPermissionContext() override;
-
-  FileHandlingPermissionContext(const FileHandlingPermissionContext&) = delete;
-  FileHandlingPermissionContext& operator=(
-      const FileHandlingPermissionContext&) = delete;
-
- protected:
-  // PermissionContextBase:
-  bool IsRestrictedToSecureOrigins() const override;
-};
-
-#endif  // COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
diff --git a/components/permissions/permission_context_base.cc b/components/permissions/permission_context_base.cc
index 2d8b6a5..d98bac3 100644
--- a/components/permissions/permission_context_base.cc
+++ b/components/permissions/permission_context_base.cc
@@ -219,6 +219,20 @@
     const GURL& embedding_origin,
     ContentSetting content_setting) {}
 
+std::unique_ptr<PermissionRequest>
+PermissionContextBase::CreatePermissionRequest(
+    const GURL& request_origin,
+    ContentSettingsType content_settings_type,
+    bool has_gesture,
+    content::WebContents* web_contents,
+    PermissionRequestImpl::PermissionDecidedCallback
+        permission_decided_callback,
+    base::OnceClosure delete_callback) const {
+  return std::make_unique<PermissionRequestImpl>(
+      request_origin, content_settings_type, has_gesture,
+      std::move(permission_decided_callback), std::move(delete_callback));
+}
+
 PermissionResult PermissionContextBase::GetPermissionStatus(
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
@@ -373,14 +387,13 @@
   if (!permission_request_manager)
     return;
 
-  std::unique_ptr<PermissionRequest> request_ptr =
-      std::make_unique<PermissionRequestImpl>(
-          requesting_origin, content_settings_type_, user_gesture,
-          base::BindOnce(&PermissionContextBase::PermissionDecided,
-                         weak_factory_.GetWeakPtr(), id, requesting_origin,
-                         embedding_origin, std::move(callback)),
-          base::BindOnce(&PermissionContextBase::CleanUpRequest,
-                         weak_factory_.GetWeakPtr(), id));
+  std::unique_ptr<PermissionRequest> request_ptr = CreatePermissionRequest(
+      requesting_origin, content_settings_type_, user_gesture, web_contents,
+      base::BindOnce(&PermissionContextBase::PermissionDecided,
+                     weak_factory_.GetWeakPtr(), id, requesting_origin,
+                     embedding_origin, std::move(callback)),
+      base::BindOnce(&PermissionContextBase::CleanUpRequest,
+                     weak_factory_.GetWeakPtr(), id));
   PermissionRequest* request = request_ptr.get();
 
   bool inserted =
diff --git a/components/permissions/permission_context_base.h b/components/permissions/permission_context_base.h
index d310912..93b981d 100644
--- a/components/permissions/permission_context_base.h
+++ b/components/permissions/permission_context_base.h
@@ -17,6 +17,7 @@
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/permissions/permission_request.h"
+#include "components/permissions/permission_request_impl.h"
 #include "components/permissions/permission_result.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"
 
@@ -183,6 +184,17 @@
                                const ContentSettingsPattern& secondary_pattern,
                                ContentSettingsType content_type) override;
 
+  // Implementors can override this method to use a different PermissionRequest
+  // implementation.
+  virtual std::unique_ptr<PermissionRequest> CreatePermissionRequest(
+      const GURL& request_origin,
+      ContentSettingsType content_settings_type,
+      bool has_gesture,
+      content::WebContents* web_contents,
+      PermissionRequestImpl::PermissionDecidedCallback
+          permission_decided_callback,
+      base::OnceClosure delete_callback) const;
+
   ContentSettingsType content_settings_type() const {
     return content_settings_type_;
   }
diff --git a/components/permissions/permission_request_impl.cc b/components/permissions/permission_request_impl.cc
index 918449e..843d291 100644
--- a/components/permissions/permission_request_impl.cc
+++ b/components/permissions/permission_request_impl.cc
@@ -186,9 +186,6 @@
     case ContentSettingsType::IDLE_DETECTION:
       message_id = IDS_IDLE_DETECTION_PERMISSION_FRAGMENT;
       break;
-    case ContentSettingsType::FILE_HANDLING:
-      message_id = IDS_FILE_HANDLING_PERMISSION_FRAGMENT;
-      break;
     default:
       NOTREACHED();
       return std::u16string();
diff --git a/components/permissions/permission_request_impl.h b/components/permissions/permission_request_impl.h
index 2195d6f..8f8645c 100644
--- a/components/permissions/permission_request_impl.h
+++ b/components/permissions/permission_request_impl.h
@@ -35,14 +35,18 @@
 
   ~PermissionRequestImpl() override;
 
+// PermissionRequest:
+#if !defined(OS_ANDROID)
+  // Implementors can override this method to customize the message text.
+  std::u16string GetMessageTextFragment() const override;
+#endif
+
  private:
-  // PermissionRequest:
   RequestType GetRequestType() const override;
 #if defined(OS_ANDROID)
   std::u16string GetMessageText() const override;
 #else
   base::Optional<std::u16string> GetChipText() const override;
-  std::u16string GetMessageTextFragment() const override;
 #endif
   GURL GetOrigin() const override;
   void PermissionGranted(bool is_one_time) override;
diff --git a/components/permissions_strings.grdp b/components/permissions_strings.grdp
index c3d43fe4..847c24e0 100644
--- a/components/permissions_strings.grdp
+++ b/components/permissions_strings.grdp
@@ -140,10 +140,6 @@
   <message name="IDS_PERMISSIONS_BUBBLE_PROMPT_ONE_TIME" desc="The label that is used to introduce permission request details to the user in a popup.">
     Allow <ph name="SITE_NAME">$1<ex>google.com</ex></ph> to:
   </message>
-  <message name="IDS_FILE_HANDLING_PERMISSION_FRAGMENT" desc="Permission request shown if the user is opening a file using a PWA with a registered file handler. Follows a prompt: 'This site would like to:'">
-    Open files with file type associations.
-  </message>
-
   <if expr="not is_android">
     <message name="IDS_GEOLOCATION_PERMISSION_CHIP" desc="Button text representing a request for the user's physical location from a website. When clicked, shows a permission prompt bubble with more information.">
       Use your location?
diff --git a/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1 b/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1
deleted file mode 100644
index 72ab8b2..0000000
--- a/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-55ddb345d69ee2187e402f22579fc4459b9563d1
\ No newline at end of file
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 13894415..cbf43c3 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -25687,6 +25687,12 @@
           'name': '554',
           'value': '554',
           'caption': '''port 554 (expires 2021/10/15)''',
+          'supported_on': [
+            'chrome.*:91-95',
+            'android:91-95',
+            'chrome_os:91-95',
+            'webview_android:91-95'
+          ],
         },
         {
           'name': '10080',
diff --git a/components/services/app_service/public/cpp/app_update.cc b/components/services/app_service/public/cpp/app_update.cc
index a7f324a..377f3bc 100644
--- a/components/services/app_service/public/cpp/app_update.cc
+++ b/components/services/app_service/public/cpp/app_update.cc
@@ -131,6 +131,9 @@
   if (delta->resize_locked != apps::mojom::OptionalBool::kUnknown) {
     state->resize_locked = delta->resize_locked;
   }
+  if (delta->preferred_app != apps::mojom::OptionalBool::kUnknown) {
+    state->preferred_app = delta->preferred_app;
+  }
 
   // When adding new fields to the App Mojo type, this function should also be
   // updated.
@@ -542,6 +545,22 @@
          (!state_ || (delta_->resize_locked != state_->resize_locked));
 }
 
+apps::mojom::OptionalBool AppUpdate::PreferredApp() const {
+  if (delta_ &&
+      (delta_->preferred_app != apps::mojom::OptionalBool::kUnknown)) {
+    return delta_->preferred_app;
+  }
+  if (state_)
+    return state_->preferred_app;
+  return apps::mojom::OptionalBool::kUnknown;
+}
+
+bool AppUpdate::PreferredAppChanged() const {
+  return delta_ &&
+         (delta_->preferred_app != apps::mojom::OptionalBool::kUnknown) &&
+         (!state_ || (delta_->preferred_app != state_->preferred_app));
+}
+
 const ::AccountId& AppUpdate::AccountId() const {
   return account_id_;
 }
diff --git a/components/services/app_service/public/cpp/app_update.h b/components/services/app_service/public/cpp/app_update.h
index 1699333b..cca4bde 100644
--- a/components/services/app_service/public/cpp/app_update.h
+++ b/components/services/app_service/public/cpp/app_update.h
@@ -136,6 +136,9 @@
   apps::mojom::OptionalBool ResizeLocked() const;
   bool ResizeLockedChanged() const;
 
+  apps::mojom::OptionalBool PreferredApp() const;
+  bool PreferredAppChanged() const;
+
   const ::AccountId& AccountId() const;
 
  private:
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
index 75a1af44..dbf521f 100644
--- a/components/services/app_service/public/mojom/types.mojom
+++ b/components/services/app_service/public/mojom/types.mojom
@@ -72,6 +72,9 @@
   // operations will be restricted.
   OptionalBool resize_locked;
 
+  // If true, this app is used as a preferred app for its given intent filters.
+  OptionalBool preferred_app;
+
   // When adding new fields, also update the Merge method and other helpers in
   // components/services/app_service/public/cpp/app_update.*
 };
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 0b3e92c..4b17a01 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -93,7 +93,7 @@
 #if defined(OS_FUCHSIA)
 // Enables SkiaOutputDeviceBufferQueue instead of Vulkan swapchain on Fuchsia.
 const base::Feature kUseSkiaOutputDeviceBufferQueue{
-    "UseSkiaOutputDeviceBufferQueue", base::FEATURE_DISABLED_BY_DEFAULT};
+    "UseSkiaOutputDeviceBufferQueue", base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 // Whether we should log extra debug information to webrtc native log.
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index 0483c1ba..01ad946 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -1196,8 +1196,7 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   auto* root_manager = GetRootBrowserAccessibilityManager();
-  if (!root_manager ||
-      !base::FeatureList::IsEnabled(features::kAndroidAutofillAccessibility))
+  if (!root_manager)
     return;
 
   BrowserAccessibility* current_focus = root_manager->GetFocus();
@@ -1236,8 +1235,7 @@
     GetIdForElementAfterElementHostingAutofillPopup(
         JNIEnv* env,
         const JavaParamRef<jobject>& obj) {
-  if (!base::FeatureList::IsEnabled(features::kAndroidAutofillAccessibility) ||
-      g_element_after_element_hosting_autofill_popup_unique_id == -1 ||
+  if (g_element_after_element_hosting_autofill_popup_unique_id == -1 ||
       GetAXFromUniqueID(
           g_element_after_element_hosting_autofill_popup_unique_id) == nullptr)
     return 0;
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 8f06f62e..99062a8 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -10671,21 +10671,16 @@
   }
 };
 
-// TODO(crbug.com/1204058): This test is flaky.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheOptInBrowserTest,
-                       DISABLED_NoCacheWithoutHeader) {
+IN_PROC_BROWSER_TEST_F(BackForwardCacheOptInBrowserTest, NoCacheWithoutHeader) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
 
   // 1) Navigate to A.
   EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
 
   // 2) Navigate to B.
   EXPECT_TRUE(NavigateToURL(shell(), url_b));
-  EXPECT_TRUE(delete_observer_rfh_a.deleted());
 
   // 3) Go back.
   web_contents()->GetController().GoBack();
@@ -10722,13 +10717,9 @@
   response.Send(kResponseWithOptIn);
   response.Done();
   observer.Wait();
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
 
   // 2) Navigate to B.
   EXPECT_TRUE(NavigateToURL(shell(), url_b));
-  ASSERT_FALSE(delete_observer_rfh_a.deleted());
-  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
 
   // 3) Go back.
   web_contents()->GetController().GoBack();
@@ -10737,9 +10728,8 @@
   ExpectRestored(FROM_HERE);
 }
 
-// TODO(crbug.com/1204027): This test is flaky.
 IN_PROC_BROWSER_TEST_F(BackForwardCacheOptInBrowserTest,
-                       DISABLED_NoCacheIfHeaderOnlyPresentOnDestinationPage) {
+                       NoCacheIfHeaderOnlyPresentOnDestinationPage) {
   net::test_server::ControllableHttpResponse response(embedded_test_server(),
                                                       "/opt_in_document");
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -10749,8 +10739,6 @@
 
   // 1) Navigate to A.
   EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
 
   // 2) Navigate to B.
   TestNavigationObserver observer(web_contents());
@@ -10759,7 +10747,6 @@
   response.Send(kResponseWithOptIn);
   response.Done();
   observer.Wait();
-  EXPECT_TRUE(delete_observer_rfh_a.deleted());
 
   // 3) Go back. - A doesn't have header so it shouldn't be cached.
   web_contents()->GetController().GoBack();
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 1a13fce..1659946 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -900,7 +900,7 @@
       base::BindRepeating(&KeyboardLockServiceImpl::CreateMojoService));
   map->Add<blink::mojom::FlocService>(
       base::BindRepeating(&FlocServiceImpl::CreateMojoService));
-  if (base::FeatureList::IsEnabled(features::kFledgeInterestGroups)) {
+  if (base::FeatureList::IsEnabled(blink::features::kFledgeInterestGroups)) {
     map->Add<blink::mojom::AdAuctionService>(
         base::BindRepeating(&AdAuctionServiceImpl::CreateMojoService));
     map->Add<blink::mojom::RestrictedInterestGroupStore>(
diff --git a/content/browser/interest_group/ad_auction_service_impl.cc b/content/browser/interest_group/ad_auction_service_impl.cc
index 09bfe18..dcdf7da 100644
--- a/content/browser/interest_group/ad_auction_service_impl.cc
+++ b/content/browser/interest_group/ad_auction_service_impl.cc
@@ -281,7 +281,9 @@
   auto url_loader_factory_proxy =
       std::make_unique<AuctionURLLoaderFactoryProxy>(
           url_loader_factory.InitWithNewPipeAndPassReceiver(),
-          base::BindRepeating(&AdAuctionServiceImpl::GetURLLoaderFactory,
+          base::BindRepeating(&AdAuctionServiceImpl::GetFrameURLLoaderFactory,
+                              base::Unretained(this)),
+          base::BindRepeating(&AdAuctionServiceImpl::GetTrustedURLLoaderFactory,
                               base::Unretained(this)),
           browser_signals->top_frame_origin, *config, bidders);
 
@@ -342,7 +344,7 @@
                                                       bidder->group->name);
   }
 
-  network::mojom::URLLoaderFactory* factory = GetURLLoaderFactory();
+  network::mojom::URLLoaderFactory* factory = GetTrustedURLLoaderFactory();
   if (bidder_report->report_requested && bidder_report->report_url.is_valid() &&
       bidder_report->report_url.SchemeIs(url::kHttpsScheme)) {
     FetchReport(factory, bidder_report->report_url, origin());
@@ -353,11 +355,23 @@
   }
 }
 
-network::mojom::URLLoaderFactory* AdAuctionServiceImpl::GetURLLoaderFactory() {
-  if (!url_loader_factory_ || !url_loader_factory_.is_connected()) {
-    url_loader_factory_.reset();
+network::mojom::URLLoaderFactory*
+AdAuctionServiceImpl::GetFrameURLLoaderFactory() {
+  if (!frame_url_loader_factory_ || !frame_url_loader_factory_.is_connected()) {
+    frame_url_loader_factory_.reset();
+    render_frame_host()->CreateNetworkServiceDefaultFactory(
+        frame_url_loader_factory_.BindNewPipeAndPassReceiver());
+  }
+  return frame_url_loader_factory_.get();
+}
+
+network::mojom::URLLoaderFactory*
+AdAuctionServiceImpl::GetTrustedURLLoaderFactory() {
+  if (!trusted_url_loader_factory_ ||
+      !trusted_url_loader_factory_.is_connected()) {
+    trusted_url_loader_factory_.reset();
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver =
-        url_loader_factory_.BindNewPipeAndPassReceiver();
+        trusted_url_loader_factory_.BindNewPipeAndPassReceiver();
 
     // TODO(mmenke): Should this have its own URLLoaderFactoryType? FLEDGE
     // requests are very different from subresource requests.
@@ -378,7 +392,7 @@
         ->GetURLLoaderFactoryForBrowserProcess()
         ->Clone(std::move(factory_receiver));
   }
-  return url_loader_factory_.get();
+  return trusted_url_loader_factory_.get();
 }
 
 void AdAuctionServiceImpl::AuctionComplete() {
diff --git a/content/browser/interest_group/ad_auction_service_impl.h b/content/browser/interest_group/ad_auction_service_impl.h
index 139a4ee..2bf799c 100644
--- a/content/browser/interest_group/ad_auction_service_impl.h
+++ b/content/browser/interest_group/ad_auction_service_impl.h
@@ -96,9 +96,16 @@
       auction_worklet::mojom::WinningBidderReportPtr bidder_report,
       auction_worklet::mojom::SellerReportPtr seller_report);
 
-  // Populates `url_loader_factory_` if it's either null or the pipe has been
-  // closed. Returns the resulting factory.
-  network::mojom::URLLoaderFactory* GetURLLoaderFactory();
+  // Returns an untrusted URLLoaderFactory created by the RenderFrameHost,
+  // suitable for loading URLs like subresources. Caches the factory in
+  // `frame_url_loader_factory_` for reuse.
+  network::mojom::URLLoaderFactory* GetFrameURLLoaderFactory();
+
+  // Returns a trusted URLLoaderFactory. Consumers should set
+  // ResourceRequest::TrustedParams to specify a NetworkIsolationKey when using
+  // the returned factory. Caches the factory in `trusted_url_loader_factory_`
+  // for reuse.
+  network::mojom::URLLoaderFactory* GetTrustedURLLoaderFactory();
 
   // Decrements number of running auctions and shuts down the worklet process
   // if needed.
@@ -112,7 +119,8 @@
   mojo::Remote<auction_worklet::mojom::AuctionWorkletService>
       auction_worklet_service_;
 
-  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_;
+  mojo::Remote<network::mojom::URLLoaderFactory> frame_url_loader_factory_;
+  mojo::Remote<network::mojom::URLLoaderFactory> trusted_url_loader_factory_;
 
   base::WeakPtrFactory<AdAuctionServiceImpl> weak_ptr_factory_{this};
 };
diff --git a/content/browser/interest_group/auction_url_loader_factory_proxy.cc b/content/browser/interest_group/auction_url_loader_factory_proxy.cc
index 36d21800..0dd1150e 100644
--- a/content/browser/interest_group/auction_url_loader_factory_proxy.cc
+++ b/content/browser/interest_group/auction_url_loader_factory_proxy.cc
@@ -34,21 +34,24 @@
 
 AuctionURLLoaderFactoryProxy::AuctionURLLoaderFactoryProxy(
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver,
-    GetUrlLoaderFactoryCallback get_url_loader_factory_callback,
+    GetUrlLoaderFactoryCallback get_publisher_frame_url_loader_factory,
+    GetUrlLoaderFactoryCallback get_trusted_url_loader_factory,
     const url::Origin& frame_origin,
     const blink::mojom::AuctionAdConfig& auction_config,
     const std::vector<auction_worklet::mojom::BiddingInterestGroupPtr>& bidders)
     : receiver_(this, std::move(pending_receiver)),
-      get_url_loader_factory_callback_(
-          std::move(get_url_loader_factory_callback)),
+      get_publisher_frame_url_loader_factory_(
+          std::move(get_publisher_frame_url_loader_factory)),
+      get_trusted_url_loader_factory_(
+          std::move(get_trusted_url_loader_factory)),
       frame_origin_(frame_origin),
       expected_query_prefix_(
           "hostname=" + net::EscapeQueryParamValue(frame_origin.host(), true) +
           "&keys=") {
-  script_urls_.insert(auction_config.decision_logic_url);
+  decision_logic_url_ = auction_config.decision_logic_url;
   for (const auto& bidder : bidders) {
     if (bidder->group->bidding_url)
-      script_urls_.insert(*bidder->group->bidding_url);
+      bidding_urls_.insert(*bidder->group->bidding_url);
     if (bidder->group->trusted_bidding_signals_url) {
       // Base trusted bidding signals URLs can't have query strings, since
       // running an auction will create URLs by adding query strings to them.
@@ -76,9 +79,21 @@
     return;
   }
 
+  // True if the more restricted publisher RenderFrameHost's URLLoader should be
+  // used to load a resource. False if the global factory should be used
+  // instead, setting the ResourceRequest::TrustedParams field to use the
+  // correct network shard.
+  bool use_publisher_frame_loader = true;
+
   if (accept_header == "application/javascript") {
-    // Only `script_urls_` may be requested with the Javascript Accept header.
-    if (script_urls_.find(url_request.url) == script_urls_.end()) {
+    // Only script_urls may be requested with the Javascript Accept header.
+    if (url_request.url == decision_logic_url_) {
+      // Nothing more to do.
+    } else if (bidding_urls_.find(url_request.url) != bidding_urls_.end()) {
+      // This is safe, because `bidding_urls_` can only be registered by
+      // calling `joinAdInterestGroup` from the URL's origin.
+      use_publisher_frame_loader = false;
+    } else {
       receiver_.ReportBadMessage("Unexpected Javascript request url");
       return;
     }
@@ -109,6 +124,9 @@
           "JSON query string has unexpected additional parameter");
       return;
     }
+    // This is safe, because `realtime_data_urls_` can only be registered by
+    // calling `joinAdInterestGroup` from the URL's origin.
+    use_publisher_frame_loader = false;
   } else {
     receiver_.ReportBadMessage("Accept header has unexpected value");
     return;
@@ -127,24 +145,33 @@
   new_request.credentials_mode = network::mojom::CredentialsMode::kOmit;
   new_request.request_initiator = frame_origin_;
 
-  // Treat this as a subresource request from the owner's origin.
-  //
-  // TODO(mmenke): This leaks information to the third party that made the
-  // request (both the URL itself leaks information, and using the origin's NIK
-  // leaks information). These leaks need to be fixed.
-  new_request.trusted_params = network::ResourceRequest::TrustedParams();
-  url::Origin origin = url::Origin::Create(url_request.url);
-  new_request.trusted_params->isolation_info =
-      net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
-                                 origin, origin, net::SiteForCookies());
+  network::mojom::URLLoaderFactory* url_loader_factory = nullptr;
+  if (use_publisher_frame_loader) {
+    url_loader_factory = get_publisher_frame_url_loader_factory_.Run();
+    new_request.mode = network::mojom::RequestMode::kCors;
+  } else {
+    // Treat this as a subresource request from the owner's origin, using the
+    // trusted URLLoaderFactory.
+    //
+    // TODO(mmenke): This leaks information to the third party that made the
+    // request (both the URL itself leaks information, and using the origin's
+    // NIK leaks information). These leaks need to be fixed.
+    url_loader_factory = get_trusted_url_loader_factory_.Run();
+    new_request.mode = network::mojom::RequestMode::kNoCors;
+    new_request.trusted_params = network::ResourceRequest::TrustedParams();
+    url::Origin origin = url::Origin::Create(url_request.url);
+    new_request.trusted_params->isolation_info =
+        net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
+                                   origin, origin, net::SiteForCookies());
+
+    // TODO(mmenke): Investigate whether `client_security_state` should be
+    // populated.
+  }
 
   // TODO(mmenke): Investigate whether `devtools_observer` or
   // `report_raw_headers` should be set when devtools is open.
 
-  // TODO(mmenke): Investigate whether `client_security_state` should be
-  // populated.
-
-  get_url_loader_factory_callback_.Run()->CreateLoaderAndStart(
+  url_loader_factory->CreateLoaderAndStart(
       std::move(receiver),
       // These are browser-initiated requests, so give them a browser request
       // ID. Extension APIs may expect these to be unique.
diff --git a/content/browser/interest_group/auction_url_loader_factory_proxy.h b/content/browser/interest_group/auction_url_loader_factory_proxy.h
index cc7cbcda..b5ee615b 100644
--- a/content/browser/interest_group/auction_url_loader_factory_proxy.h
+++ b/content/browser/interest_group/auction_url_loader_factory_proxy.h
@@ -32,14 +32,35 @@
   using GetUrlLoaderFactoryCallback =
       base::RepeatingCallback<network::mojom::URLLoaderFactory*()>;
 
-  // `get_url_loader_factory_callback` must be safe to call at any time during
-  // the lifetime of the AuctionURLLoaderFactoryProxy.
+  // Passed in callbacks must be safe to call at any time during the lifetime of
+  // the AuctionURLLoaderFactoryProxy.
+  //
+  // `get_publisher_frame_url_loader_factory` returns a URLLoaderFactory
+  // configured to behave like the URLLoaderFactory in use by the frame running
+  // the auction. It uses the same network partition, request initiator lock
+  // etc. This is used to request resources specified by the publisher page
+  // (currently, just the the `decision_logic_url`). This is needed to protect
+  // against a V8 compromise being used to access arbitrary resources by setting
+  // the `decision_logic_url` to a target site. URLs associated with interest
+  // groups already have first-party opt in, so don't need this, but the seller
+  // URLs do not. If `decision_logic_url` matches any bidding script URL, the
+  // frame factory is used for all requests for that URL. Bidder JSON requests
+  // are distinguishable via their accept header, so always use the trusted
+  // factory.
+  //
+  // `get_trusted_url_loader_factory` returns a trusted URLLoaderFactory that
+  // can request arbitrary URLs. This is used to request interest groups with
+  // the appropriate network partition. Each interest group URL request needs to
+  // use the partition of the associated interest group to avoid leaking the
+  // fetched URLs to the publisher, since interest groups are roughly analogous
+  // to more restricted third party cookies.
   //
   // URLs that may be requested are extracted from `auction_config` and
   // `bidders`. Any other requested URL will result in failure.
   AuctionURLLoaderFactoryProxy(
       mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver,
-      GetUrlLoaderFactoryCallback get_url_loader_factory_callback,
+      GetUrlLoaderFactoryCallback get_publisher_frame_url_loader_factory,
+      GetUrlLoaderFactoryCallback get_trusted_url_loader_factory,
       const url::Origin& frame_origin,
       const blink::mojom::AuctionAdConfig& auction_config,
       const std::vector<auction_worklet::mojom::BiddingInterestGroupPtr>&
@@ -64,12 +85,19 @@
  private:
   mojo::Receiver<network::mojom::URLLoaderFactory> receiver_;
 
-  const GetUrlLoaderFactoryCallback get_url_loader_factory_callback_;
+  const GetUrlLoaderFactoryCallback get_publisher_frame_url_loader_factory_;
+  const GetUrlLoaderFactoryCallback get_trusted_url_loader_factory_;
 
   const url::Origin frame_origin_;
 
-  // URLs of worklet scripts. Requested URLs may match these URLs exactly.
-  std::set<GURL> script_urls_;
+  // URL of the seller script. Requested URLs may match these URLs exactly.
+  // Unlike `bidding_urls_`, requests for this URL must use the publisher
+  // frame's more restricted URLLoaderFactory. See constructor for more details.
+  GURL decision_logic_url_;
+
+  // URLs of worklet bidder scripts. Requested URLs may match these URLs
+  // exactly.
+  std::set<GURL> bidding_urls_;
 
   // URLs for real-time bidding data. Requests may match these with the query
   // parameter removed.
diff --git a/content/browser/interest_group/auction_url_loader_factory_proxy_unittest.cc b/content/browser/interest_group/auction_url_loader_factory_proxy_unittest.cc
index d3fc43f..2a33f9a 100644
--- a/content/browser/interest_group/auction_url_loader_factory_proxy_unittest.cc
+++ b/content/browser/interest_group/auction_url_loader_factory_proxy_unittest.cc
@@ -54,6 +54,13 @@
 
 class ActionUrlLoaderFactoryProxyTest : public testing::Test {
  public:
+  // Ways the proxy can behave in response to a request.
+  enum class ExpectedResponse {
+    kReject,
+    kUseFrameFactory,
+    kUseTrustedFactory,
+  };
+
   ActionUrlLoaderFactoryProxyTest() { CreateUrlLoaderFactoryProxy(); }
 
   ~ActionUrlLoaderFactoryProxyTest() override {
@@ -91,15 +98,24 @@
         remote_url_loader_factory_.BindNewPipeAndPassReceiver(),
         base::BindRepeating(
             [](network::mojom::URLLoaderFactory* factory) { return factory; },
-            &proxied_url_loader_factory_),
+            &proxied_frame_url_loader_factory_),
+        base::BindRepeating(
+            [](network::mojom::URLLoaderFactory* factory) { return factory; },
+            &proxied_trusted_url_loader_factory_),
         frame_origin_, *auction_config, bidders);
   }
 
-  // Attempts to make a request for `request`. Return true of the request is
-  // passed through AuctionURLLoaderFactoryProxy to the nested
-  // TestURLLoaderFactory.
-  bool TryMakeRequest(const network::ResourceRequest& request) {
-    int initial_num_requests = proxied_url_loader_factory_.NumPending();
+  // Attempts to make a request for `request`.
+  void TryMakeRequest(const network::ResourceRequest& request,
+                      ExpectedResponse expected_response) {
+    // Create a new factory if the last test case closed the pipe.
+    if (!remote_url_loader_factory_.is_connected())
+      CreateUrlLoaderFactoryProxy();
+
+    int initial_num_frame_requests =
+        proxied_frame_url_loader_factory_.NumPending();
+    int initial_num_trusted_requests =
+        proxied_trusted_url_loader_factory_.NumPending();
 
     // Try to send a request. Requests are never run to completion, instead,
     // requests that make it to the nested `url_loader_factory_` are tracked in
@@ -118,44 +134,60 @@
     // actually spinds the message loop already, but seems best to be safe.
     remote_url_loader_factory_.FlushForTesting();
 
-    // If there are just as many requests now as there were before a request was
-    // made, then the proxy blocked the request.
-    int final_num_requests = proxied_url_loader_factory_.NumPending();
-    bool request_rejected = initial_num_requests == final_num_requests;
-
-    // A request being rejected closes the receiver. Need to create a new
-    // AuctionURLLoaderFactoryProxy for next test.
-    EXPECT_EQ(request_rejected, !remote_url_loader_factory_.is_connected());
-    if (!remote_url_loader_factory_.is_connected())
-      CreateUrlLoaderFactoryProxy();
-
-    if (request_rejected)
-      return false;
-
-    // If there are more pending requests than before, there should only be one
-    // more pending request.
-    EXPECT_EQ(initial_num_requests + 1, final_num_requests);
-
-    const auto& pending_request =
-        proxied_url_loader_factory_.pending_requests()->back();
+    network::TestURLLoaderFactory::PendingRequest const* pending_request;
+    switch (expected_response) {
+      case ExpectedResponse::kReject:
+        // A request being rejected closes the receiver.
+        EXPECT_EQ(initial_num_frame_requests,
+                  proxied_frame_url_loader_factory_.NumPending());
+        EXPECT_EQ(initial_num_trusted_requests,
+                  proxied_trusted_url_loader_factory_.NumPending());
+        // Rejecting a request should result in closing the factory mojo pipe.
+        EXPECT_FALSE(remote_url_loader_factory_.is_connected());
+        return;
+      case ExpectedResponse::kUseFrameFactory:
+        ASSERT_EQ(initial_num_frame_requests + 1,
+                  proxied_frame_url_loader_factory_.NumPending());
+        ASSERT_EQ(initial_num_trusted_requests,
+                  proxied_trusted_url_loader_factory_.NumPending());
+        EXPECT_TRUE(remote_url_loader_factory_.is_connected());
+        pending_request =
+            &proxied_frame_url_loader_factory_.pending_requests()->back();
+        break;
+      case ExpectedResponse::kUseTrustedFactory:
+        ASSERT_EQ(initial_num_frame_requests,
+                  proxied_frame_url_loader_factory_.NumPending());
+        ASSERT_EQ(initial_num_trusted_requests + 1,
+                  proxied_trusted_url_loader_factory_.NumPending());
+        EXPECT_TRUE(remote_url_loader_factory_.is_connected());
+        pending_request =
+            &proxied_trusted_url_loader_factory_.pending_requests()->back();
+        break;
+    }
 
     // These should always be the same for all requests.
-    EXPECT_EQ(0u, pending_request.options);
+    EXPECT_EQ(0u, pending_request->options);
     EXPECT_EQ(
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
-        pending_request.traffic_annotation);
+        pending_request->traffic_annotation);
 
     // Each request should be assigned a unique ID. These should actually be
     // unique within the browser process, not just among requests using the
     // AuctionURLLoaderFactoryProxy.
     for (const auto& other_pending_request :
-         *proxied_url_loader_factory_.pending_requests()) {
-      if (&other_pending_request == &pending_request)
+         *proxied_frame_url_loader_factory_.pending_requests()) {
+      if (&other_pending_request == pending_request)
         continue;
-      EXPECT_NE(other_pending_request.request_id, pending_request.request_id);
+      EXPECT_NE(other_pending_request.request_id, pending_request->request_id);
+    }
+    for (const auto& other_pending_request :
+         *proxied_trusted_url_loader_factory_.pending_requests()) {
+      if (&other_pending_request == pending_request)
+        continue;
+      EXPECT_NE(other_pending_request.request_id, pending_request->request_id);
     }
 
-    const auto& observed_request = pending_request.request;
+    const auto& observed_request = pending_request->request;
 
     // The URL should be unaltered.
     EXPECT_EQ(request.url, observed_request.url);
@@ -181,11 +213,13 @@
     // The initiator should be set.
     EXPECT_EQ(frame_origin_, observed_request.request_initiator);
 
-    // Validate `observed_request.trusted_params`.
-    EXPECT_TRUE(observed_request.trusted_params);
-    if (observed_request.trusted_params) {
+    if (expected_response == ExpectedResponse::kUseFrameFactory) {
+      EXPECT_EQ(network::mojom::RequestMode::kCors, observed_request.mode);
+      EXPECT_FALSE(observed_request.trusted_params);
+    } else {
+      EXPECT_EQ(network::mojom::RequestMode::kNoCors, observed_request.mode);
+      ASSERT_TRUE(observed_request.trusted_params);
       EXPECT_FALSE(observed_request.trusted_params->disable_secure_dns);
-
       const auto& observed_isolation_info =
           observed_request.trusted_params->isolation_info;
       EXPECT_EQ(net::IsolationInfo::RequestType::kOther,
@@ -195,26 +229,26 @@
       EXPECT_EQ(expected_origin, observed_isolation_info.frame_origin());
       EXPECT_TRUE(observed_isolation_info.site_for_cookies().IsNull());
     }
-
-    return true;
   }
 
-  bool TryMakeRequest(const std::string& url,
-                      base::Optional<std::string> accept_value) {
+  void TryMakeRequest(const std::string& url,
+                      base::Optional<std::string> accept_value,
+                      ExpectedResponse expected_response) {
     network::ResourceRequest request;
     request.url = GURL(url);
     if (accept_value) {
       request.headers.SetHeader(net::HttpRequestHeaders::kAccept,
                                 *accept_value);
     }
-    return TryMakeRequest(request);
+    TryMakeRequest(request, expected_response);
   }
 
  protected:
   base::test::TaskEnvironment task_environment_;
 
   url::Origin frame_origin_ = url::Origin::Create(GURL("https://foo.test/"));
-  network::TestURLLoaderFactory proxied_url_loader_factory_;
+  network::TestURLLoaderFactory proxied_frame_url_loader_factory_;
+  network::TestURLLoaderFactory proxied_trusted_url_loader_factory_;
   std::unique_ptr<AuctionURLLoaderFactoryProxy> url_loader_factory_proxy_;
   mojo::Remote<network::mojom::URLLoaderFactory> remote_url_loader_factory_;
 };
@@ -222,27 +256,39 @@
 // Test exact URL matches. Trusted bidding signals URLs should be rejected
 // unless that have a valid query string appended.
 TEST_F(ActionUrlLoaderFactoryProxyTest, ExactURLMatch) {
-  EXPECT_TRUE(TryMakeRequest(kScoringWorkletUrl, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kScoringWorkletUrl, kAcceptJson));
-  EXPECT_FALSE(TryMakeRequest(kScoringWorkletUrl, "Unknown/Unknown"));
-  EXPECT_FALSE(TryMakeRequest(kScoringWorkletUrl, base::nullopt));
+  TryMakeRequest(kScoringWorkletUrl, kAcceptJavascript,
+                 ExpectedResponse::kUseFrameFactory);
+  TryMakeRequest(kScoringWorkletUrl, kAcceptJson, ExpectedResponse::kReject);
+  TryMakeRequest(kScoringWorkletUrl, "Unknown/Unknown",
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kScoringWorkletUrl, base::nullopt, ExpectedResponse::kReject);
 
-  EXPECT_TRUE(TryMakeRequest(kBiddingWorkletUrl1, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kBiddingWorkletUrl1, kAcceptJson));
-  EXPECT_FALSE(TryMakeRequest(kBiddingWorkletUrl1, "Unknown/Unknown"));
-  EXPECT_FALSE(TryMakeRequest(kBiddingWorkletUrl1, base::nullopt));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl1, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl1, kAcceptJson));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl1, "Unknown/Unknown"));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl1, base::nullopt));
+  TryMakeRequest(kBiddingWorkletUrl1, kAcceptJavascript,
+                 ExpectedResponse::kUseTrustedFactory);
+  TryMakeRequest(kBiddingWorkletUrl1, kAcceptJson, ExpectedResponse::kReject);
+  TryMakeRequest(kBiddingWorkletUrl1, "Unknown/Unknown",
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kBiddingWorkletUrl1, base::nullopt, ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl1, kAcceptJavascript,
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl1, kAcceptJson,
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl1, "Unknown/Unknown",
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl1, base::nullopt,
+                 ExpectedResponse::kReject);
 
-  EXPECT_TRUE(TryMakeRequest(kBiddingWorkletUrl2, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kBiddingWorkletUrl2, kAcceptJson));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl2, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kTrustedBiddingSignalsUrl2, kAcceptJson));
+  TryMakeRequest(kBiddingWorkletUrl2, kAcceptJavascript,
+                 ExpectedResponse::kUseTrustedFactory);
+  TryMakeRequest(kBiddingWorkletUrl2, kAcceptJson, ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl2, kAcceptJavascript,
+                 ExpectedResponse::kReject);
+  TryMakeRequest(kTrustedBiddingSignalsUrl2, kAcceptJson,
+                 ExpectedResponse::kReject);
 
-  EXPECT_TRUE(TryMakeRequest(kBiddingWorkletUrl3, kAcceptJavascript));
-  EXPECT_FALSE(TryMakeRequest(kBiddingWorkletUrl3, kAcceptJson));
+  TryMakeRequest(kBiddingWorkletUrl3, kAcceptJavascript,
+                 ExpectedResponse::kUseTrustedFactory);
+  TryMakeRequest(kBiddingWorkletUrl3, kAcceptJson, ExpectedResponse::kReject);
 }
 
 TEST_F(ActionUrlLoaderFactoryProxyTest, QueryStrings) {
@@ -266,40 +312,40 @@
 
   for (std::string query_string : kValidBiddingSignalsQueryStrings) {
     SCOPED_TRACE(query_string);
-    EXPECT_FALSE(
-        TryMakeRequest(kScoringWorkletUrl + query_string, kAcceptJavascript));
+    TryMakeRequest(kScoringWorkletUrl + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl1 + query_string, kAcceptJavascript));
-    EXPECT_TRUE(
-        TryMakeRequest(kTrustedBiddingSignalsUrl1 + query_string, kAcceptJson));
+    TryMakeRequest(kBiddingWorkletUrl1 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
+    TryMakeRequest(kTrustedBiddingSignalsUrl1 + query_string, kAcceptJson,
+                   ExpectedResponse::kUseTrustedFactory);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl2 + query_string, kAcceptJavascript));
-    EXPECT_TRUE(
-        TryMakeRequest(kTrustedBiddingSignalsUrl2 + query_string, kAcceptJson));
+    TryMakeRequest(kBiddingWorkletUrl2 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
+    TryMakeRequest(kTrustedBiddingSignalsUrl2 + query_string, kAcceptJson,
+                   ExpectedResponse::kUseTrustedFactory);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl3 + query_string, kAcceptJavascript));
+    TryMakeRequest(kBiddingWorkletUrl3 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
   }
 
   for (std::string query_string : kInvalidBiddingSignalsQueryStrings) {
     SCOPED_TRACE(query_string);
-    EXPECT_FALSE(
-        TryMakeRequest(kScoringWorkletUrl + query_string, kAcceptJavascript));
+    TryMakeRequest(kScoringWorkletUrl + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl1 + query_string, kAcceptJavascript));
-    EXPECT_FALSE(
-        TryMakeRequest(kTrustedBiddingSignalsUrl1 + query_string, kAcceptJson));
+    TryMakeRequest(kBiddingWorkletUrl1 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
+    TryMakeRequest(kTrustedBiddingSignalsUrl1 + query_string, kAcceptJson,
+                   ExpectedResponse::kReject);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl2 + query_string, kAcceptJavascript));
-    EXPECT_FALSE(
-        TryMakeRequest(kTrustedBiddingSignalsUrl2 + query_string, kAcceptJson));
+    TryMakeRequest(kBiddingWorkletUrl2 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
+    TryMakeRequest(kTrustedBiddingSignalsUrl2 + query_string, kAcceptJson,
+                   ExpectedResponse::kReject);
 
-    EXPECT_FALSE(
-        TryMakeRequest(kBiddingWorkletUrl3 + query_string, kAcceptJavascript));
+    TryMakeRequest(kBiddingWorkletUrl3 + query_string, kAcceptJavascript,
+                   ExpectedResponse::kReject);
   }
 }
 
@@ -325,15 +371,45 @@
                             kAcceptJavascript);
 
   request.url = GURL(kScoringWorkletUrl);
-  EXPECT_TRUE(TryMakeRequest(request));
+  TryMakeRequest(request, ExpectedResponse::kUseFrameFactory);
 
   request.url = GURL(kBiddingWorkletUrl1);
-  EXPECT_TRUE(TryMakeRequest(request));
+  TryMakeRequest(request, ExpectedResponse::kUseTrustedFactory);
 
   request.url = GURL(std::string(kTrustedBiddingSignalsUrl1) +
                      "?hostname=foo.test&keys=bar");
   request.headers.SetHeader(net::HttpRequestHeaders::kAccept, kAcceptJson);
-  EXPECT_TRUE(TryMakeRequest(request));
+  TryMakeRequest(request, ExpectedResponse::kUseTrustedFactory);
+}
+
+// If a bidder URL matches the scoring URL, the publisher frame's
+// URLLoaderFactory should be used instead of the trusted one.
+TEST_F(ActionUrlLoaderFactoryProxyTest, BidderUrlMatchesScoringUrl) {
+  blink::mojom::AuctionAdConfigPtr auction_config =
+      blink::mojom::AuctionAdConfig::New();
+  auction_config->decision_logic_url = GURL(kScoringWorkletUrl);
+  std::vector<auction_worklet::mojom::BiddingInterestGroupPtr> bidders;
+
+  bidders.emplace_back(auction_worklet::mojom::BiddingInterestGroup::New());
+  bidders.back()->group = blink::mojom::InterestGroup::New();
+  bidders.back()->group->bidding_url = GURL(kScoringWorkletUrl);
+
+  remote_url_loader_factory_.reset();
+  url_loader_factory_proxy_ = std::make_unique<AuctionURLLoaderFactoryProxy>(
+      remote_url_loader_factory_.BindNewPipeAndPassReceiver(),
+      base::BindRepeating(
+          [](network::mojom::URLLoaderFactory* factory) { return factory; },
+          &proxied_frame_url_loader_factory_),
+      base::BindRepeating(
+          [](network::mojom::URLLoaderFactory* factory) { return factory; },
+          &proxied_trusted_url_loader_factory_),
+      frame_origin_, *auction_config, bidders);
+
+  // Make request twice, as will actually happen in this case.
+  TryMakeRequest(kScoringWorkletUrl, kAcceptJavascript,
+                 ExpectedResponse::kUseFrameFactory);
+  TryMakeRequest(kScoringWorkletUrl, kAcceptJavascript,
+                 ExpectedResponse::kUseFrameFactory);
 }
 
 }  // namespace content
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index fc04e44..565f82e 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -23,7 +23,6 @@
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -42,6 +41,7 @@
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
 #include "third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom.h"
 #include "url/gurl.h"
@@ -76,7 +76,9 @@
 class InterestGroupBrowserTest : public ContentBrowserTest {
  public:
   InterestGroupBrowserTest() {
-    feature_list_.InitAndEnableFeature(features::kFledgeInterestGroups);
+    feature_list_.InitWithFeatures({blink::features::kFledgeInterestGroups,
+                                    blink::features::kFledgeInterestGroupAPI},
+                                   {});
   }
 
   ~InterestGroupBrowserTest() override {
@@ -104,8 +106,9 @@
                                                ->GetDefaultStoragePartition())
             ->GetInterestGroupStorage();
     content_browser_client_.SetAllowList(
-        {url::Origin::Create(https_server_->GetURL("a.test", "/echo")),
-         url::Origin::Create(https_server_->GetURL("b.test", "/echo"))});
+        {url::Origin::Create(https_server_->GetURL("a.test", "/")),
+         url::Origin::Create(https_server_->GetURL("b.test", "/")),
+         url::Origin::Create(https_server_->GetURL("c.test", "/"))});
     old_content_browser_client_ =
         SetBrowserClientForTesting(&content_browser_client_);
   }
@@ -1109,16 +1112,17 @@
   const struct ExpectedRequest {
     GURL url;
     const char* accept_header;
+    bool expect_trusted_params;
   } kExpectedRequests[] = {
       {https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
-       "application/javascript"},
+       "application/javascript", true /* expect_trusted_params */},
       {https_server_->GetURL(
            "a.test",
            "/interest_group/"
            "trusted_bidding_signals.json?hostname=a.test&keys=key1"),
-       "application/json"},
+       "application/json", true /* expect_trusted_params */},
       {https_server_->GetURL("a.test", "/interest_group/decision_logic.js"),
-       "application/javascript"},
+       "application/javascript", false /* expect_trusted_params */},
   };
   for (const auto& expected_request : kExpectedRequests) {
     SCOPED_TRACE(expected_request.url);
@@ -1137,15 +1141,27 @@
                                            &accept_value));
     EXPECT_EQ(expected_request.accept_header, accept_value);
 
-    ASSERT_TRUE(request->trusted_params);
-    const net::IsolationInfo& isolation_info =
-        request->trusted_params->isolation_info;
-    EXPECT_EQ(net::IsolationInfo::RequestType::kOther,
-              isolation_info.request_type());
-    url::Origin expected_origin = url::Origin::Create(expected_request.url);
-    EXPECT_EQ(expected_origin, isolation_info.top_frame_origin());
-    EXPECT_EQ(expected_origin, isolation_info.frame_origin());
-    EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
+    EXPECT_EQ(expected_request.expect_trusted_params,
+              request->trusted_params.has_value());
+    if (!request->trusted_params) {
+      // Requests for render-provided URLs use an empty trusted params value and
+      // enable CORS (and should use the RenderFrameHosts's URLLoaderFactory,
+      // which is validated in the next test).
+      EXPECT_EQ(network::mojom::RequestMode::kCors, request->mode);
+    } else {
+      // Requests for interest-group provided URLs are cross-origin, and set
+      // trusted params to use the right cache shard, since they use a trusted
+      // URLLoaderFactory.
+      EXPECT_EQ(network::mojom::RequestMode::kNoCors, request->mode);
+      const net::IsolationInfo& isolation_info =
+          request->trusted_params->isolation_info;
+      EXPECT_EQ(net::IsolationInfo::RequestType::kOther,
+                isolation_info.request_type());
+      url::Origin expected_origin = url::Origin::Create(expected_request.url);
+      EXPECT_EQ(expected_origin, isolation_info.top_frame_origin());
+      EXPECT_EQ(expected_origin, isolation_info.frame_origin());
+      EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
+    }
   }
 
   // Check ResourceRequest structs of report requests.
@@ -1183,6 +1199,82 @@
                 ->trusted_params->isolation_info.network_isolation_key());
 }
 
+// Use different origins for publisher, bidder, and seller, and make sure
+// everything works as expected.
+IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, CrossOrigin) {
+  const char kPublisher[] = "a.test";
+  const char kBidder[] = "b.test";
+  const char kSeller[] = "c.test";
+
+  // Navigate to bidder site, and add an interest group.
+  GURL bidder_url = https_server_->GetURL(kBidder, "/echo");
+  ASSERT_TRUE(NavigateToURL(shell(), bidder_url));
+  std::string ads =
+      "[{renderUrl : 'https://example.com/render',"
+      "metadata : {ad:'metadata', here : [ 1, 2 ]}}]";
+  EXPECT_TRUE(JoinInterestGroupAndWait(
+      blink::mojom::InterestGroup::New(
+          /* expiry */ base::Time(),
+          /* owner= */ url::Origin::Create(bidder_url.GetOrigin()),
+          /* name = */ "cars",
+          /* bidding_url = */
+          https_server_->GetURL(kBidder, "/interest_group/bidding_logic.js"),
+          /* update_url  = */ base::nullopt,
+          /* trusted_bidding_signals_url = */
+          https_server_->GetURL(kBidder,
+                                "/interest_group/trusted_bidding_signals.json"),
+          /* trusted_bidding_signals_keys = */ base::nullopt,
+          /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}",
+          /* ads = */ base::nullopt),
+      ads, "['key1']"));
+
+  // Navigate to publisher.
+  ASSERT_TRUE(
+      NavigateToURL(shell(), https_server_->GetURL(kPublisher, "/echo")));
+
+  // Run auction with a seller script missing an "Access-Control-Allow-Origin"
+  // header. The request for the seller script should fail, and so should the
+  // auction.
+  GURL seller_logic_url =
+      https_server_->GetURL(kSeller, "/interest_group/decision_logic.js");
+  EXPECT_EQ(nullptr,
+            RunAuctionAndWait(JsReplace(
+                R"(
+{
+  seller: $1,
+  decisionLogicUrl: $2,
+  interestGroupBuyers: [$3],
+  auctionSignals: {x: 1},
+  sellerSignals: {yet: 'more', info: 1},
+  perBuyerSignals: {$3: {even: 'more', x: 4.5}}
+}
+)",
+                url::Origin::Create(seller_logic_url), seller_logic_url.spec(),
+                url::Origin::Create(bidder_url))));
+
+  // Run auction with a seller script with an "Access-Control-Allow-Origin"
+  // header. The auction should succeed.
+  seller_logic_url = https_server_->GetURL(
+      kSeller, "/interest_group/decision_logic_cross_origin.js");
+  ASSERT_EQ("https://example.com/render",
+            RunAuctionAndWait(JsReplace(
+                R"(
+{
+  seller: $1,
+  decisionLogicUrl: $2,
+  interestGroupBuyers: [$3],
+  auctionSignals: {x: 1},
+  sellerSignals: {yet: 'more', info: 1},
+  perBuyerSignals: {$3: {even: 'more', x: 4.5}}
+}
+)",
+                url::Origin::Create(seller_logic_url), seller_logic_url.spec(),
+                url::Origin::Create(bidder_url))));
+  // Reporting urls should be fetched after an auction succeeded.
+  WaitForURL(https_server_->GetURL("/echoall?report_seller"));
+  WaitForURL(https_server_->GetURL("/echoall?report_bidder"));
+}
+
 IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
                        RunAdAuctionWithWinnerManyInterestGroups) {
   GURL test_url = https_server_->GetURL("a.test", "/echo");
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc
index a8d2eca9..48e7c251 100644
--- a/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -577,7 +577,15 @@
         base::WaitableEvent::InitialState::NOT_SIGNALED);
 
     scoped_refptr<base::SingleThreadTaskRunner> message_loop_task_runner;
-    scoped_refptr<base::TestMockTimeTaskRunner> task_runner;
+    // Note that we deliberately don't keep a reference to the
+    // TestMockTimeTaskRunner. That way, it's destroyed through
+    // |capture_device_|->StopAndDeAllocate() before the capture device's
+    // internal thread is stopped. This is important because either the
+    // TestMockTimeTaskRunner is destroyed on the thread it was created on or a
+    // task is posted to that thread to destroy it. If that thread is stopped
+    // before the last reference to the TestMockTimeTaskRunner goes away, we'd
+    // get a leak.
+    base::TestMockTimeTaskRunner* task_runner = nullptr;
     int nb_frames = 0;
 
     std::unique_ptr<media::MockVideoCaptureDeviceClient> client(
@@ -588,11 +596,13 @@
         .WillOnce(InvokeWithoutArgs([this, &task_runner,
                                      &message_loop_task_runner] {
           message_loop_task_runner = base::ThreadTaskRunnerHandle::Get();
-          task_runner = new base::TestMockTimeTaskRunner(
-              base::Time::Now(), base::TimeTicks::Now(),
-              base::TestMockTimeTaskRunner::Type::kStandalone);
+          auto test_task_runner =
+              base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+                  base::Time::Now(), base::TimeTicks::Now(),
+                  base::TestMockTimeTaskRunner::Type::kStandalone);
+          task_runner = test_task_runner.get();
           capture_device_->SetMockTimeForTesting(
-              task_runner, task_runner->GetMockTickClock());
+              std::move(test_task_runner), task_runner->GetMockTickClock());
         }));
 
     EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _, _, _))
@@ -629,7 +639,7 @@
                           task_runner->FastForwardBy(
                               task_runner->NextPendingTaskDelay());
                         },
-                        task_runner));
+                        base::WrapRefCounted(task_runner)));
               }
             }))));
     media::VideoCaptureParams capture_params;
diff --git a/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc b/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
index d4be0138..50c27549 100644
--- a/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
+++ b/content/browser/media/capture/mouse_cursor_overlay_controller_aura.cc
@@ -153,12 +153,8 @@
   if (auto* window = Observer::GetTargetWindow(observer_)) {
     if (auto* host = window->GetHost()) {
       gfx::NativeCursor cursor = host->last_cursor();
-      if (cursor != ui::mojom::CursorType::kNull) {
-        if (cursor.image_scale_factor() < 1.0f) {
-          cursor.set_image_scale_factor(1.0f);
-        }
+      if (cursor != ui::mojom::CursorType::kNull)
         return cursor;
-      }
     }
   }
 
@@ -174,21 +170,17 @@
     const gfx::Size window_size = window->bounds().size();
     if (!window_size.IsEmpty()) {
       if (auto* root_window = window->GetRootWindow()) {
-        // Compute the cursor size in terms of DIP coordinates.
         const SkBitmap& bitmap = GetCursorBitmap(cursor);
         const float scale_factor = cursor.image_scale_factor();
-        const gfx::SizeF size =
-            scale_factor > 0.0f
-                ? gfx::ScaleSize(gfx::SizeF(bitmap.width(), bitmap.height()),
-                                 1.0f / scale_factor)
-                : gfx::SizeF(bitmap.width(), bitmap.height());
+        DCHECK_GT(scale_factor, 0.0f);
+
+        // Compute the cursor size in terms of DIP coordinates.
+        const gfx::SizeF size = gfx::ScaleSize(
+            gfx::SizeF(bitmap.width(), bitmap.height()), 1.0f / scale_factor);
 
         // Compute the hotspot in terms of DIP coordinates.
-        const gfx::PointF hotspot =
-            scale_factor > 0.0f
-                ? gfx::ScalePoint(gfx::PointF(GetCursorHotspot(cursor)),
-                                  1.0f / scale_factor)
-                : gfx::PointF(GetCursorHotspot(cursor));
+        const gfx::PointF hotspot = gfx::ScalePoint(
+            gfx::PointF(GetCursorHotspot(cursor)), 1.0f / scale_factor);
 
         // Finally, put it all together: Scale the absolute bounds of the
         // overlay by the window size to produce relative coordinates.
diff --git a/content/browser/prerender/OWNERS b/content/browser/prerender/OWNERS
index 5754b82..cf065e6 100644
--- a/content/browser/prerender/OWNERS
+++ b/content/browser/prerender/OWNERS
@@ -2,3 +2,5 @@
 kinuko@chromium.org
 nhiroki@chromium.org
 toyoshim@chromium.org
+
+per-file *test.cc=lingqi@chromium.org
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 1ed1f57..a9a31ed 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -10373,66 +10373,80 @@
     return;
   }
 
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_intended",
-                        request->commit_params().intended_as_new_entry);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_intended",
-                        params.intended_as_new_entry);
-
-  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "browser_method",
-                            browser_method);
-  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "renderer_method",
-                            params.method);
-  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "original_method",
-                            request->commit_params().original_method);
-
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_unreachable",
-                        browser_url_is_unreachable);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_unreachable",
-                        params.url_is_unreachable);
-
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "prev_ldwb",
                         is_loaded_from_load_data_with_base_url_);
   SCOPED_CRASH_KEY_BOOL(
       "VerifyDidCommit", "prev_ldwbu",
       is_loaded_from_load_data_with_base_url_and_unreachable_url_);
   SCOPED_CRASH_KEY_BOOL(
-      "VerifyDidCommit", "b_hist_url_empty",
-      request->common_params().history_url_for_data_url.is_empty());
+      "VerifyDidCommit", "base_url_fdu_empty",
+      request->common_params().base_url_for_data_url.is_empty());
 #if defined(OS_ANDROID)
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "b_data_url_empty",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "data_url_empty",
                         request->commit_params().data_url_as_string.empty());
 #endif
   SCOPED_CRASH_KEY_BOOL(
-      "VerifyDidCommit", "r_history_url_empty",
+      "VerifyDidCommit", "history_url_fdu_empty",
       request->common_params().history_url_for_data_url.is_empty());
 
-  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "browser_post_id",
-                          browser_post_id);
-  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "renderer_post_id",
-                          params.post_id);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "intended_browser",
+                        request->commit_params().intended_as_new_entry);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "intended_renderer",
+                        params.intended_as_new_entry);
 
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_override_ua",
+  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "method_browser",
+                            browser_method);
+  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "method_renderer",
+                            params.method);
+  SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "original_method",
+                            request->commit_params().original_method);
+  // For WebView, since we don't want to log potential PIIs.
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "method_post_browser",
+                        browser_method == "POST");
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "method_post_renderer",
+                        params.method == "POST");
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "original_method_post",
+                        request->commit_params().original_method == "POST");
+
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "unreachable_browser",
+                        browser_url_is_unreachable);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "unreachable_renderer",
+                        params.url_is_unreachable);
+
+  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "post_id_browser",
+                          browser_post_id);
+  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "post_id_renderer",
+                          params.post_id);
+  // For WebView, since we don't want to log IDs.
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_matches",
+                        browser_post_id == params.post_id);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_-1_browser",
+                        browser_post_id == -1);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_-1_renderer",
+                        params.post_id == -1);
+
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "override_ua_browser",
                         browser_is_overriding_user_agent);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_override_ua",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "override_ua_renderer",
                         params.is_overriding_user_agent);
 
-  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "browser_code",
+  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "code_browser",
                           browser_http_status_code);
-  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "renderer_code",
+  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "code_renderer",
                           params.http_status_code);
 
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_suh",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "suh_browser",
                         browser_should_update_history);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_suh",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "suh_renderer",
                         params.should_update_history);
 
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_gesture", browser_gesture);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_gesture",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "gesture_browser", browser_gesture);
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "gesture_renderer",
                         renderer_gesture);
 
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "browser_replace",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "replace_browser",
                         browser_should_replace_current_entry);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_replace",
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "replace_renderer",
                         params.should_replace_current_entry);
 
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_same_document",
@@ -10456,10 +10470,24 @@
 
   SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "entry_offset",
                           request->GetNavigationEntryOffset());
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_reload",
-                        request->GetReloadType() != ReloadType::NONE);
-  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_restore",
-                        request->GetRestoreType() == RestoreType::kRestored);
+  SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "entry_count",
+                          frame_tree()->controller().GetEntryCount());
+  SCOPED_CRASH_KEY_NUMBER(
+      "VerifyDidCommit", "last_committed_index",
+      frame_tree()->controller().GetLastCommittedEntryIndex());
+
+  SCOPED_CRASH_KEY_BOOL(
+      "VerifyDidCommit", "is_reload",
+      NavigationTypeUtils::IsReload(request->common_params().navigation_type));
+  SCOPED_CRASH_KEY_BOOL(
+      "VerifyDidCommit", "is_restore",
+      NavigationTypeUtils::IsRestore(request->common_params().navigation_type));
+  SCOPED_CRASH_KEY_BOOL(
+      "VerifyDidCommit", "is_history",
+      NavigationTypeUtils::IsHistory(request->common_params().navigation_type));
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "has_valid_page_state",
+                        request->commit_params().page_state.IsValid());
+
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "has_gesture",
                         request->HasUserGesture());
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "was_click",
@@ -10482,8 +10510,12 @@
                         request->commit_params().original_url.EqualsIgnoringRef(
                             GetLastCommittedURL()));
 
+  SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "committed_real_load",
+                        frame_tree_node_->has_committed_real_load());
+
   SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "last_committed_url",
                              GetLastCommittedURL().spec());
+
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "last_url_empty",
                         GetLastCommittedURL().is_empty());
   SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "last_url_blank",
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 16674999..d30fbc3 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -122,10 +122,6 @@
 #include "ui/wm/core/ime_util_chromeos.h"
 #endif
 
-#if defined(OS_FUCHSIA)
-#include "ui/base/ime/virtual_keyboard_controller.h"
-#endif
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
@@ -1828,12 +1824,6 @@
   if (window_ && virtual_keyboard_controller_win_) {
     virtual_keyboard_controller_win_->FocusedNodeChanged(editable);
   }
-#elif defined(OS_FUCHSIA)
-  if (!editable && window_) {
-    if (input_method) {
-      input_method->GetVirtualKeyboardController()->DismissVirtualKeyboard();
-    }
-  }
 #endif
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index e90a659..03c0e80 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -571,6 +571,9 @@
   // Whether or not the NSView is first responder.
   bool is_first_responder_ = false;
 
+  // Whether Focus() is being called.
+  bool is_getting_focus_ = false;
+
   // Indicates if the page is loading.
   bool is_loading_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index fea56a43..e99a5a1 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
@@ -509,9 +510,11 @@
 
 void RenderWidgetHostViewMac::Focus() {
   // Ignore redundant calls, as they can cause unending loops of focus-setting.
-  // https://crbug.com/998123
-  if (is_first_responder_)
+  // crbug.com/998123, crbug.com/804184.
+  if (is_first_responder_ || is_getting_focus_)
     return;
+
+  base::AutoReset<bool> is_getting_focus_bit(&is_getting_focus_, true);
   ns_view_->MakeFirstResponder();
 }
 
@@ -1474,6 +1477,7 @@
     return;
   is_first_responder_ = is_first_responder;
   accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder_);
+
   if (is_first_responder_) {
     host()->GotFocus();
     SetTextInputActive(true);
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index d5d615f..a6dbfdb 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -1297,7 +1297,7 @@
         this, path, special_storage_policy_);
   }
 
-  if (base::FeatureList::IsEnabled(features::kFledgeInterestGroups)) {
+  if (base::FeatureList::IsEnabled(blink::features::kFledgeInterestGroups)) {
     interest_group_manager_ =
         std::make_unique<InterestGroupManager>(path, is_in_memory_);
   }
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 0fe9dfe..59ff210 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -822,9 +822,9 @@
     // Configures the Conversion API to run in memory to speed up it's
     // initialization and avoid timeouts. See https://crbug.com/1080764.
     ConversionManagerImpl::RunInMemoryForTesting();
-    feature_list_.InitWithFeatures(
-        {features::kConversionMeasurement, features::kFledgeInterestGroups},
-        {});
+    feature_list_.InitWithFeatures({features::kConversionMeasurement,
+                                    blink::features::kFledgeInterestGroups},
+                                   {});
   }
 
   storage::MockQuotaManager* GetMockManager() {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 7f610a6e..bf97b7f 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -361,7 +361,7 @@
           {"FontAccess", blink::features::kFontAccess},
           {"FontAccessPersistent", blink::features::kFontAccessPersistent},
           {"FontSrcLocalMatching", features::kFontSrcLocalMatching},
-          {"FledgeInterestGroups", features::kFledgeInterestGroups},
+          {"FledgeInterestGroupAPI", blink::features::kFledgeInterestGroupAPI},
           {"ForceSynchronousHTMLParsing",
            blink::features::kForceSynchronousHTMLParsing},
           {"IgnoreCrossOriginWindowWhenNamedAccessOnWindow",
diff --git a/content/common/cursors/webcursor_aura.cc b/content/common/cursors/webcursor_aura.cc
index 9dc2116..752dcb5 100644
--- a/content/common/cursors/webcursor_aura.cc
+++ b/content/common/cursors/webcursor_aura.cc
@@ -22,7 +22,7 @@
       CreateScaledBitmapAndHotspotFromCustomData(&bitmap, &hotspot, &scale);
       custom_cursor_->set_custom_bitmap(bitmap);
       custom_cursor_->set_custom_hotspot(hotspot);
-      custom_cursor_->set_image_scale_factor(scale);
+      custom_cursor_->set_image_scale_factor(device_scale_factor_);
       custom_cursor_->SetPlatformCursor(
           ui::CursorFactory::GetInstance()->CreateImageCursor(
               ui::mojom::CursorType::kCustom, bitmap, hotspot));
diff --git a/content/common/cursors/webcursor_unittest.cc b/content/common/cursors/webcursor_unittest.cc
index 373ca54..530f0e2 100644
--- a/content/common/cursors/webcursor_unittest.cc
+++ b/content/common/cursors/webcursor_unittest.cc
@@ -11,6 +11,8 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/skia_util.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
@@ -140,23 +142,36 @@
 
 #if defined(USE_AURA)
 TEST(WebCursorTest, CursorScaleFactor) {
+  constexpr float kImageScale = 2.0f;
+  constexpr float kDeviceScale = 4.2f;
+
   ui::Cursor cursor(ui::mojom::CursorType::kCustom);
   cursor.set_custom_hotspot(gfx::Point(0, 1));
-  cursor.set_image_scale_factor(2.0f);
+  cursor.set_image_scale_factor(kImageScale);
   cursor.set_custom_bitmap(CreateTestBitmap(128, 128));
   WebCursor webcursor(cursor);
 
   display::Display display;
-  display.set_device_scale_factor(4.2f);
+  display.set_device_scale_factor(kDeviceScale);
   webcursor.SetDisplayInfo(display);
 
 #if defined(USE_OZONE)
-  // For Ozone cursors, the size of the cursor is capped at 64px, and this is
-  // enforce through the calculated scale factor.
-  EXPECT_EQ(0.5f, webcursor.GetNativeCursor().image_scale_factor());
+  // In Ozone, the size of the cursor is capped at 64px unless the hardware
+  // advertises support for bigger cursors.
+  const gfx::Size kDefaultMaxSize = gfx::Size(64, 64);
+  EXPECT_EQ(gfx::SkISizeToSize(
+                webcursor.GetNativeCursor().custom_bitmap().dimensions()),
+            kDefaultMaxSize);
 #else
-  EXPECT_EQ(2.1f, webcursor.GetNativeCursor().image_scale_factor());
+  EXPECT_EQ(
+      gfx::SkISizeToSize(
+          webcursor.GetNativeCursor().custom_bitmap().dimensions()),
+      gfx::ScaleToFlooredSize(gfx::Size(128, 128), kDeviceScale / kImageScale));
 #endif
+
+  // The scale factor of the cursor image should match the device scale factor,
+  // regardless of the cursor size.
+  EXPECT_EQ(webcursor.GetNativeCursor().image_scale_factor(), kDeviceScale);
 }
 
 TEST(WebCursorTest, UnscaledImageCopy) {
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index a799656..839bd7a 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -262,10 +262,6 @@
 const base::Feature kFeaturePolicyForClientHints{
     "FeaturePolicyForClientHints", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enables FLEDGE implementation. See https://crbug.com/1186444.
-const base::Feature kFledgeInterestGroups{"FledgeInterestGroups",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables fixes for matching src: local() for web fonts correctly against full
 // font name or postscript name. Rolling out behind a flag, as enabling this
 // enables a font indexer on Android which we need to test in the field first.
@@ -960,11 +956,6 @@
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
 #if defined(OS_ANDROID)
-// Autofill Accessibility in Android.
-// crbug.com/627860
-const base::Feature kAndroidAutofillAccessibility{
-    "AndroidAutofillAccessibility", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Sets moderate binding to background renderers playing media, when enabled.
 // Else the renderer will have strong binding.
 const base::Feature kBackgroundMediaRendererHasModerateBinding{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index b0567cb..6efd166 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -66,7 +66,6 @@
 CONTENT_EXPORT extern const base::Feature
     kExtraSafelistedRequestHeadersForOutOfBlinkCors;
 CONTENT_EXPORT extern const base::Feature kFeaturePolicyForClientHints;
-CONTENT_EXPORT extern const base::Feature kFledgeInterestGroups;
 CONTENT_EXPORT extern const base::Feature kFontSrcLocalMatching;
 #if !defined(OS_ANDROID)
 CONTENT_EXPORT extern const base::Feature
@@ -237,7 +236,6 @@
 CONTENT_EXPORT extern const base::Feature kWebXrIncubations;
 
 #if defined(OS_ANDROID)
-CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;
 CONTENT_EXPORT extern const base::Feature
     kBackgroundMediaRendererHasModerateBinding;
 CONTENT_EXPORT extern const base::Feature kBindingManagementWaiveCpu;
diff --git a/content/public/test/prerender_test_util.cc b/content/public/test/prerender_test_util.cc
index f664161..032b6791c 100644
--- a/content/public/test/prerender_test_util.cc
+++ b/content/public/test/prerender_test_util.cc
@@ -217,6 +217,38 @@
       << "AddPrerender failed. Did you load add_prerender.html?";
 }
 
+int PrerenderTestHelper::AddPrerenderWithTestUtilJS(const GURL& gurl) {
+  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  std::string start_prerender = R"(
+      (() => {
+        const script = document.createElement('script');
+        script.addEventListener('load', () => {
+          window.domAutomationController.send(true);
+        });
+        script.addEventListener('error', () => {
+          window.domAutomationController.send(false);
+        });
+        script.src = '/prerender/test_utils.js';
+        document.body.appendChild(script);
+      })();
+    )";
+  bool script_loaded = false;
+  // Load test_utils.js and wait util loading done.
+  EXPECT_TRUE(ExecuteScriptAndExtractBool(GetWebContents()->GetMainFrame(),
+                                          start_prerender, &script_loaded));
+  EXPECT_TRUE(script_loaded);
+
+  EXPECT_TRUE(ExecJs(GetWebContents(), JsReplace("add_prerender($1)", gurl)))
+      << "AddPrerender failed. Did you set the right path to load "
+         "/prerender/test_utils.js?";
+
+  WaitForPrerenderLoadCompletion(gurl);
+  int host_id = GetHostForUrl(gurl);
+  EXPECT_NE(host_id, RenderFrameHost::kNoFrameTreeNodeId);
+  return host_id;
+}
+
 void PrerenderTestHelper::NavigatePrerenderedPage(int host_id,
                                                   const GURL& gurl) {
   auto* prerender_host = GetPrerenderHostById(GetWebContents(), host_id);
diff --git a/content/public/test/prerender_test_util.h b/content/public/test/prerender_test_util.h
index 9f84c5a..789ef75 100644
--- a/content/public/test/prerender_test_util.h
+++ b/content/public/test/prerender_test_util.h
@@ -89,6 +89,10 @@
   int AddPrerender(const GURL& gurl);
   void AddPrerenderAsync(const GURL& gurl);
 
+  // Adds <link rel=prerender> in the current main frame without loading
+  // add_prerender.html and waits until the completion of prerendering.
+  int AddPrerenderWithTestUtilJS(const GURL& gurl);
+
   // This navigates, but does not activate, the prerendered page.
   void NavigatePrerenderedPage(int host_id, const GURL& gurl);
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 2bff271..781c590e 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2390,6 +2390,7 @@
     "//ui/events:gesture_detection",
     "//ui/events:test_support",
     "//ui/events/blink",
+    "//ui/gfx:geometry_skia",
     "//ui/gfx:test_support",
     "//ui/gfx/geometry",
     "//ui/gfx/geometry/mojom:mojom_traits",
diff --git a/content/test/data/interest_group/decision_logic_cross_origin.js b/content/test/data/interest_group/decision_logic_cross_origin.js
new file mode 100644
index 0000000..975d5c1
--- /dev/null
+++ b/content/test/data/interest_group/decision_logic_cross_origin.js
@@ -0,0 +1,18 @@
+// 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.
+
+function scoreAd(
+  adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
+  return bid;
+}
+
+function reportResult(
+  auctionConfig, browserSignals) {
+  sendReportTo(auctionConfig.seller + '/echoall?report_seller');
+  return {
+    'success': true,
+    'signalsForWinner': {'signalForWinner': 1},
+    'reportUrl': auctionConfig.seller + '/report_seller',
+  };
+}
diff --git a/content/test/data/interest_group/decision_logic_cross_origin.js.mock-http-headers b/content/test/data/interest_group/decision_logic_cross_origin.js.mock-http-headers
new file mode 100644
index 0000000..575efbf
--- /dev/null
+++ b/content/test/data/interest_group/decision_logic_cross_origin.js.mock-http-headers
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OK
+Content-Type: Application/Javascript
+X-Allow-FLEDGE: true
+Access-Control-Allow-Origin: *
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py
index f275c2a..ad02a22 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -129,6 +129,13 @@
       os_name = cls.browser.platform.GetOSName()
       if os_name == 'android' or os_name == 'chromeos':
         browser_args.remove(cba.DISABLE_GPU)
+
+    # Reduce number of video buffers when running tests on Fuchsia to
+    # workaround crbug.com/1203580
+    # TODO(https://crbug.com/1203580): Remove this once the bug is resolved.
+    if cls._finder_options.browser_type == 'web-engine-shell':
+      browser_args.append('--double-buffer-compositing')
+
     return browser_args
 
   @classmethod
diff --git a/extensions/browser/content_script_tracker.cc b/extensions/browser/content_script_tracker.cc
index f605f701..2207b07 100644
--- a/extensions/browser/content_script_tracker.cc
+++ b/extensions/browser/content_script_tracker.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/url_loader_factory_manager.h"
+#include "extensions/common/content_script_injection_url_getter.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/user_script.h"
@@ -74,63 +75,81 @@
 
 const char* ContentScriptsSet::kUserDataKey = "ContentScriptTracker's data";
 
-// If `match_about_blank` is true, then traverses parent/opener chain until the
-// first non-about-scheme document and returns its url.  Otherwise, simply
-// returns `document_url`.
-//
-// This function approximates
-// ScriptContext::GetEffectiveDocumentURLForInjection() from the renderer side.
-// Unlike the renderer code, this just iterates up frame tree, and doesn't look
-// at the effective or precursor origin of the frame. This is okay, because our
-// only caller (DoesContentScriptMatch()) expects false positives.
-GURL GetEffectiveDocumentURL(content::RenderFrameHost* frame,
-                             const GURL& document_url,
-                             bool match_about_blank) {
-  base::flat_set<content::RenderFrameHost*> already_visited_frames;
+class RenderFrameHostAdapter
+    : public ContentScriptInjectionUrlGetter::FrameAdapter {
+ public:
+  explicit RenderFrameHostAdapter(content::RenderFrameHost* frame)
+      : frame_(frame) {}
 
-  // Common scenario. If `match_about_blank` is false (as is the case in most
-  // extensions), or if the frame is not an about:-page, just return
-  // `document_url` (supposedly the URL of the frame).
-  if (!match_about_blank || !document_url.SchemeIs(url::kAboutScheme))
-    return document_url;
+  ~RenderFrameHostAdapter() override = default;
 
-  // Non-sandboxed about:blank and about:srcdoc pages inherit their security
-  // origin from their parent frame/window. So, traverse the frame/window
-  // hierarchy to find the closest non-about:-page and return its URL.
-  //
-  // TODO(https://crbug.com/1186321): The assumption above is incorrect -
-  // about:blank frames inherit their origin from the initiator of the
-  // navigation (which might not be the parent and/or the opener).
-  content::RenderFrameHost* found_frame = frame;
-  do {
-    DCHECK(found_frame);
-    already_visited_frames.insert(found_frame);
+  std::unique_ptr<FrameAdapter> Clone() const override {
+    return std::make_unique<RenderFrameHostAdapter>(frame_);
+  }
 
-    // The loop should only execute (and consider the parent chain) if the
-    // currently considered frame has about: scheme.
-    DCHECK(match_about_blank);
-    DCHECK(
-        ((found_frame == frame) && document_url.SchemeIs(url::kAboutScheme)) ||
-        found_frame->GetLastCommittedURL().SchemeIs(url::kAboutScheme));
-
-    // Attempt to find `next_candidate` - either a parent of opener of
-    // `found_frame`.
-    content::RenderFrameHost* next_candidate = found_frame->GetParent();
-    if (!next_candidate) {
-      next_candidate =
-          content::WebContents::FromRenderFrameHost(found_frame)->GetOpener();
+  std::unique_ptr<FrameAdapter> GetLocalParentOrOpener() const override {
+    content::RenderFrameHost* parent_or_opener = frame_->GetParent();
+    if (!parent_or_opener) {
+      parent_or_opener =
+          content::WebContents::FromRenderFrameHost(frame_)->GetOpener();
     }
-    if (!next_candidate ||
-        base::Contains(already_visited_frames, next_candidate)) {
-      break;
-    }
+    if (!parent_or_opener)
+      return nullptr;
 
-    found_frame = next_candidate;
-  } while (found_frame->GetLastCommittedURL().SchemeIs(url::kAboutScheme));
+    // Renderer-side WebLocalFrameAdapter only considers local frames.
+    // Comparing processes is robust way to replicate such renderer-side checks,
+    // because out caller (DoesContentScriptMatch) accepts false positives.
+    // This comparison might be less accurate (e.g. give more false positives)
+    // than SiteInstance comparison, but comparing processes should be robust
+    // and stable as SiteInstanceGroup refactoring proceeds.
+    if (parent_or_opener->GetProcess() != frame_->GetProcess())
+      return nullptr;
 
-  if (found_frame == frame)
-    return document_url;  // Not committed yet at ReadyToCommitNavigation time.
-  return found_frame->GetLastCommittedURL();
+    return std::make_unique<RenderFrameHostAdapter>(parent_or_opener);
+  }
+
+  GURL GetUrl() const override { return frame_->GetLastCommittedURL(); }
+
+  url::Origin GetOrigin() const override {
+    return frame_->GetLastCommittedOrigin();
+  }
+
+  bool CanAccess(const url::Origin& target) const override {
+    // CanAccess should not be called - see the comment for
+    // kAllowInaccessibleParents in GetEffectiveDocumentURL below.
+    NOTREACHED();
+    return true;
+  }
+
+  bool CanAccess(const FrameAdapter& target) const override {
+    // CanAccess should not be called - see the comment for
+    // kAllowInaccessibleParents in GetEffectiveDocumentURL below.
+    NOTREACHED();
+    return true;
+  }
+
+  uintptr_t GetId() const override { return frame_->GetRoutingID(); }
+
+ private:
+  content::RenderFrameHost* const frame_;
+};
+
+// This function approximates ScriptContext::GetEffectiveDocumentURLForInjection
+// from the renderer side.
+GURL GetEffectiveDocumentURL(
+    content::RenderFrameHost* frame,
+    const GURL& document_url,
+    MatchOriginAsFallbackBehavior match_origin_as_fallback) {
+  // This is a simplification to avoid calling
+  // `RenderFrameHostAdapter::CanAccess` which is unable to replicate all of
+  // WebSecurityOrigin::CanAccess checks (e.g. universal access or file
+  // exceptions tracked on the renderer side).  This is okay, because our only
+  // caller (DoesContentScriptMatch()) expects false positives.
+  constexpr bool kAllowInaccessibleParents = true;
+
+  return ContentScriptInjectionUrlGetter::Get(
+      RenderFrameHostAdapter(frame), document_url, match_origin_as_fallback,
+      kAllowInaccessibleParents);
 }
 
 // If `user_script` will inject JavaScript content script into the target of
@@ -153,18 +172,8 @@
   if (user_script.js_scripts().empty())
     return false;
 
-  // TODO(devlin): Update GetEffectiveDocumentURL() to take a
-  // MatchOriginAsFallbackBehavior.
-  bool match_about_blank = false;
-  switch (user_script.match_origin_as_fallback()) {
-    case MatchOriginAsFallbackBehavior::kAlways:
-    case MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree:
-      match_about_blank = true;
-      break;
-    case MatchOriginAsFallbackBehavior::kNever:
-      break;  // `false` is correct for `match_about_blank`.
-  }
-  GURL effective_url = GetEffectiveDocumentURL(frame, url, match_about_blank);
+  GURL effective_url = GetEffectiveDocumentURL(
+      frame, url, user_script.match_origin_as_fallback());
   bool is_subframe = frame->GetParent();
   return user_script.MatchesDocument(effective_url, is_subframe);
 }
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index c8f8d8f..bd9ba08 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -146,6 +146,8 @@
       "common_manifest_handlers.cc",
       "common_manifest_handlers.h",
       "common_param_traits.h",
+      "content_script_injection_url_getter.cc",
+      "content_script_injection_url_getter.h",
       "cors_util.cc",
       "cors_util.h",
       "csp_validator.cc",
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json
index 77faf04..e25ae97 100644
--- a/extensions/common/api/_manifest_features.json
+++ b/extensions/common/api/_manifest_features.json
@@ -39,6 +39,14 @@
     "channel": "stable",
     "extension_types": ["platform_app"]
   },
+  "automation": [{
+    "channel": "dev",
+    "extension_types": ["extension", "legacy_packaged_app", "platform_app"]
+  }, {
+    "channel": "stable",
+    "extension_types": ["extension", "legacy_packaged_app"],
+    "allowlist": [ "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E" ]
+  }],
   "background": {
     "channel": "stable",
     "extension_types": [
diff --git a/extensions/common/common_manifest_handlers.cc b/extensions/common/common_manifest_handlers.cc
index c5f6e47..b8e0283 100644
--- a/extensions/common/common_manifest_handlers.cc
+++ b/extensions/common/common_manifest_handlers.cc
@@ -14,6 +14,7 @@
 #include "extensions/common/api/printer_provider/usb_printer_manifest_handler.h"
 #include "extensions/common/api/sockets/sockets_manifest_handler.h"
 #include "extensions/common/manifest_handler.h"
+#include "extensions/common/manifest_handlers/automation.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/manifest_handlers/content_capabilities_handler.h"
 #include "extensions/common/manifest_handlers/content_scripts_handler.h"
@@ -54,6 +55,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   registry->RegisterHandler(std::make_unique<ActionHandlersHandler>());
 #endif
+  registry->RegisterHandler(std::make_unique<AutomationHandler>());
   registry->RegisterHandler(std::make_unique<BackgroundManifestHandler>());
   registry->RegisterHandler(std::make_unique<BluetoothManifestHandler>());
   registry->RegisterHandler(std::make_unique<ContentCapabilitiesHandler>());
diff --git a/extensions/common/content_script_injection_url_getter.cc b/extensions/common/content_script_injection_url_getter.cc
new file mode 100644
index 0000000..5baa46f
--- /dev/null
+++ b/extensions/common/content_script_injection_url_getter.cc
@@ -0,0 +1,155 @@
+// 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 "extensions/common/content_script_injection_url_getter.h"
+
+#include "base/containers/flat_set.h"
+#include "base/notreached.h"
+#include "url/scheme_host_port.h"
+
+namespace extensions {
+
+ContentScriptInjectionUrlGetter::FrameAdapter::~FrameAdapter() = default;
+
+// static
+GURL ContentScriptInjectionUrlGetter::Get(
+    const FrameAdapter& frame,
+    const GURL& document_url,
+    MatchOriginAsFallbackBehavior match_origin_as_fallback,
+    bool allow_inaccessible_parents) {
+  auto should_consider_origin = [&document_url, match_origin_as_fallback]() {
+    switch (match_origin_as_fallback) {
+      case MatchOriginAsFallbackBehavior::kNever:
+        return false;
+      case MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree:
+        return document_url.SchemeIs(url::kAboutScheme);
+      case MatchOriginAsFallbackBehavior::kAlways:
+        // TODO(devlin): Add more schemes here - blob, filesystem, etc.
+        return document_url.SchemeIs(url::kAboutScheme) ||
+               document_url.SchemeIs(url::kDataScheme);
+    }
+
+    NOTREACHED();
+  };
+
+  // If we don't need to consider the origin, we're done.
+  if (!should_consider_origin())
+    return document_url;
+
+  // Get the security origin for the `frame`. For about: frames, this is the
+  // origin of that of the controlling frame - e.g., an about:blank frame on
+  // https://example.com will have the security origin of https://example.com.
+  // Other frames, like data: frames, will have an opaque origin. For these,
+  // we can get the precursor origin.
+  const url::Origin frame_origin = frame.GetOrigin();
+  const url::SchemeHostPort& tuple_or_precursor_tuple =
+      frame_origin.GetTupleOrPrecursorTupleIfOpaque();
+
+  // When there's no valid tuple (which can happen in the case of e.g. a
+  // browser-initiated navigation to an opaque URL), there's no origin to
+  // fallback to. Bail.
+  if (!tuple_or_precursor_tuple.IsValid())
+    return document_url;
+
+  const url::Origin origin_or_precursor_origin =
+      url::Origin::Create(tuple_or_precursor_tuple.GetURL());
+
+  if (!allow_inaccessible_parents &&
+      !frame.CanAccess(origin_or_precursor_origin)) {
+    // The `frame` can't access its precursor. Bail.
+    return document_url;
+  }
+
+  // Note: Just because the frame origin can theoretically access its
+  // precursor origin, there may be more restrictions in practice - such as
+  // if the frame has the disallowdocumentaccess attribute. It's okay to
+  // ignore this case for context classification because it's not meant as an
+  // origin boundary (unlike e.g. a sandboxed frame).
+
+  // Looks like the initiator origin is an appropriate fallback!
+
+  if (match_origin_as_fallback == MatchOriginAsFallbackBehavior::kAlways) {
+    // The easy case! We use the origin directly. We're done.
+    return origin_or_precursor_origin.GetURL();
+  }
+
+  DCHECK_EQ(MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree,
+            match_origin_as_fallback);
+
+  // Unfortunately, in this case, we have to climb the frame tree. This is for
+  // match patterns that are associated with paths as well, not just origins.
+  // For instance, if an extension wants to run on google.com/maps/* with
+  // match_about_blank true, then it should run on about:-scheme frames created
+  // by google.com/maps, but not about:-scheme frames created by google.com
+  // (which is what the precursor tuple origin would be).
+
+  // Traverse the frame/window hierarchy to find the closest non-about:-page
+  // with the same origin as the precursor and return its URL.
+  // TODO(https://crbug.com/1186321): This can return the incorrect result, e.g.
+  // if a parent frame navigates a grandchild frame to about:blank.
+  std::unique_ptr<FrameAdapter> parent = frame.Clone();
+  GURL parent_url;
+  base::flat_set<uintptr_t> already_visited_frame_ids;
+  do {
+    already_visited_frame_ids.insert(parent->GetId());
+    parent = parent->GetLocalParentOrOpener();
+
+    // We reached the end of the ancestral chain without finding a valid parent,
+    // or found a remote web frame (in which case, it's a different origin).
+    // Bail and use the original URL.
+    if (!parent)
+      return document_url;
+
+    // Avoid an infinite loop - see https://crbug.com/568432 and
+    // https://crbug.com/883526.
+    if (base::Contains(already_visited_frame_ids, parent->GetId()))
+      return document_url;
+
+    url::SchemeHostPort parent_tuple_or_precursor_tuple =
+        url::Origin(parent->GetOrigin()).GetTupleOrPrecursorTupleIfOpaque();
+    if (!parent_tuple_or_precursor_tuple.IsValid() ||
+        parent_tuple_or_precursor_tuple != tuple_or_precursor_tuple) {
+      // The parent has a different tuple origin than frame; this could happen
+      // in edge cases where a parent navigates an iframe or popup of a child
+      // frame at a different origin. [1] In this case, bail, since we can't
+      // find a full URL (i.e., one including the path) with the same security
+      // origin to use for the frame in question.
+      // [1] Consider a frame tree like:
+      // <html> <!--example.com-->
+      //   <iframe id="a" src="a.com">
+      //     <iframe id="b" src="b.com"></iframe>
+      //   </iframe>
+      // </html>
+      // Frame "a" is cross-origin from the top-level frame, and so the
+      // example.com top-level frame can't directly access frame "b". However,
+      // it can navigate it through
+      // window.frames[0].frames[0].location.href = 'about:blank';
+      // In that case, the precursor origin tuple origin of frame "b" would be
+      // example.com, but the parent tuple origin is a.com.
+      // Note that usually, this would have bailed earlier with a remote frame,
+      // but it may not if we're at the process limit.
+      return document_url;
+    }
+
+    // If we don't allow inaccessible parents, the security origin may still
+    // be restricted if the author has prevented same-origin access via the
+    // disallowdocumentaccess attribute on iframe.
+    if (!allow_inaccessible_parents && !frame.CanAccess(*parent)) {
+      // The frame can't access its precursor. Bail.
+      return document_url;
+    }
+
+    parent_url = parent->GetUrl();
+  } while (parent_url.SchemeIs(url::kAboutScheme));
+
+  DCHECK(!parent_url.is_empty());
+
+  // We should know that the frame can access the parent document (unless we
+  // explicitly allow it not to), since it has the same tuple origin as the
+  // frame, and we checked the frame access above.
+  DCHECK(allow_inaccessible_parents || frame.CanAccess(parent->GetOrigin()));
+  return parent_url;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/content_script_injection_url_getter.h b/extensions/common/content_script_injection_url_getter.h
new file mode 100644
index 0000000..5a81cfb1
--- /dev/null
+++ b/extensions/common/content_script_injection_url_getter.h
@@ -0,0 +1,51 @@
+// 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 EXTENSIONS_COMMON_CONTENT_SCRIPT_INJECTION_URL_GETTER_H_
+#define EXTENSIONS_COMMON_CONTENT_SCRIPT_INJECTION_URL_GETTER_H_
+
+#include <memory>
+
+#include "extensions/common/script_constants.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace extensions {
+
+// A helper for deciding which URL to use for deciding whether to inject a
+// content script - it finds the effective document URL by (depending on content
+// script options) possibly looking at the parent-or-opener document instead,
+// looking at the precursor origin of data: documents, etc.
+//
+// TODO(https://crbug.com/1186321): Content script injection assumes that
+// about:blank inherits origin from the parent.  This can return the incorrect
+// result, e.g.  if a parent frame navigates a grandchild frame to about:blank.
+class ContentScriptInjectionUrlGetter {
+ public:
+  // Only static methods.
+  ContentScriptInjectionUrlGetter() = delete;
+
+  // Adapter abstracting away differences between RenderFrameHost and
+  // RenderFrame.
+  class FrameAdapter {
+   public:
+    virtual ~FrameAdapter();
+    virtual std::unique_ptr<FrameAdapter> Clone() const = 0;
+    virtual std::unique_ptr<FrameAdapter> GetLocalParentOrOpener() const = 0;
+    virtual GURL GetUrl() const = 0;
+    virtual url::Origin GetOrigin() const = 0;
+    virtual bool CanAccess(const url::Origin& target) const = 0;
+    virtual bool CanAccess(const FrameAdapter& target) const = 0;
+    virtual uintptr_t GetId() const = 0;
+  };
+
+  static GURL Get(const FrameAdapter& frame,
+                  const GURL& document_url,
+                  MatchOriginAsFallbackBehavior match_origin_as_fallback,
+                  bool allow_inaccessible_parents);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_CONTENT_SCRIPT_INJECTION_URL_GETTER_H_
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn
index 9d07ce1..c436d7a 100644
--- a/extensions/renderer/BUILD.gn
+++ b/extensions/renderer/BUILD.gn
@@ -318,6 +318,7 @@
   testonly = true
   sources = [
     "activity_log_converter_strategy_unittest.cc",
+    "api/automation/automation_internal_custom_bindings_unittests.cc",
     "api_activity_logger_unittest.cc",
     "bindings/api_binding_bridge_unittest.cc",
     "bindings/api_binding_hooks_test_delegate.cc",
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.h b/extensions/renderer/api/automation/automation_internal_custom_bindings.h
index a5d9054..148d96c 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.h
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.h
@@ -99,6 +99,8 @@
   void SendAccessibilityFocusedLocationChange(const gfx::Point& mouse_location);
 
  private:
+  friend class AutomationInternalCustomBindingsTest;
+
   // ObjectBackedNativeHandler overrides:
   void Invalidate() override;
 
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc
new file mode 100644
index 0000000..b4bc9ba
--- /dev/null
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc
@@ -0,0 +1,324 @@
+// 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 "extensions/renderer/api/automation/automation_internal_custom_bindings.h"
+
+#include "extensions/common/constants.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/features/feature_provider.h"
+#include "extensions/renderer/bindings/api_binding_test_util.h"
+#include "extensions/renderer/native_extension_bindings_system.h"
+#include "extensions/renderer/native_extension_bindings_system_test_base.h"
+#include "extensions/renderer/script_context.h"
+#include "ui/accessibility/ax_tree_id.h"
+
+namespace extensions {
+
+class AutomationInternalCustomBindingsTest
+    : public NativeExtensionBindingsSystemUnittest {
+ public:
+  void SetUp() override {
+    NativeExtensionBindingsSystemUnittest::SetUp();
+
+    // Bootstrap a simple extension with desktop automation permissions.
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("testExtension")
+            .SetManifestPath({"automation", "desktop"}, true)
+            .SetLocation(mojom::ManifestLocation::kComponent)
+            .Build();
+    RegisterExtension(extension);
+    v8::HandleScope handle_scope(isolate());
+    v8::Local<v8::Context> context = MainContext();
+    ScriptContext* script_context = CreateScriptContext(
+        context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
+    script_context->set_url(extension->url());
+    bindings_system()->UpdateBindingsForContext(script_context);
+
+    auto automation_internal_bindings =
+        std::make_unique<AutomationInternalCustomBindings>(script_context,
+                                                           bindings_system());
+    automation_internal_bindings_ = automation_internal_bindings.get();
+    script_context->module_system()->RegisterNativeHandler(
+        "automationInternal", std::move(automation_internal_bindings));
+
+    // Validate api access.
+    const Feature* automation_api =
+        FeatureProvider::GetAPIFeature("automation");
+    ASSERT_TRUE(automation_api);
+    Feature::Availability availability =
+        automation_api->IsAvailableToExtension(extension.get());
+    EXPECT_TRUE(availability.is_available()) << availability.message();
+  }
+
+  std::map<ui::AXTreeID, std::unique_ptr<AutomationAXTreeWrapper>>&
+  GetTreeIDToTreeMap() {
+    return automation_internal_bindings_->tree_id_to_tree_wrapper_map_;
+  }
+
+  void SendOnAccessibilityEvents(
+      const ExtensionMsg_AccessibilityEventBundleParams& event_bundle,
+      bool is_active_profile) {
+    automation_internal_bindings_->OnAccessibilityEvents(event_bundle,
+                                                         is_active_profile);
+  }
+
+  bool CallGetFocusInternal(AutomationAXTreeWrapper* top_wrapper,
+                            AutomationAXTreeWrapper** focused_wrapper,
+                            ui::AXNode** focused_node) {
+    return automation_internal_bindings_->GetFocusInternal(
+        top_wrapper, focused_wrapper, focused_node);
+  }
+
+ private:
+  AutomationInternalCustomBindings* automation_internal_bindings_ = nullptr;
+};
+
+TEST_F(AutomationInternalCustomBindingsTest, GetDesktop) {
+  EXPECT_TRUE(GetTreeIDToTreeMap().empty());
+
+  // A desktop tree.
+  ExtensionMsg_AccessibilityEventBundleParams bundle;
+  bundle.updates.emplace_back();
+  auto& tree_update = bundle.updates.back();
+  tree_update.nodes.emplace_back();
+  auto& node_data = tree_update.nodes.back();
+  node_data.role = ax::mojom::Role::kDesktop;
+  SendOnAccessibilityEvents(bundle, true /* active profile */);
+
+  ASSERT_EQ(1U, GetTreeIDToTreeMap().size());
+
+  AutomationAXTreeWrapper* desktop = GetTreeIDToTreeMap().begin()->second.get();
+  ASSERT_TRUE(desktop);
+  EXPECT_TRUE(desktop->IsDesktopTree());
+}
+
+TEST_F(AutomationInternalCustomBindingsTest, GetFocusOneTree) {
+  // A desktop tree with focus on a button.
+  ExtensionMsg_AccessibilityEventBundleParams bundle;
+  bundle.updates.emplace_back();
+  auto& tree_update = bundle.updates.back();
+  tree_update.has_tree_data = true;
+  tree_update.root_id = 1;
+  auto& tree_data = tree_update.tree_data;
+  tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+  tree_data.focus_id = 2;
+  tree_update.nodes.emplace_back();
+  auto& node_data1 = tree_update.nodes.back();
+  node_data1.id = 1;
+  node_data1.role = ax::mojom::Role::kDesktop;
+  node_data1.child_ids.push_back(2);
+  tree_update.nodes.emplace_back();
+  auto& node_data2 = tree_update.nodes.back();
+  node_data2.id = 2;
+  node_data2.role = ax::mojom::Role::kButton;
+  SendOnAccessibilityEvents(bundle, true /* active profile */);
+
+  ASSERT_EQ(1U, GetTreeIDToTreeMap().size());
+
+  AutomationAXTreeWrapper* desktop = GetTreeIDToTreeMap().begin()->second.get();
+  ASSERT_TRUE(desktop);
+
+  AutomationAXTreeWrapper* focused_wrapper = nullptr;
+  ui::AXNode* focused_node = nullptr;
+  CallGetFocusInternal(desktop, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(desktop, focused_wrapper);
+  EXPECT_EQ(ax::mojom::Role::kButton, focused_node->data().role);
+
+  // Push an update where we change the focus.
+  focused_wrapper = nullptr;
+  focused_node = nullptr;
+  tree_data.focus_id = 1;
+  SendOnAccessibilityEvents(bundle, true /* active profile */);
+  CallGetFocusInternal(desktop, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(desktop, focused_wrapper);
+  EXPECT_EQ(ax::mojom::Role::kDesktop, focused_node->data().role);
+
+  // Push an update where we change the focus to nothing.
+  focused_wrapper = nullptr;
+  focused_node = nullptr;
+  tree_data.focus_id = 100;
+  SendOnAccessibilityEvents(bundle, true /* active profile */);
+  CallGetFocusInternal(desktop, &focused_wrapper, &focused_node);
+  ASSERT_FALSE(focused_wrapper);
+  ASSERT_FALSE(focused_node);
+}
+
+TEST_F(AutomationInternalCustomBindingsTest,
+       GetFocusMultipleTreesChildTreeConstruction) {
+  // Three trees each with a button and link.
+  std::vector<ExtensionMsg_AccessibilityEventBundleParams> bundles;
+  for (int i = 0; i < 3; i++) {
+    bundles.emplace_back();
+    auto& bundle = bundles.back();
+    bundle.updates.emplace_back();
+    auto& tree_update = bundle.updates.back();
+    tree_update.has_tree_data = true;
+    tree_update.root_id = 1;
+    auto& tree_data = tree_update.tree_data;
+
+    // This is a point of inconsistency as the mojo representation allows
+    // updates from multiple trees.
+    tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+    bundle.tree_id = tree_data.tree_id;
+    tree_data.focus_id = 2;
+    tree_update.nodes.emplace_back();
+    auto& node_data1 = tree_update.nodes.back();
+    node_data1.id = 1;
+    node_data1.role = ax::mojom::Role::kRootWebArea;
+    node_data1.child_ids.push_back(2);
+    node_data1.child_ids.push_back(3);
+    tree_update.nodes.emplace_back();
+    auto& node_data2 = tree_update.nodes.back();
+    node_data2.id = 2;
+    node_data2.role = ax::mojom::Role::kButton;
+    tree_update.nodes.emplace_back();
+    auto& node_data3 = tree_update.nodes.back();
+    node_data3.id = 3;
+    node_data3.role = ax::mojom::Role::kLink;
+  }
+
+  // Link up the trees so that the first is a parent of the other two using
+  // child tree id.
+  ui::AXTreeID tree_0_id = bundles[0].updates[0].tree_data.tree_id;
+  ui::AXTreeID tree_1_id = bundles[1].updates[0].tree_data.tree_id;
+  ui::AXTreeID tree_2_id = bundles[2].updates[0].tree_data.tree_id;
+  bundles[0].updates[0].nodes[1].AddChildTreeId(tree_1_id);
+  bundles[0].updates[0].nodes[2].AddChildTreeId(tree_2_id);
+
+  for (auto& bundle : bundles)
+    SendOnAccessibilityEvents(bundle, true /* active profile */);
+
+  ASSERT_EQ(3U, GetTreeIDToTreeMap().size());
+
+  AutomationAXTreeWrapper* wrapper_0 = GetTreeIDToTreeMap()[tree_0_id].get();
+  ASSERT_TRUE(wrapper_0);
+  AutomationAXTreeWrapper* wrapper_1 = GetTreeIDToTreeMap()[tree_1_id].get();
+  ASSERT_TRUE(wrapper_1);
+  AutomationAXTreeWrapper* wrapper_2 = GetTreeIDToTreeMap()[tree_2_id].get();
+  ASSERT_TRUE(wrapper_2);
+
+  AutomationAXTreeWrapper* focused_wrapper = nullptr;
+  ui::AXNode* focused_node = nullptr;
+  CallGetFocusInternal(wrapper_0, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(wrapper_1, focused_wrapper);
+  EXPECT_EQ(tree_1_id, focused_node->tree()->GetAXTreeID());
+  EXPECT_EQ(ax::mojom::Role::kButton, focused_node->data().role);
+
+  // Push an update where we change the focus.
+  focused_wrapper = nullptr;
+  focused_node = nullptr;
+
+  // The link in wrapper 0 which has a child tree id pointing to wrapper 2.
+  bundles[0].updates[0].tree_data.focus_id = 3;
+  SendOnAccessibilityEvents(bundles[0], true /* active profile */);
+  CallGetFocusInternal(wrapper_0, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(wrapper_2, focused_wrapper);
+  EXPECT_EQ(tree_2_id, focused_node->tree()->GetAXTreeID());
+  EXPECT_EQ(ax::mojom::Role::kButton, focused_node->data().role);
+}
+
+TEST_F(AutomationInternalCustomBindingsTest,
+       GetFocusMultipleTreesAppIdConstruction) {
+  // Three trees each with a button and link.
+  std::vector<ExtensionMsg_AccessibilityEventBundleParams> bundles;
+  for (int i = 0; i < 3; i++) {
+    bundles.emplace_back();
+    auto& bundle = bundles.back();
+    bundle.updates.emplace_back();
+    auto& tree_update = bundle.updates.back();
+    tree_update.has_tree_data = true;
+    tree_update.root_id = 1;
+    auto& tree_data = tree_update.tree_data;
+
+    // This is a point of inconsistency as the mojo representation allows
+    // updates from ultiple trees.
+    tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
+    bundle.tree_id = tree_data.tree_id;
+    tree_data.focus_id = 2;
+    tree_update.nodes.emplace_back();
+    auto& node_data1 = tree_update.nodes.back();
+    node_data1.id = 1;
+    node_data1.role = ax::mojom::Role::kRootWebArea;
+    node_data1.child_ids.push_back(2);
+    node_data1.child_ids.push_back(3);
+    tree_update.nodes.emplace_back();
+    auto& node_data2 = tree_update.nodes.back();
+    node_data2.id = 2;
+    node_data2.role = ax::mojom::Role::kButton;
+    tree_update.nodes.emplace_back();
+    auto& node_data3 = tree_update.nodes.back();
+    node_data3.id = 3;
+    node_data3.role = ax::mojom::Role::kLink;
+  }
+
+  // Link up the trees so that the first is a parent of the other two using app
+  // ids.
+  ui::AXTreeID tree_0_id = bundles[0].updates[0].tree_data.tree_id;
+  ui::AXTreeID tree_1_id = bundles[1].updates[0].tree_data.tree_id;
+  ui::AXTreeID tree_2_id = bundles[2].updates[0].tree_data.tree_id;
+  auto& wrapper0_button_data = bundles[0].updates[0].nodes[1];
+  auto& wrapper0_link_data = bundles[0].updates[0].nodes[2];
+  auto& wrapper1_link_data = bundles[1].updates[0].nodes[2];
+  auto& wrapper2_button_data = bundles[2].updates[0].nodes[1];
+
+  // This construction requires the hosting and client nodes annotate with the
+  // same app id.
+  wrapper0_button_data.AddStringAttribute(
+      ax::mojom::StringAttribute::kChildTreeNodeAppId, "app1");
+  wrapper1_link_data.AddStringAttribute(
+      ax::mojom::StringAttribute::kParentTreeNodeAppId, "app1");
+  wrapper0_link_data.AddStringAttribute(
+      ax::mojom::StringAttribute::kChildTreeNodeAppId, "app2");
+  wrapper2_button_data.AddStringAttribute(
+      ax::mojom::StringAttribute::kParentTreeNodeAppId, "app2");
+
+  for (auto& bundle : bundles)
+    SendOnAccessibilityEvents(bundle, true /* active profile */);
+
+  ASSERT_EQ(3U, GetTreeIDToTreeMap().size());
+
+  AutomationAXTreeWrapper* wrapper_0 = GetTreeIDToTreeMap()[tree_0_id].get();
+  ASSERT_TRUE(wrapper_0);
+  AutomationAXTreeWrapper* wrapper_1 = GetTreeIDToTreeMap()[tree_1_id].get();
+  ASSERT_TRUE(wrapper_1);
+  AutomationAXTreeWrapper* wrapper_2 = GetTreeIDToTreeMap()[tree_2_id].get();
+  ASSERT_TRUE(wrapper_2);
+
+  AutomationAXTreeWrapper* focused_wrapper = nullptr;
+  ui::AXNode* focused_node = nullptr;
+  CallGetFocusInternal(wrapper_0, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(wrapper_1, focused_wrapper);
+  EXPECT_EQ(tree_1_id, focused_node->tree()->GetAXTreeID());
+
+  // This is an interesting inconsistency as this node is technically not in the
+  // app (which starts at the link in wrapper 1).
+  EXPECT_EQ(ax::mojom::Role::kButton, focused_node->data().role);
+
+  // Push an update where we change the focus.
+  focused_wrapper = nullptr;
+  focused_node = nullptr;
+
+  // The link in wrapper 0 which has a child tree id pointing to wrapper 2.
+  bundles[0].updates[0].tree_data.focus_id = 3;
+  SendOnAccessibilityEvents(bundles[0], true /* active profile */);
+  CallGetFocusInternal(wrapper_0, &focused_wrapper, &focused_node);
+  ASSERT_TRUE(focused_wrapper);
+  ASSERT_TRUE(focused_node);
+  EXPECT_EQ(wrapper_2, focused_wrapper);
+  EXPECT_EQ(tree_2_id, focused_node->tree()->GetAXTreeID());
+  EXPECT_EQ(ax::mojom::Role::kButton, focused_node->data().role);
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc
index 76c4442..d44ac6a 100644
--- a/extensions/renderer/script_context.cc
+++ b/extensions/renderer/script_context.cc
@@ -15,6 +15,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/render_frame.h"
 #include "extensions/common/constants.h"
+#include "extensions/common/content_script_injection_url_getter.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_urls.h"
@@ -33,158 +34,73 @@
 
 namespace {
 
+class WebLocalFrameAdapter
+    : public ContentScriptInjectionUrlGetter::FrameAdapter {
+ public:
+  explicit WebLocalFrameAdapter(const blink::WebLocalFrame* frame)
+      : frame_(frame) {}
+
+  ~WebLocalFrameAdapter() override = default;
+
+  std::unique_ptr<FrameAdapter> Clone() const override {
+    return std::make_unique<WebLocalFrameAdapter>(frame_);
+  }
+
+  std::unique_ptr<FrameAdapter> GetLocalParentOrOpener() const override {
+    blink::WebFrame* parent_or_opener = nullptr;
+    if (frame_->Parent())
+      parent_or_opener = frame_->Parent();
+    else
+      parent_or_opener = frame_->Opener();
+    if (!parent_or_opener || !parent_or_opener->IsWebLocalFrame())
+      return nullptr;
+
+    blink::WebLocalFrame* local_parent_or_opener =
+        parent_or_opener->ToWebLocalFrame();
+    if (local_parent_or_opener->GetDocument().IsNull())
+      return nullptr;
+
+    return std::make_unique<WebLocalFrameAdapter>(local_parent_or_opener);
+  }
+
+  GURL GetUrl() const override { return frame_->GetDocument().Url(); }
+
+  url::Origin GetOrigin() const override { return frame_->GetSecurityOrigin(); }
+
+  bool CanAccess(const url::Origin& target) const override {
+    return frame_->GetSecurityOrigin().CanAccess(target);
+  }
+
+  bool CanAccess(const FrameAdapter& target) const override {
+    // It is important that below `web_security_origin` wraps the security
+    // origin of the `target_frame` (rather than a new origin created via
+    // url::Origin round-trip - such an origin wouldn't be 100% equivalent -
+    // e.g. `disallowdocumentaccess` information might be lost).  FWIW, this
+    // scenario is execised by ScriptContextTest.GetEffectiveDocumentURL.
+    const blink::WebLocalFrame* target_frame =
+        static_cast<const WebLocalFrameAdapter&>(target).frame_;
+    blink::WebSecurityOrigin web_security_origin =
+        target_frame->GetDocument().GetSecurityOrigin();
+
+    return frame_->GetSecurityOrigin().CanAccess(web_security_origin);
+  }
+
+  uintptr_t GetId() const override {
+    return reinterpret_cast<uintptr_t>(frame_);
+  }
+
+ private:
+  const blink::WebLocalFrame* const frame_;
+};
+
 GURL GetEffectiveDocumentURL(
     blink::WebLocalFrame* frame,
     const GURL& document_url,
     MatchOriginAsFallbackBehavior match_origin_as_fallback,
     bool allow_inaccessible_parents) {
-  auto should_consider_origin = [document_url, match_origin_as_fallback]() {
-    switch (match_origin_as_fallback) {
-      case MatchOriginAsFallbackBehavior::kNever:
-        return false;
-      case MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree:
-        return document_url.SchemeIs(url::kAboutScheme);
-      case MatchOriginAsFallbackBehavior::kAlways:
-        // TODO(devlin): Add more schemes here - blob, filesystem, etc.
-        return document_url.SchemeIs(url::kAboutScheme) ||
-               document_url.SchemeIs(url::kDataScheme);
-    }
-
-    NOTREACHED();
-  };
-
-  // If we don't need to consider the origin, we're done.
-  if (!should_consider_origin())
-    return document_url;
-
-  // Get the "security origin" for the frame. For about: frames, this is the
-  // origin of that of the controlling frame - e.g., an about:blank frame on
-  // https://example.com will have the security origin of https://example.com.
-  // Other frames, like data: frames, will have an opaque origin. For these,
-  // we can get the precursor origin.
-  const blink::WebSecurityOrigin web_frame_origin = frame->GetSecurityOrigin();
-  const url::Origin frame_origin = web_frame_origin;
-  const url::SchemeHostPort& tuple_or_precursor_tuple =
-      frame_origin.GetTupleOrPrecursorTupleIfOpaque();
-
-  // When there's no valid tuple (which can happen in the case of e.g. a
-  // browser-initiated navigation to an opaque URL), there's no origin to
-  // fallback to. Bail.
-  if (!tuple_or_precursor_tuple.IsValid())
-    return document_url;
-
-  const url::Origin origin_or_precursor_origin =
-      url::Origin::Create(tuple_or_precursor_tuple.GetURL());
-
-  if (!allow_inaccessible_parents &&
-      !web_frame_origin.CanAccess(
-          blink::WebSecurityOrigin(origin_or_precursor_origin))) {
-    // The frame can't access its precursor. Bail.
-    return document_url;
-  }
-
-  // Note: Just because the frame origin can theoretically access its
-  // precursor origin, there may be more restrictions in practice - such as
-  // if the frame has the disallowdocumentaccess attribute. It's okay to
-  // ignore this case for context classification because it's not meant as an
-  // origin boundary (unlike e.g. a sandboxed frame).
-
-  // Looks like the initiator origin is an appropriate fallback!
-
-  if (match_origin_as_fallback == MatchOriginAsFallbackBehavior::kAlways) {
-    // The easy case! We use the origin directly. We're done.
-    return origin_or_precursor_origin.GetURL();
-  }
-
-  DCHECK_EQ(MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree,
-            match_origin_as_fallback);
-
-  // Unfortunately, in this case, we have to climb the frame tree. This is for
-  // match patterns that are associated with paths as well, not just origins.
-  // For instance, if an extension wants to run on google.com/maps/* with
-  // match_about_blank true, then it should run on about:-scheme frames created
-  // by google.com/maps, but not about:-scheme frames created by google.com
-  // (which is what the precursor tuple origin would be).
-
-  // Traverse the frame/window hierarchy to find the closest non-about:-page
-  // with the same origin as the precursor and return its URL.
-  // TODO(https://crbug.com/1186321): This can return the incorrect result, e.g.
-  // if a parent frame navigates a grandchild frame to about:blank.
-  blink::WebFrame* parent = frame;
-  GURL parent_url;
-  blink::WebDocument parent_document;
-  base::flat_set<blink::WebFrame*> already_visited_frames;
-  do {
-    already_visited_frames.insert(parent);
-    if (parent->Parent())
-      parent = parent->Parent();
-    else
-      parent = parent->Opener();
-
-    // Avoid an infinite loop - see https://crbug.com/568432 and
-    // https://crbug.com/883526.
-    if (base::Contains(already_visited_frames, parent))
-      return document_url;
-
-    parent_document = parent && parent->IsWebLocalFrame()
-                          ? parent->ToWebLocalFrame()->GetDocument()
-                          : blink::WebDocument();
-
-    // We reached the end of the ancestral chain without finding a valid parent,
-    // or found a remote web frame (in which case, it's a different origin).
-    // Bail and use the original URL.
-    if (parent_document.IsNull())
-      return document_url;
-
-    url::SchemeHostPort parent_tuple_or_precursor_tuple =
-        url::Origin(parent->GetSecurityOrigin())
-            .GetTupleOrPrecursorTupleIfOpaque();
-    if (!parent_tuple_or_precursor_tuple.IsValid() ||
-        parent_tuple_or_precursor_tuple != tuple_or_precursor_tuple) {
-      // The parent has a different tuple origin than frame; this could happen
-      // in edge cases where a parent navigates an iframe or popup of a child
-      // frame at a different origin. [1] In this case, bail, since we can't
-      // find a full URL (i.e., one including the path) with the same security
-      // origin to use for the frame in question.
-      // [1] Consider a frame tree like:
-      // <html> <!--example.com-->
-      //   <iframe id="a" src="a.com">
-      //     <iframe id="b" src="b.com"></iframe>
-      //   </iframe>
-      // </html>
-      // Frame "a" is cross-origin from the top-level frame, and so the
-      // example.com top-level frame can't directly access frame "b". However,
-      // it can navigate it through
-      // window.frames[0].frames[0].location.href = 'about:blank';
-      // In that case, the precursor origin tuple origin of frame "b" would be
-      // example.com, but the parent tuple origin is a.com.
-      // Note that usually, this would have bailed earlier with a remote frame,
-      // but it may not if we're at the process limit.
-      return document_url;
-    }
-
-    // If we don't allow inaccessible parents, the security origin may still
-    // be restricted if the author has prevented same-origin access via the
-    // disallowdocumentaccess attribute on iframe.
-    if (!allow_inaccessible_parents &&
-        !web_frame_origin.CanAccess(
-            blink::WebSecurityOrigin(parent_document.GetSecurityOrigin()))) {
-      // The frame can't access its precursor. Bail.
-      return document_url;
-    }
-
-    parent_url = GURL(parent_document.Url());
-  } while (parent_url.SchemeIs(url::kAboutScheme));
-
-  DCHECK(!parent_url.is_empty());
-  DCHECK(!parent_document.IsNull());
-
-  // We should know that the frame can access the parent document (unless we
-  // explicitly allow it not to), since it has the same tuple origin as the
-  // frame, and we checked the frame access above.
-  DCHECK(allow_inaccessible_parents ||
-         web_frame_origin.CanAccess(parent_document.GetSecurityOrigin()));
-  return parent_url;
+  return ContentScriptInjectionUrlGetter::Get(
+      WebLocalFrameAdapter(frame), document_url, match_origin_as_fallback,
+      allow_inaccessible_parents);
 }
 
 std::string GetContextTypeDescriptionString(Feature::Context context_type) {
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index b952b79..7cb6715 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -72,7 +72,6 @@
   void SetCursor(gfx::NativeCursor cursor,
                  wm::NativeCursorManagerDelegate* delegate) override {
     cursor_loader_.SetPlatformCursor(&cursor);
-    cursor.set_image_scale_factor(cursor_loader_.scale());
     delegate->CommitCursor(cursor);
 
     if (delegate->IsCursorVisible())
diff --git a/fuchsia/engine/browser/virtual_keyboard_browsertest.cc b/fuchsia/engine/browser/virtual_keyboard_browsertest.cc
index 6c646f95..8e6b8c1b 100644
--- a/fuchsia/engine/browser/virtual_keyboard_browsertest.cc
+++ b/fuchsia/engine/browser/virtual_keyboard_browsertest.cc
@@ -242,67 +242,40 @@
   fuchsia::ui::views::ViewRef view_ref_;
 };
 
-// Verifies that RequestShow() is invoked multiple times if the virtual
-// keyboard service does not indicate that the keyboard is made visible.
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, ShowAndHideCalledButIgnored) {
-  testing::InSequence s;
-  EXPECT_CALL(*controller_, RequestShow()).Times(2);
-  EXPECT_CALL(*controller_, RequestHide());
-  base::RunLoop run_loop;
-  EXPECT_CALL(*controller_, RequestShow())
-      .WillOnce(testing::InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-
-  // Tap inside the text field. The IME should be summoned via a call to
-  // RequestShow().
-  content::SimulateTapAt(web_contents_,
-                         GetCoordinatesOfInputField(kInputFieldText));
-
-  // Change fields. RequestShow() should be called again, since the keyboard
-  // is not yet known to be visible.
-  content::SimulateTapAt(web_contents_,
-                         GetCoordinatesOfInputField(kInputFieldNumeric));
-
-  // Tap outside the text field. The IME should be dismissed, which will result
-  // in a call to RequestHide().
-  content::SimulateTapAt(web_contents_, kNoTarget);
-
-  // Tap back on a text field. RequestShow should be called.
-  content::SimulateTapAt(web_contents_,
-                         GetCoordinatesOfInputField(kInputFieldText));
-  run_loop.Run();
-}
-
 // Verifies that RequestShow() is not called redundantly if the virtual
 // keyboard is reported as visible.
 IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, ShowAndHideWithVisibility) {
   testing::InSequence s;
-  base::RunLoop on_show_run_loop;
-  EXPECT_CALL(*controller_,
-              SetTextType(virtualkeyboard::TextType::ALPHANUMERIC));
-  EXPECT_CALL(*controller_, RequestShow())
-      .WillOnce(testing::InvokeWithoutArgs(
-          [&on_show_run_loop]() { on_show_run_loop.Quit(); }));
-  EXPECT_CALL(*controller_, SetTextType(virtualkeyboard::TextType::NUMERIC));
-  base::RunLoop on_hide_run_loop;
-  EXPECT_CALL(*controller_, RequestHide())
-      .WillOnce(testing::InvokeWithoutArgs(
-          [&on_hide_run_loop]() { on_hide_run_loop.Quit(); }));
 
   // Give focus to an input field, which will result in RequestShow() being
   // called.
+  base::RunLoop on_show_run_loop;
+  EXPECT_CALL(*controller_, RequestShow())
+      .WillOnce(testing::InvokeWithoutArgs(
+          [&on_show_run_loop]() { on_show_run_loop.Quit(); }))
+      .RetiresOnSaturation();
   content::SimulateTapAt(web_contents_,
                          GetCoordinatesOfInputField(kInputFieldText));
   on_show_run_loop.Run();
+  EXPECT_EQ(controller_->text_type(), virtualkeyboard::TextType::ALPHANUMERIC);
 
   // Indicate that the virtual keyboard is now visible.
   controller_->AwaitWatchAndRespondWith(true);
+  base::RunLoop().RunUntilIdle();
 
   // Tap on another text field. RequestShow should not be called a second time
   // since the keyboard is already onscreen.
+  EXPECT_CALL(*controller_, RequestHide()).RetiresOnSaturation();
+  EXPECT_CALL(*controller_, SetTextType(virtualkeyboard::TextType::NUMERIC));
+  EXPECT_CALL(*controller_, RequestShow()).RetiresOnSaturation();
   content::SimulateTapAt(web_contents_,
                          GetCoordinatesOfInputField(kInputFieldNumeric));
   base::RunLoop().RunUntilIdle();
 
+  base::RunLoop on_hide_run_loop;
+  EXPECT_CALL(*controller_, RequestHide())
+      .WillOnce(testing::InvokeWithoutArgs(
+          [&on_hide_run_loop]() { on_hide_run_loop.Quit(); }));
   content::SimulateTapAt(web_contents_, kNoTarget);
   on_hide_run_loop.Run();
 }
@@ -310,47 +283,49 @@
 // Gives focus to a sequence of HTML <input> nodes with different InputModes,
 // and verifies that the InputMode's FIDL equivalent is sent via SetTextType().
 IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, InputModeMappings) {
+  // Note that the service will elide type updates if there is no change,
+  // so the array is ordered to produce an update on each entry.
   const std::vector<std::pair<base::StringPiece, virtualkeyboard::TextType>>
       kInputTypeMappings = {
-          {kInputFieldText, virtualkeyboard::TextType::ALPHANUMERIC},
           {kInputFieldTel, virtualkeyboard::TextType::PHONE},
+          {kInputFieldSearch, virtualkeyboard::TextType::ALPHANUMERIC},
           {kInputFieldNumeric, virtualkeyboard::TextType::NUMERIC},
           {kInputFieldUrl, virtualkeyboard::TextType::ALPHANUMERIC},
-          {kInputFieldEmail, virtualkeyboard::TextType::ALPHANUMERIC},
           {kInputFieldDecimal, virtualkeyboard::TextType::NUMERIC},
-          {kInputFieldSearch, virtualkeyboard::TextType::ALPHANUMERIC},
+          {kInputFieldEmail, virtualkeyboard::TextType::ALPHANUMERIC},
       };
 
-  // Simulate like the keyboard is already shown, so that the test can focus on
-  // input type mappings without clutter from visibility management.
-  controller_->AwaitWatchAndRespondWith(true);
-  base::RunLoop().RunUntilIdle();
+  controller_->AwaitWatchAndRespondWith(false);
+
+  testing::InSequence s;
 
   // GMock expectations must be set upfront, hence the redundant for-each loop.
-  for (const auto& field_type_pair : kInputTypeMappings) {
+  virtualkeyboard::TextType previous_text_type =
+      virtualkeyboard::TextType::ALPHANUMERIC;
+  std::vector<base::RunLoop> set_type_loops(base::size(kInputTypeMappings));
+  for (size_t i = 0; i < base::size(kInputTypeMappings); ++i) {
+    const auto& field_type_pair = kInputTypeMappings[i];
+    DCHECK_NE(field_type_pair.second, previous_text_type);
+
     EXPECT_CALL(*controller_, SetTextType(field_type_pair.second))
+        .WillOnce(testing::InvokeWithoutArgs(
+            [run_loop = &set_type_loops[i]]() mutable { run_loop->Quit(); }))
         .RetiresOnSaturation();
+    previous_text_type = field_type_pair.second;
   }
 
-  base::RunLoop run_loop;
-  EXPECT_CALL(*controller_, RequestHide())
-      .WillOnce(testing::InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
+  for (size_t i = 0; i < base::size(kInputTypeMappings); ++i) {
+    content::SimulateTapAt(
+        web_contents_, GetCoordinatesOfInputField(kInputTypeMappings[i].first));
 
-  for (const auto& field_type_pair : kInputTypeMappings) {
-    content::SimulateTapAt(web_contents_,
-                           GetCoordinatesOfInputField(field_type_pair.first));
+    // Spin the runloop until we've received the type update.
+    set_type_loops[i].Run();
   }
-
-  // Dismiss the virtual keyboard and wait for RequestHide().
-  content::SimulateTapAt(web_contents_, kNoTarget);
-  run_loop.Run();
 }
 
 IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, Disconnection) {
   testing::InSequence s;
   base::RunLoop on_show_run_loop;
-  EXPECT_CALL(*controller_,
-              SetTextType(virtualkeyboard::TextType::ALPHANUMERIC));
   EXPECT_CALL(*controller_, RequestShow())
       .WillOnce(testing::InvokeWithoutArgs(
           [&on_show_run_loop]() { on_show_run_loop.Quit(); }));
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index af2816e..405a6da 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3619,18 +3619,6 @@
       ]
     },
     {
-      "id": 368,
-      "cr_bugs": [1181358],
-      "description": "High D3D11VideoDecoder error rates for AV1 content on Intel GPUs",
-      "os": {
-        "type": "win"
-      },
-      "vendor_id": "0x8086",
-      "features": [
-        "disable_accelerated_av1_decode_d3d11"
-      ]
-    },
-    {
       "id": 369,
       "cr_bugs": [1184340],
       "description": "Limit MSAA quality samples to 4 and storage samples 2 on Pollock",
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index db17827..137c5d8 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -97,8 +97,7 @@
   output = "$root_out_dir/headless_lib.pak"
 }
 
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action("embed_resources") {
+action("embed_resources") {
   # TODO(altimin): Consider zipping file here, it can reduce size up to 80%.
   script = "lib/embed_data.py"
 
@@ -530,7 +529,7 @@
   }
 
   if (headless_use_embedded_resources) {
-    defines = [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
+    defines += [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
     deps += [ ":embed_resources" ]
     sources += [
       "$root_gen_dir/headless/embedded_resource_pak.cc",
@@ -577,10 +576,6 @@
       sources += [ "lib/headless_content_main_delegate_mac.mm" ]
     }
 
-    if (headless_use_embedded_resources) {
-      defines += [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
-    }
-
     if (enable_basic_printing) {
       sources += [
         "lib/renderer/headless_print_render_frame_helper_delegate.cc",
@@ -603,6 +598,14 @@
       ]
     }
     configs += [ ":headless_policy_config" ]
+    if (headless_use_embedded_resources) {
+      defines += [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
+      deps += [ ":embed_resources" ]
+      sources += [
+        "$root_gen_dir/headless/embedded_resource_pak.cc",
+        "$root_gen_dir/headless/embedded_resource_pak.h",
+      ]
+    }
   }
 } else {
   # For component builds all dependencies are already included in the headless
diff --git a/headless/app/headless_shell_switches.cc b/headless/app/headless_shell_switches.cc
index d67b470a..5229318d 100644
--- a/headless/app/headless_shell_switches.cc
+++ b/headless/app/headless_shell_switches.cc
@@ -124,7 +124,8 @@
 const char kWindowSize[] = "window-size";
 
 // Allowlist for Negotiate Auth servers.
-const char kAuthServerAllowlist[] = "auth-server-whitelist";
+const char kAuthServerAllowlist[] = "auth-server-allowlist";
+const char kAuthServerAllowlistDeprecated[] = "auth-server-whitelist";
 
 // Sets font render hinting when running headless, affects Skia rendering and
 // whether glyph subpixel positioning is enabled.
diff --git a/headless/app/headless_shell_switches.h b/headless/app/headless_shell_switches.h
index 3011369..d10b842 100644
--- a/headless/app/headless_shell_switches.h
+++ b/headless/app/headless_shell_switches.h
@@ -39,6 +39,7 @@
 HEADLESS_EXPORT extern const char kVirtualTimeBudget[];
 HEADLESS_EXPORT extern const char kWindowSize[];
 HEADLESS_EXPORT extern const char kAuthServerAllowlist[];
+HEADLESS_EXPORT extern const char kAuthServerAllowlistDeprecated[];
 HEADLESS_EXPORT extern const char kFontRenderHinting[];
 HEADLESS_EXPORT extern const char kBlockNewWebContents[];
 
diff --git a/headless/lib/browser/headless_request_context_manager.cc b/headless/lib/browser/headless_request_context_manager.cc
index 4ac0070..3b54e857 100644
--- a/headless/lib/browser/headless_request_context_manager.cc
+++ b/headless/lib/browser/headless_request_context_manager.cc
@@ -5,6 +5,7 @@
 #include "headless/lib/browser/headless_request_context_manager.h"
 
 #include "base/bind.h"
+#include "base/logging.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -186,8 +187,22 @@
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   auto auth_params = ::network::mojom::HttpAuthDynamicParams::New();
-  auth_params->server_allowlist =
-      command_line->GetSwitchValueASCII(switches::kAuthServerAllowlist);
+
+  // Support both current and deprecated switches for now, with the current
+  // switch value overriding the deprecated one. Expect the deprecated switch
+  // support to be removed soon, see crbug/1142696.
+  if (command_line->HasSwitch(switches::kAuthServerAllowlist)) {
+    auth_params->server_allowlist =
+        command_line->GetSwitchValueASCII(switches::kAuthServerAllowlist);
+  } else if (command_line->HasSwitch(
+                 switches::kAuthServerAllowlistDeprecated)) {
+    LOG(ERROR) << "'" << switches::kAuthServerAllowlistDeprecated
+               << "' is deprecated and will be removed soon. Please use '"
+               << switches::kAuthServerAllowlist << "' instead.";
+    auth_params->server_allowlist = command_line->GetSwitchValueASCII(
+        switches::kAuthServerAllowlistDeprecated);
+  }
+
   auto* network_service = content::GetNetworkService();
   network_service->ConfigureHttpAuthPrefs(std::move(auth_params));
 
diff --git a/headless/lib/embed_data.py b/headless/lib/embed_data.py
index 57ab268..737fe36 100644
--- a/headless/lib/embed_data.py
+++ b/headless/lib/embed_data.py
@@ -55,7 +55,7 @@
   with open(filepath, 'rb') as f:
     contents = f.read()
 
-  contents = [ str(ord(char)) for char in contents ]
+  contents = [ str(byte) for byte in bytearray(contents) ]
 
   return len(contents), '{' + ','.join(contents) + '}'
 
diff --git a/headless/test/data/protocol/input/input-clipboard-ops-expected.txt b/headless/test/data/protocol/input/input-clipboard-ops-expected.txt
new file mode 100644
index 0000000..79fdbfc
--- /dev/null
+++ b/headless/test/data/protocol/input/input-clipboard-ops-expected.txt
@@ -0,0 +1,4 @@
+Tests input field clipboard operations.
+input: input_value
+input: abc
+input: input_value
\ No newline at end of file
diff --git a/headless/test/data/protocol/input/input-clipboard-ops.js b/headless/test/data/protocol/input/input-clipboard-ops.js
new file mode 100644
index 0000000..6710e6f
--- /dev/null
+++ b/headless/test/data/protocol/input/input-clipboard-ops.js
@@ -0,0 +1,52 @@
+// 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.
+
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Tests input field clipboard operations.`);
+
+  await dp.Page.enable();
+  dp.Page.navigate({url: testRunner.url('/resources/input.html')});
+  await dp.Page.onceLoadEventFired();
+
+  async function logElementValue(id) {
+    const value = await session.evaluate(`
+      document.getElementById("${id}").value;
+    `);
+    testRunner.log(`${id}: ${value}`);
+  }
+
+  async function sendKey(text, nativeVirtualKeyCode,
+      modifiers = 0, commands = []) {
+    await dp.Input.dispatchKeyEvent({
+      type: 'keyDown',
+      modifiers: modifiers,
+      text: text,
+      nativeVirtualKeyCode: nativeVirtualKeyCode,
+      commands: commands
+    });
+
+    await dp.Input.dispatchKeyEvent({
+      type: 'keyUp',
+      modifiers: modifiers,
+      nativeVirtualKeyCode: nativeVirtualKeyCode
+    });
+  }
+
+  await logElementValue("input");
+  await sendKey('a', 65, 2, ["selectAll"]);
+  await sendKey('c', 67, 2, ["copy"]);
+
+  await sendKey('a', 65);
+  await sendKey('b', 66);
+  await sendKey('c', 67);
+  await logElementValue("input");
+
+  await sendKey('a', 65, 2, ["selectAll"]);
+  await sendKey('c', 67, 2, ["paste"]);
+  await logElementValue("input");
+
+  testRunner.completeTest();
+})
+
diff --git a/headless/test/data/protocol/input/resources/input.html b/headless/test/data/protocol/input/resources/input.html
new file mode 100644
index 0000000..a750341
--- /dev/null
+++ b/headless/test/data/protocol/input/resources/input.html
@@ -0,0 +1,3 @@
+<html> <body>
+  <input type="text" id="input" value="input_value" autofocus>
+</body></html>
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc
index cc353e74a..1c5ed22 100644
--- a/headless/test/headless_protocol_browsertest.cc
+++ b/headless/test/headless_protocol_browsertest.cc
@@ -261,6 +261,8 @@
 
 HEADLESS_PROTOCOL_TEST(DragStarted, "input/dragIntercepted.js")
 
+HEADLESS_PROTOCOL_TEST(InputClipboardOps, "input/input-clipboard-ops.js")
+
 HEADLESS_PROTOCOL_TEST(HeadlessSessionBasicsTest,
                        "sessions/headless-session-basics.js")
 
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 518d3d14..a06ed31 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -245,6 +245,13 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/android-marshmallow-x86-rel-rts"
+        experiment_percentage: 5
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/android-official"
         includable_only: true
       }
@@ -518,6 +525,13 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/chromeos-amd64-generic-rel-rts"
+        experiment_percentage: 5
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/chromeos-arm-generic-dbg"
         includable_only: true
       }
@@ -676,6 +690,13 @@
         location_regexp_exclude: ".+/[+]/infra/config/.+"
       }
       builders {
+        name: "chromium/try/fuchsia_x64_rts"
+        experiment_percentage: 5
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/gpu-fyi-try-android-l-nexus-5-32"
         includable_only: true
       }
@@ -965,6 +986,13 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/ios-simulator-rts"
+        experiment_percentage: 1
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/ios13-beta-simulator"
         includable_only: true
       }
@@ -1443,6 +1471,13 @@
         location_regexp_exclude: ".+/[+]/infra/config/.+"
       }
       builders {
+        name: "chromium/try/mac-rel-rts"
+        experiment_percentage: 1
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/mac-swangle-chromium-try-x64"
         includable_only: true
       }
@@ -1687,6 +1722,13 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/win10_chromium_x64_rel_ng_rts"
+        experiment_percentage: 5
+        location_regexp: ".*"
+        location_regexp_exclude: ".+/[+]/docs/.+"
+        location_regexp_exclude: ".+/[+]/infra/config/.+"
+      }
+      builders {
         name: "chromium/try/win32-official"
         includable_only: true
       }
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index c0870ec..a451556 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -429,9 +429,21 @@
 * [android-marshmallow-arm64-rel-dual-coverage](https://ci.chromium.org/p/chromium/builders/try/android-marshmallow-arm64-rel-dual-coverage) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-marshmallow-arm64-rel-dual-coverage)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-marshmallow-arm64-rel-dual-coverage))
   * Experiment percentage: 3.0
 
+* [android-marshmallow-x86-rel-rts](https://ci.chromium.org/p/chromium/builders/try/android-marshmallow-x86-rel-rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-marshmallow-x86-rel-rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-marshmallow-x86-rel-rts))
+  * Experiment percentage: 5.0
+
 * [android-pie-arm64-coverage-experimental-rel](https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-coverage-experimental-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+android-pie-arm64-coverage-experimental-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+android-pie-arm64-coverage-experimental-rel))
   * Experiment percentage: 3.0
 
+* [chromeos-amd64-generic-rel-rts](https://ci.chromium.org/p/chromium/builders/try/chromeos-amd64-generic-rel-rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+chromeos-amd64-generic-rel-rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+chromeos-amd64-generic-rel-rts))
+  * Experiment percentage: 5.0
+
+* [fuchsia_x64_rts](https://ci.chromium.org/p/chromium/builders/try/fuchsia_x64_rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+fuchsia_x64_rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+fuchsia_x64_rts))
+  * Experiment percentage: 5.0
+
+* [ios-simulator-rts](https://ci.chromium.org/p/chromium/builders/try/ios-simulator-rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+ios-simulator-rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+ios-simulator-rts))
+  * Experiment percentage: 1.0
+
 * [linux-experimental-next-rel](https://ci.chromium.org/p/chromium/builders/try/linux-experimental-next-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-experimental-next-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-experimental-next-rel))
   * Experiment percentage: 10.0
 
@@ -457,3 +469,9 @@
 * [linux_chromium_tsan_rel_ng_bionic](https://ci.chromium.org/p/chromium/builders/try/linux_chromium_tsan_rel_ng_bionic) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux_chromium_tsan_rel_ng_bionic)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux_chromium_tsan_rel_ng_bionic))
   * Experiment percentage: 40.0
 
+* [mac-rel-rts](https://ci.chromium.org/p/chromium/builders/try/mac-rel-rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+mac-rel-rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+mac-rel-rts))
+  * Experiment percentage: 1.0
+
+* [win10_chromium_x64_rel_ng_rts](https://ci.chromium.org/p/chromium/builders/try/win10_chromium_x64_rel_ng_rts) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+win10_chromium_x64_rel_ng_rts)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+win10_chromium_x64_rel_ng_rts))
+  * Experiment percentage: 5.0
+
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 36d858be..6f973804 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -21237,7 +21237,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"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\"},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -21595,6 +21595,68 @@
       }
     }
     builders {
+      name: "android-weblayer-with-aosp-webview-x86-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"chromium.android\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.gtests_local"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.buildbucket.use_bbagent"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "android-weblayer-x86-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -26150,6 +26212,68 @@
       }
     }
     builders {
+      name: "linux-lacros-code-coverage"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:32"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:1"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 72000
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.gtests_local"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.buildbucket.use_bbagent"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-lacros-tester-fyi-rel"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -32849,11 +32973,11 @@
       }
     }
     builders {
-      name: "Chromium Win Goma RBE Staging"
+      name: "Chromium Win Goma RBE ATS Staging"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builder:Chromium Win Goma RBE Staging"
-      dimensions: "cores:32"
+      dimensions: "builder:Chromium Win Goma RBE ATS Staging"
+      dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.ci"
@@ -32875,11 +32999,89 @@
       }
     }
     builders {
+      name: "Chromium Win Goma RBE ATS Staging (clobber)"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:Chromium Win Goma RBE ATS Staging (clobber)"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows-10"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+      }
+    }
+    builders {
+      name: "Chromium Win Goma RBE ATS ToT"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:Chromium Win Goma RBE ATS ToT"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows-10"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+      }
+    }
+    builders {
+      name: "Chromium Win Goma RBE Staging"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:Chromium Win Goma RBE Staging"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows-10"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+      }
+    }
+    builders {
       name: "Chromium Win Goma RBE Staging (clobber)"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builder:Chromium Win Goma RBE Staging (clobber)"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.ci"
@@ -32888,7 +33090,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      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\"},\"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\"},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -32905,7 +33107,7 @@
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
       dimensions: "builder:Chromium Win Goma RBE ToT"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
       dimensions: "cpu:x86-64"
       dimensions: "os:Windows-10"
       dimensions: "pool:luci.chromium.ci"
@@ -32914,7 +33116,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      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\"},\"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\"},\"builder_group\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com"
@@ -34898,6 +35100,70 @@
       }
     }
     builders {
+      name: "android-marshmallow-x86-rel-rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:android-marshmallow-x86-rel-rts"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"tryserver.chromium.android\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "android-official"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -38135,6 +38401,70 @@
       }
     }
     builders {
+      name: "chromeos-amd64-generic-rel-rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:chromeos-amd64-generic-rel-rts"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.chromiumos\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "chromeos-arm-generic-dbg"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -39682,6 +40012,70 @@
       }
     }
     builders {
+      name: "fuchsia_x64_rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:fuchsia_x64_rts"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "gpu-fyi-try-android-l-nexus-5-32"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -44074,6 +44468,77 @@
       }
     }
     builders {
+      name: "ios-simulator-rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:ios-simulator-rts"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Mac-10.15"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\",\"xcode_build_version\":\"12d4e\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      caches {
+        name: "xcode_ios_12d4e"
+        path: "xcode_ios_12d4e.app"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.chromium_tests.use_rbe_cas"
+        value: 20
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "ios13-beta-simulator"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -50336,6 +50801,74 @@
       }
     }
     builders {
+      name: "mac-rel-rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:mac-rel-rts"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Mac"
+      dimensions: "pool:luci.chromium.try"
+      dimensions: "ssd:1"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.chromium_tests.use_rbe_cas"
+        value: 20
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "mac-swangle-chromium-try-x64"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -53745,6 +54278,70 @@
       }
     }
     builders {
+      name: "win10_chromium_x64_rel_ng_rts"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:win10_chromium_x64_rel_ng_rts"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Windows-10"
+      dimensions: "pool:luci.chromium.try"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      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\"},\"builder_group\":\"tryserver.chromium.win\",\"recipe\":\"chromium_trybot\"}"
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "win32-official"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index ea9084c5..c75ddf8 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -2601,6 +2601,11 @@
     short_name: "x86"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/android-weblayer-with-aosp-webview-x86-rel"
+    category: "builder|weblayer_with_aosp_webview"
+    short_name: "x86"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/Lollipop Phone Tester"
     category: "tester|phone"
     short_name: "L"
@@ -2640,6 +2645,11 @@
     category: "tester|incremental"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/android-weblayer-marshmallow-x86-rel-tests"
+    category: "tester|weblayer"
+    short_name: "M"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/android-weblayer-oreo-x86-rel-tests"
     category: "tester|weblayer"
     short_name: "O"
@@ -3089,11 +3099,6 @@
     category: "tester|weblayer"
     short_name: "10"
   }
-  builders {
-    name: "buildbucket/luci.chromium.ci/android-weblayer-marshmallow-x86-rel-tests"
-    category: "tester|weblayer"
-    short_name: "M"
-  }
   header {
     oncalls {
       name: "Chromium"
@@ -5642,6 +5647,11 @@
     short_name: "ios"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/linux-lacros-code-coverage"
+    category: "code_coverage"
+    short_name: "lac"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/win10-code-coverage"
     category: "code_coverage"
     short_name: "win"
@@ -6315,6 +6325,11 @@
     category: "rbe|tot|win|rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.goma/Chromium Win Goma RBE ATS ToT"
+    category: "rbe|tot|win|rel"
+    short_name: "ats"
+  }
+  builders {
     name: "buildbucket/luci.chromium.goma/Chromium iOS Goma RBE ToT"
     category: "rbe|tot|ios|rel"
   }
@@ -6367,11 +6382,21 @@
     category: "rbe|staging|win|rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.goma/Chromium Win Goma RBE ATS Staging"
+    category: "rbe|staging|win|rel"
+    short_name: "ats"
+  }
+  builders {
     name: "buildbucket/luci.chromium.goma/Chromium Win Goma RBE Staging (clobber)"
     category: "rbe|staging|win|rel"
     short_name: "clb"
   }
   builders {
+    name: "buildbucket/luci.chromium.goma/Chromium Win Goma RBE ATS Staging (clobber)"
+    category: "rbe|staging|win|rel"
+    short_name: "ats"
+  }
+  builders {
     name: "buildbucket/luci.chromium.goma/Chromium Android ARM 32-bit Goma RBE Staging"
     category: "rbe|staging|android arm|rel"
   }
@@ -12686,6 +12711,9 @@
     name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-non-cq"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-official"
   }
   builders {
@@ -12836,6 +12864,9 @@
     name: "buildbucket/luci.chromium.try/chromeos-amd64-generic-rel-dchecks"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/chromeos-amd64-generic-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/chromeos-arm-generic-dbg"
   }
   builders {
@@ -12908,6 +12939,9 @@
     name: "buildbucket/luci.chromium.try/fuchsia_x64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/fuchsia_x64_rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-android-l-nexus-5-32"
   }
   builders {
@@ -13118,6 +13152,9 @@
     name: "buildbucket/luci.chromium.try/ios-simulator-noncq"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/ios-simulator-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/ios13-beta-simulator"
   }
   builders {
@@ -13406,6 +13443,9 @@
     name: "buildbucket/luci.chromium.try/mac-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/mac-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/mac-swangle-chromium-try-x64"
   }
   builders {
@@ -13562,6 +13602,9 @@
     name: "buildbucket/luci.chromium.try/win10_chromium_x64_rel_ng_exp"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/win10_chromium_x64_rel_ng_rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/win32-official"
   }
   builders {
@@ -13713,6 +13756,9 @@
     name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-non-cq"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-marshmallow-x86-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-opus-arm-rel"
   }
   builders {
@@ -13945,6 +13991,9 @@
     name: "buildbucket/luci.chromium.try/chromeos-amd64-generic-rel-dchecks"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/chromeos-amd64-generic-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/chromeos-arm-generic-dbg"
   }
   builders {
@@ -14092,6 +14141,9 @@
     name: "buildbucket/luci.chromium.try/fuchsia_x64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/fuchsia_x64_rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-lacros-amd-rel"
   }
   builders {
@@ -14412,6 +14464,9 @@
     name: "buildbucket/luci.chromium.try/ios-simulator-noncq"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/ios-simulator-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/ios13-beta-simulator"
   }
   builders {
@@ -14436,6 +14491,9 @@
     name: "buildbucket/luci.chromium.try/mac-rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/mac-rel-rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/mac_chromium_10.11_rel_ng"
   }
   builders {
@@ -14618,6 +14676,9 @@
     name: "buildbucket/luci.chromium.try/win10_chromium_x64_rel_ng_exp"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/win10_chromium_x64_rel_ng_rts"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/win7-rel"
   }
   builders {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 59e29fea..7485a00 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -664,6 +664,36 @@
   }
 }
 job {
+  id: "Chromium Win Goma RBE ATS Staging"
+  realm: "goma"
+  acl_sets: "goma"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.goma"
+    builder: "Chromium Win Goma RBE ATS Staging"
+  }
+}
+job {
+  id: "Chromium Win Goma RBE ATS Staging (clobber)"
+  realm: "goma"
+  acl_sets: "goma"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.goma"
+    builder: "Chromium Win Goma RBE ATS Staging (clobber)"
+  }
+}
+job {
+  id: "Chromium Win Goma RBE ATS ToT"
+  realm: "goma"
+  acl_sets: "goma"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.goma"
+    builder: "Chromium Win Goma RBE ATS ToT"
+  }
+}
+job {
   id: "Chromium Win Goma RBE Staging"
   realm: "goma"
   acl_sets: "goma"
@@ -4769,6 +4799,16 @@
   }
 }
 job {
+  id: "android-weblayer-with-aosp-webview-x86-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "android-weblayer-with-aosp-webview-x86-rel"
+  }
+}
+job {
   id: "android-weblayer-x86-rel"
   realm: "ci"
   acl_sets: "ci"
@@ -5611,6 +5651,16 @@
   }
 }
 job {
+  id: "linux-lacros-code-coverage"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-lacros-code-coverage"
+  }
+}
+job {
   id: "linux-lacros-tester-fyi-rel"
   realm: "ci"
   acls {
@@ -6943,6 +6993,7 @@
   triggers: "android-weblayer-pie-x86-wpt-fyi-rel"
   triggers: "android-weblayer-pie-x86-wpt-smoketest"
   triggers: "android-weblayer-with-aosp-webview-x86-fyi-rel"
+  triggers: "android-weblayer-with-aosp-webview-x86-rel"
   triggers: "android-weblayer-x86-rel"
   triggers: "android-webview-pie-x86-wpt-fyi-rel"
   triggers: "chromeos-amd64-generic-asan-rel"
@@ -7000,6 +7051,7 @@
   triggers: "linux-gcc-rel"
   triggers: "linux-lacros-builder-fyi-rel"
   triggers: "linux-lacros-builder-rel"
+  triggers: "linux-lacros-code-coverage"
   triggers: "linux-official"
   triggers: "linux-ozone-rel"
   triggers: "linux-perfetto-rel"
@@ -7071,6 +7123,9 @@
   triggers: "Chromium Mac Goma RBE Staging (clobber)"
   triggers: "Chromium Mac Goma RBE Staging (dbg)"
   triggers: "Chromium Mac Goma RBE ToT"
+  triggers: "Chromium Win Goma RBE ATS Staging"
+  triggers: "Chromium Win Goma RBE ATS Staging (clobber)"
+  triggers: "Chromium Win Goma RBE ATS ToT"
   triggers: "Chromium Win Goma RBE Staging"
   triggers: "Chromium Win Goma RBE Staging (clobber)"
   triggers: "Chromium Win Goma RBE ToT"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index ed3019b..26fb3002 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -933,6 +933,16 @@
 )
 
 ci.android_builder(
+    name = "android-weblayer-marshmallow-x86-rel-tests",
+    console_view_entry = consoles.console_view_entry(
+        category = "tester|weblayer",
+        short_name = "M",
+    ),
+    triggered_by = ["android-weblayer-with-aosp-webview-x86-rel"],
+    notifies = ["weblayer-sheriff"],
+)
+
+ci.android_builder(
     name = "android-weblayer-oreo-x86-rel-tests",
     console_view_entry = consoles.console_view_entry(
         category = "tester|weblayer",
@@ -953,6 +963,14 @@
 )
 
 ci.android_builder(
+    name = "android-weblayer-with-aosp-webview-x86-rel",
+    console_view_entry = consoles.console_view_entry(
+        category = "builder|weblayer_with_aosp_webview",
+        short_name = "x86",
+    ),
+)
+
+ci.android_builder(
     name = "android-weblayer-x86-rel",
     console_view_entry = consoles.console_view_entry(
         category = "builder|weblayer",
@@ -1052,16 +1070,6 @@
 )
 
 ci.android_fyi_builder(
-    name = "android-weblayer-marshmallow-x86-rel-tests",
-    console_view_entry = consoles.console_view_entry(
-        category = "tester|weblayer",
-        short_name = "M",
-    ),
-    triggered_by = ["android-weblayer-with-aosp-webview-x86-fyi-rel"],
-    notifies = ["weblayer-sheriff"],
-)
-
-ci.android_fyi_builder(
     name = "android-weblayer-with-aosp-webview-x86-fyi-rel",
     console_view_entry = consoles.console_view_entry(
         category = "builder|weblayer_with_aosp_webview",
@@ -3777,6 +3785,16 @@
 )
 
 ci.fyi_coverage_builder(
+    name = "linux-lacros-code-coverage",
+    console_view_entry = consoles.console_view_entry(
+        category = "code_coverage",
+        short_name = "lac",
+    ),
+    use_clang_coverage = True,
+    coverage_test_types = ["overall", "unit"],
+)
+
+ci.fyi_coverage_builder(
     name = "mac-code-coverage",
     builderless = True,
     console_view_entry = consoles.console_view_entry(
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 8fcb7cd..38a5f3c 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -1291,16 +1291,6 @@
 )
 
 try_.chromium_linux_builder(
-    name = "linux-rel-rts",
-    builderless = False,
-    goma_jobs = goma.jobs.J150,
-    use_clang_coverage = True,
-    tryjob = try_.job(
-        experiment_percentage = 5,
-    ),
-)
-
-try_.chromium_linux_builder(
     name = "linux-trusty-rel",
     goma_jobs = goma.jobs.J150,
     os = os.LINUX_TRUSTY,
@@ -2012,6 +2002,73 @@
     ),
 )
 
+# RTS builders (https://crbug.com/1203048)
+try_.chromium_linux_builder(
+    name = "linux-rel-rts",
+    builderless = False,
+    goma_jobs = goma.jobs.J150,
+    use_clang_coverage = True,
+    tryjob = try_.job(
+        experiment_percentage = 5,
+    ),
+)
+
+try_.chromium_mac_builder(
+    name = "mac-rel-rts",
+    builderless = False,
+    use_clang_coverage = True,
+    goma_jobs = goma.jobs.J150,
+    tryjob = try_.job(
+        experiment_percentage = 1,
+    ),
+)
+
+try_.chromium_win_builder(
+    name = "win10_chromium_x64_rel_ng_rts",
+    goma_jobs = goma.jobs.J150,
+    use_clang_coverage = True,
+    builderless = False,
+    tryjob = try_.job(
+        experiment_percentage = 5,
+    ),
+)
+
+try_.chromium_android_builder(
+    name = "android-marshmallow-x86-rel-rts",
+    goma_jobs = goma.jobs.J300,
+    builderless = False,
+    tryjob = try_.job(
+        experiment_percentage = 5,
+    ),
+)
+
+try_.chromium_linux_builder(
+    name = "fuchsia_x64_rts",
+    builderless = False,
+    tryjob = try_.job(
+        experiment_percentage = 5,
+    ),
+)
+
+try_.chromium_chromiumos_builder(
+    name = "chromeos-amd64-generic-rel-rts",
+    builderless = False,
+    tryjob = try_.job(
+        experiment_percentage = 5,
+    ),
+)
+
+try_.chromium_mac_ios_builder(
+    name = "ios-simulator-rts",
+    use_clang_coverage = True,
+    coverage_exclude_sources = "ios_test_files_and_test_utils",
+    coverage_test_types = ["unit"],
+    builderless = False,
+    tryjob = try_.job(
+        experiment_percentage = 1,
+    ),
+)
+
 # Used for listing chrome trybots in chromium's commit-queue.cfg without also
 # adding them to chromium's cr-buildbucket.cfg. Note that the recipe these
 # builders run allow only known roller accounts when triggered via the CQ.
diff --git a/infra/config/subprojects/goma/consoles/chromium.goma.star b/infra/config/subprojects/goma/consoles/chromium.goma.star
index e371b502..3f413f1f 100644
--- a/infra/config/subprojects/goma/consoles/chromium.goma.star
+++ b/infra/config/subprojects/goma/consoles/chromium.goma.star
@@ -28,6 +28,11 @@
             category = "rbe|tot|win|rel",
         ),
         luci.console_view_entry(
+            builder = "goma/Chromium Win Goma RBE ATS ToT",
+            category = "rbe|tot|win|rel",
+            short_name = "ats",
+        ),
+        luci.console_view_entry(
             builder = "goma/Chromium iOS Goma RBE ToT",
             category = "rbe|tot|ios|rel",
         ),
@@ -80,11 +85,21 @@
             category = "rbe|staging|win|rel",
         ),
         luci.console_view_entry(
+            builder = "goma/Chromium Win Goma RBE ATS Staging",
+            category = "rbe|staging|win|rel",
+            short_name = "ats",
+        ),
+        luci.console_view_entry(
             builder = "goma/Chromium Win Goma RBE Staging (clobber)",
             category = "rbe|staging|win|rel",
             short_name = "clb",
         ),
         luci.console_view_entry(
+            builder = "goma/Chromium Win Goma RBE ATS Staging (clobber)",
+            category = "rbe|staging|win|rel",
+            short_name = "ats",
+        ),
+        luci.console_view_entry(
             builder = "goma/Chromium Android ARM 32-bit Goma RBE Staging",
             category = "rbe|staging|android arm|rel",
         ),
diff --git a/infra/config/subprojects/goma/goma.star b/infra/config/subprojects/goma/goma.star
index 5f4971b..9bf62e7 100644
--- a/infra/config/subprojects/goma/goma.star
+++ b/infra/config/subprojects/goma/goma.star
@@ -340,11 +340,9 @@
         *,
         name,
         goma_enable_ats = True,
-        cores = 32,
         **kwargs):
     return goma_builder(
         name = name,
-        cores = cores,
         goma_enable_ats = goma_enable_ats,
         os = os.WINDOWS_DEFAULT,
         **kwargs
@@ -353,14 +351,35 @@
 goma_windows_builder(
     name = "Chromium Win Goma RBE Staging",
     goma_backend = goma.backend.RBE_STAGING,
+    goma_enable_ats = False,
 )
 
 goma_windows_builder(
     name = "Chromium Win Goma RBE Staging (clobber)",
     goma_backend = goma.backend.RBE_STAGING,
+    goma_enable_ats = False,
 )
 
 goma_windows_builder(
     name = "Chromium Win Goma RBE ToT",
     goma_backend = goma.backend.RBE_TOT,
+    goma_enable_ats = False,
+)
+
+goma_windows_builder(
+    name = "Chromium Win Goma RBE ATS Staging",
+    goma_backend = goma.backend.RBE_STAGING,
+    goma_enable_ats = True,
+)
+
+goma_windows_builder(
+    name = "Chromium Win Goma RBE ATS Staging (clobber)",
+    goma_backend = goma.backend.RBE_STAGING,
+    goma_enable_ats = True,
+)
+
+goma_windows_builder(
+    name = "Chromium Win Goma RBE ATS ToT",
+    goma_backend = goma.backend.RBE_TOT,
+    goma_enable_ats = True,
 )
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/BUILD.gn b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/BUILD.gn
index b743858..7613c8ff 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/BUILD.gn
@@ -12,6 +12,10 @@
     "consistency_account_chooser_coordinator.mm",
     "consistency_account_chooser_mediator.h",
     "consistency_account_chooser_mediator.mm",
+    "consistency_account_chooser_table_view_controller.h",
+    "consistency_account_chooser_table_view_controller.mm",
+    "consistency_account_chooser_table_view_controller_action_delegate.h",
+    "consistency_account_chooser_table_view_controller_model_delegate.h",
     "consistency_account_chooser_view_controller.h",
     "consistency_account_chooser_view_controller.mm",
     "identity_item_configurator.h",
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm
index ff7d29e3..6ee73802 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm
@@ -6,10 +6,9 @@
 
 #import "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_action_delegate.h"
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h"
 #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
-#import "ios/chrome/browser/ui/table_view/table_view_utils.h"
-#import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
@@ -19,7 +18,7 @@
 #endif
 
 @interface ConsistencyAccountChooserCoordinator () <
-    ConsistencyAccountChooserViewControllerActionDelegate>
+    ConsistencyAccountChooserTableViewControllerActionDelegate>
 
 @property(nonatomic, strong)
     ConsistencyAccountChooserViewController* accountChooserViewController;
@@ -35,13 +34,10 @@
   [super start];
   self.mediator = [[ConsistencyAccountChooserMediator alloc]
       initWithSelectedIdentity:selectedIdentity];
-  UITableViewStyle style = base::FeatureList::IsEnabled(kSettingsRefresh)
-                               ? ChromeTableViewStyle()
-                               : UITableViewStylePlain;
   self.accountChooserViewController =
-      [[ConsistencyAccountChooserViewController alloc] initWithStyle:style];
+      [[ConsistencyAccountChooserViewController alloc] init];
   self.accountChooserViewController.modelDelegate = self.mediator;
-  self.mediator.consumer = self.accountChooserViewController;
+  self.mediator.consumer = self.accountChooserViewController.consumer;
   self.accountChooserViewController.actionDelegate = self;
   [self.accountChooserViewController view];
 }
@@ -56,11 +52,11 @@
   return self.mediator.selectedIdentity;
 }
 
-#pragma mark - ConsistencyAccountChooserViewControllerPresentationDelegate
+#pragma mark - ConsistencyAccountChooserTableViewControllerPresentationDelegate
 
-- (void)consistencyAccountChooserViewController:
-            (ConsistencyAccountChooserViewController*)viewController
-                    didSelectIdentityWithGaiaID:(NSString*)gaiaID {
+- (void)consistencyAccountChooserTableViewController:
+            (ConsistencyAccountChooserTableViewController*)viewController
+                         didSelectIdentityWithGaiaID:(NSString*)gaiaID {
   ios::ChromeIdentityService* identityService =
       ios::GetChromeBrowserProvider()->GetChromeIdentityService();
   ChromeIdentity* identity =
@@ -71,8 +67,8 @@
       consistencyAccountChooserCoordinatorChromeIdentitySelected:self];
 }
 
-- (void)consistencyAccountChooserViewControllerDidTapOnAddAccount:
-    (ConsistencyAccountChooserViewController*)viewController {
+- (void)consistencyAccountChooserTableViewControllerDidTapOnAddAccount:
+    (ConsistencyAccountChooserTableViewController*)viewController {
   self.addAccountSigninCoordinator = [SigninCoordinator
       addAccountCoordinatorWithBaseViewController:self.viewController
                                           browser:self.browser
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.h
index 1ab1292..f13041b1 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.h
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.h
@@ -7,7 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_model_delegate.h"
 
 @class ChromeIdentity;
 @protocol ConsistencyAccountChooserConsumer;
@@ -15,7 +15,7 @@
 
 // Mediator for ConsistencyAccountChooserCoordinator.
 @interface ConsistencyAccountChooserMediator
-    : NSObject <ConsistencyAccountChooserViewControllerModelDelegate>
+    : NSObject <ConsistencyAccountChooserTableViewControllerModelDelegate>
 
 @property(nonatomic, strong) id<ConsistencyAccountChooserConsumer> consumer;
 @property(nonatomic, strong) ChromeIdentity* selectedIdentity;
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
index 5bf87e5..0458586 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
@@ -7,6 +7,7 @@
 #import "ios/chrome/browser/chrome_browser_provider_observer_bridge.h"
 #import "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h"
 #import "ios/chrome/browser/ui/authentication/resized_avatar_cache.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_consumer.h"
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/identity_item_configurator.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
@@ -17,8 +18,7 @@
 
 @interface ConsistencyAccountChooserMediator () <
     ChromeBrowserProviderObserver,
-    ChromeIdentityServiceObserver,
-    ConsistencyAccountChooserViewControllerModelDelegate> {
+    ChromeIdentityServiceObserver> {
   std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver;
   std::unique_ptr<ChromeBrowserProviderObserverBridge> _browserProviderObserver;
 }
@@ -140,7 +140,7 @@
   _identityServiceObserver.reset();
 }
 
-#pragma mark - ConsistencyAccountChooserViewControllerModelDelegate
+#pragma mark - ConsistencyAccountChooserTableViewControllerModelDelegate
 
 - (NSArray*)sortedIdentityItemConfigurators {
   if (!_sortedIdentityItemConfigurators) {
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.h
new file mode 100644
index 0000000..553e46ee
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.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 IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_consumer.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
+
+@protocol ConsistencyAccountChooserTableViewControllerActionDelegate;
+@protocol ConsistencyAccountChooserTableViewControllerModelDelegate;
+
+// View controller for ConsistencyAccountChooserCoordinator.
+@interface ConsistencyAccountChooserTableViewController
+    : ChromeTableViewController <ConsistencyAccountChooserConsumer>
+
+@property(nonatomic, weak)
+    id<ConsistencyAccountChooserTableViewControllerActionDelegate>
+        actionDelegate;
+@property(nonatomic, weak)
+    id<ConsistencyAccountChooserTableViewControllerModelDelegate>
+        modelDelegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.mm
new file mode 100644
index 0000000..33133805
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.mm
@@ -0,0 +1,152 @@
+// 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/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.h"
+
+#import "base/check.h"
+#import "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/authentication/cells/table_view_identity_item.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_action_delegate.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_model_delegate.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/identity_item_configurator.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_image_item.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "ios/chrome/grit/ios_strings.h"
+#import "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// List of sections.
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  IdentitySectionIdentifier = kSectionIdentifierEnumZero,
+  AddAccountSectionIdentifier,
+};
+
+typedef NS_ENUM(NSInteger, ItemType) {
+  // IdentitySectionIdentifier section.
+  IdentityItemType = kItemTypeEnumZero,
+  // AddAccountSectionIdentifier section.
+  AddAccountItemType,
+};
+
+// Table view header/footer height.
+CGFloat kSectionHeaderHeight = 8.;
+CGFloat kSectionFooterHeight = 8.;
+
+}  // naemspace
+
+@interface ConsistencyAccountChooserTableViewController ()
+
+@end
+
+@implementation ConsistencyAccountChooserTableViewController
+
+#pragma mark - UIView
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  [self loadModel];
+  [self.tableView reloadData];
+  self.view.backgroundColor = UIColor.clearColor;
+}
+
+#pragma mark - UITableViewController
+
+- (void)loadModel {
+  [super loadModel];
+  [self loadIdentitySection];
+  [self loadAddAccountSection];
+}
+
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+  ListItem* item = [self.tableViewModel itemAtIndexPath:indexPath];
+  switch ((ItemType)item.type) {
+    case IdentityItemType: {
+      TableViewIdentityItem* identityItem =
+          base::mac::ObjCCastStrict<TableViewIdentityItem>(item);
+      DCHECK(identityItem);
+      [self.actionDelegate
+          consistencyAccountChooserTableViewController:self
+                           didSelectIdentityWithGaiaID:identityItem.gaiaID];
+      break;
+    }
+    case AddAccountItemType:
+      [self.actionDelegate
+          consistencyAccountChooserTableViewControllerDidTapOnAddAccount:self];
+      break;
+  }
+}
+
+- (CGFloat)tableView:(UITableView*)tableView
+    heightForHeaderInSection:(NSInteger)section {
+  return kSectionHeaderHeight;
+}
+
+- (CGFloat)tableView:(UITableView*)tableView
+    heightForFooterInSection:(NSInteger)section {
+  return kSectionFooterHeight;
+}
+
+#pragma mark - Private
+
+// Creates the identity section in the table view model.
+- (void)loadIdentitySection {
+  TableViewModel* model = self.tableViewModel;
+  [model addSectionWithIdentifier:IdentitySectionIdentifier];
+  [self loadIdentityItems];
+}
+
+// Creates all the identity items in the table view model.
+- (void)loadIdentityItems {
+  TableViewModel* model = self.tableViewModel;
+  for (IdentityItemConfigurator* configurator in self.modelDelegate
+           .sortedIdentityItemConfigurators) {
+    TableViewIdentityItem* item =
+        [[TableViewIdentityItem alloc] initWithType:IdentityItemType];
+    [configurator configureIdentityChooser:item];
+    [model addItem:item toSectionWithIdentifier:IdentitySectionIdentifier];
+  }
+}
+
+// Creates the add account section in the table view model.
+- (void)loadAddAccountSection {
+  TableViewModel* model = self.tableViewModel;
+  [model addSectionWithIdentifier:AddAccountSectionIdentifier];
+  TableViewImageItem* item =
+      [[TableViewImageItem alloc] initWithType:AddAccountItemType];
+  item.title = l10n_util::GetNSString(IDS_IOS_CONSISTENCY_PROMO_ADD_ACCOUNT);
+  item.textColor = [UIColor colorNamed:kBlueColor];
+  [model addItem:item toSectionWithIdentifier:AddAccountSectionIdentifier];
+}
+
+#pragma mark - ConsistencyAccountChooserConsumer
+
+- (void)reloadAllIdentities {
+  TableViewModel* model = self.tableViewModel;
+  [model deleteAllItemsFromSectionWithIdentifier:IdentitySectionIdentifier];
+  [self loadIdentityItems];
+  [self.tableView reloadData];
+}
+
+- (void)reloadIdentityForIdentityItemConfigurator:
+    (IdentityItemConfigurator*)configurator {
+  TableViewModel* model = self.tableViewModel;
+  NSArray* items =
+      [model itemsInSectionWithIdentifier:IdentitySectionIdentifier];
+  for (TableViewIdentityItem* item in items) {
+    if ([item.gaiaID isEqual:configurator.gaiaID]) {
+      [configurator configureIdentityChooser:item];
+      [self reconfigureCellsForItems:@[ item ]];
+      break;
+    }
+  }
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_action_delegate.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_action_delegate.h
new file mode 100644
index 0000000..4990d9d
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_action_delegate.h
@@ -0,0 +1,25 @@
+// 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_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_ACTION_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_ACTION_DELEGATE_H_
+
+#import <Foundation/Foundation.h>
+
+@class ConsistencyAccountChooserTableViewController;
+
+// Delegate protocol for ConsistencyAccountChooserTableViewController.
+@protocol ConsistencyAccountChooserTableViewControllerActionDelegate <NSObject>
+
+// Invoked when the user selects an identity.
+- (void)consistencyAccountChooserTableViewController:
+            (ConsistencyAccountChooserTableViewController*)viewController
+                         didSelectIdentityWithGaiaID:(NSString*)gaiaID;
+// Invoked when the user taps on "Add account".
+- (void)consistencyAccountChooserTableViewControllerDidTapOnAddAccount:
+    (ConsistencyAccountChooserTableViewController*)viewController;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_ACTION_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_model_delegate.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_model_delegate.h
new file mode 100644
index 0000000..a575589
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller_model_delegate.h
@@ -0,0 +1,20 @@
+// 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_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_MODEL_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_MODEL_DELEGATE_H_
+
+#import <Foundation/Foundation.h>
+
+@class ConsistencyAccountChooserViewController;
+
+// Protocol to get the model.
+@protocol ConsistencyAccountChooserTableViewControllerModelDelegate <NSObject>
+
+// Returns all the configurators to generate model items.
+@property(nonatomic, strong, readonly) NSArray* sortedIdentityItemConfigurators;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_CONSISTENCY_PROMO_SIGNIN_CONSISTENCY_ACCOUNT_CHOOSER_CONSISTENCY_ACCOUNT_CHOOSER_TABLE_VIEW_CONTROLLER_MODEL_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h
index e18f762..1150604d 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h
@@ -8,43 +8,23 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/bottom_sheet/child_bottom_sheet_view_controller.h"
-#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_consumer.h"
-#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
 
-@class ConsistencyAccountChooserViewController;
-
-// Delegate protocol for ConsistencyAccountChooserViewController.
-@protocol ConsistencyAccountChooserViewControllerActionDelegate <NSObject>
-
-// Invoked when the user selects an identity.
-- (void)consistencyAccountChooserViewController:
-            (ConsistencyAccountChooserViewController*)viewController
-                    didSelectIdentityWithGaiaID:(NSString*)gaiaID;
-// Invoked when the user taps on "Add account".
-- (void)consistencyAccountChooserViewControllerDidTapOnAddAccount:
-    (ConsistencyAccountChooserViewController*)viewController;
-
-@end
-
-// Protocol to get the model.
-@protocol ConsistencyAccountChooserViewControllerModelDelegate <NSObject>
-
-// Returns all the configurators to generate model items.
-@property(nonatomic, strong, readonly) NSArray* sortedIdentityItemConfigurators;
-
-@end
+@protocol ConsistencyAccountChooserTableViewControllerActionDelegate;
+@protocol ConsistencyAccountChooserTableViewControllerModelDelegate;
+@protocol ConsistencyAccountChooserConsumer;
 
 // View controller for ConsistencyAccountChooserCoordinator.
 @interface ConsistencyAccountChooserViewController
-    : ChromeTableViewController <ChildBottomSheetViewController,
-                                 ConsistencyAccountChooserConsumer>
+    : UIViewController <ChildBottomSheetViewController>
 
 @property(nonatomic, weak)
-    id<ConsistencyAccountChooserViewControllerActionDelegate>
+    id<ConsistencyAccountChooserTableViewControllerActionDelegate>
         actionDelegate;
 @property(nonatomic, weak)
-    id<ConsistencyAccountChooserViewControllerModelDelegate>
+    id<ConsistencyAccountChooserTableViewControllerModelDelegate>
         modelDelegate;
+@property(nonatomic, strong, readonly) id<ConsistencyAccountChooserConsumer>
+    consumer;
 
 @end
 
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.mm
index 9a1b90a..b77401e 100644
--- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.mm
@@ -5,11 +5,9 @@
 #import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_view_controller.h"
 
 #import "base/check.h"
-#import "base/mac/foundation_util.h"
-#import "ios/chrome/browser/ui/authentication/cells/table_view_identity_item.h"
-#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/identity_item_configurator.h"
-#import "ios/chrome/browser/ui/table_view/cells/table_view_image_item.h"
-#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_table_view_controller.h"
+#import "ios/chrome/browser/ui/table_view/table_view_utils.h"
+#import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util.h"
 
@@ -17,111 +15,68 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// List of sections.
-typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  IdentitySectionIdentifier = kSectionIdentifierEnumZero,
-  AddAccountSectionIdentifier,
-};
-
-typedef NS_ENUM(NSInteger, ItemType) {
-  // IdentitySectionIdentifier section.
-  IdentityItemType = kItemTypeEnumZero,
-  // AddAccountSectionIdentifier section.
-  AddAccountItemType,
-};
-
-// Table view header/footer height.
-CGFloat kSectionHeaderHeight = 8.;
-CGFloat kSectionFooterHeight = 8.;
-
-}  // naemspace
-
 @interface ConsistencyAccountChooserViewController ()
 
+@property(nonatomic, strong)
+    ConsistencyAccountChooserTableViewController* tableViewController;
+
 @end
 
 @implementation ConsistencyAccountChooserViewController
 
-#pragma mark - UITableViewController
-
-- (void)loadModel {
-  [super loadModel];
-  [self loadIdentitySection];
-  [self loadAddAccountSection];
-}
-
-- (void)tableView:(UITableView*)tableView
-    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
-  [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
-  ListItem* item = [self.tableViewModel itemAtIndexPath:indexPath];
-  switch ((ItemType)item.type) {
-    case IdentityItemType: {
-      TableViewIdentityItem* identityItem =
-          base::mac::ObjCCastStrict<TableViewIdentityItem>(item);
-      DCHECK(identityItem);
-      [self.actionDelegate
-          consistencyAccountChooserViewController:self
-                      didSelectIdentityWithGaiaID:identityItem.gaiaID];
-      break;
-    }
-    case AddAccountItemType:
-      [self.actionDelegate
-          consistencyAccountChooserViewControllerDidTapOnAddAccount:self];
-      break;
-  }
-}
-
-- (CGFloat)tableView:(UITableView*)tableView
-    heightForHeaderInSection:(NSInteger)section {
-  return kSectionHeaderHeight;
-}
-
-- (CGFloat)tableView:(UITableView*)tableView
-    heightForFooterInSection:(NSInteger)section {
-  return kSectionFooterHeight;
-}
-
-#pragma mark - UIView
-
 - (void)viewDidLoad {
   [super viewDidLoad];
   self.title = l10n_util::GetNSString(IDS_IOS_CONSISTENCY_PROMO_CHOOSE_ACCOUNT);
-  [self loadModel];
-  [self.tableView reloadData];
+  [self addChildViewController:self.tableViewController];
+  UIView* subView = self.tableViewController.view;
+  subView.translatesAutoresizingMaskIntoConstraints = NO;
+  [self.view addSubview:subView];
+  [NSLayoutConstraint activateConstraints:@[
+    [subView.topAnchor
+        constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
+    [subView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
+    [subView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
+    [subView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
+  ]];
+  [self didMoveToParentViewController:self.tableViewController];
 }
 
-#pragma mark - Private
+#pragma mark - Properties
 
-// Creates the identity section in the table view model.
-- (void)loadIdentitySection {
-  TableViewModel* model = self.tableViewModel;
-  [model addSectionWithIdentifier:IdentitySectionIdentifier];
-  [self loadIdentityItems];
+- (id<ConsistencyAccountChooserTableViewControllerActionDelegate>)
+    actionDelegate {
+  return self.tableViewController.actionDelegate;
 }
 
-// Creates all the identity items in the table view model.
-- (void)loadIdentityItems {
-  TableViewModel* model = self.tableViewModel;
-  for (IdentityItemConfigurator* configurator in self.modelDelegate
-           .sortedIdentityItemConfigurators) {
-    TableViewIdentityItem* item =
-        [[TableViewIdentityItem alloc] initWithType:IdentityItemType];
-    [configurator configureIdentityChooser:item];
-    [model addItem:item toSectionWithIdentifier:IdentitySectionIdentifier];
+- (void)setActionDelegate:
+    (id<ConsistencyAccountChooserTableViewControllerActionDelegate>)
+        actionDelegate {
+  self.tableViewController.actionDelegate = actionDelegate;
+}
+
+- (id<ConsistencyAccountChooserTableViewControllerModelDelegate>)modelDelegate {
+  return self.tableViewController.modelDelegate;
+}
+
+- (void)setModelDelegate:
+    (id<ConsistencyAccountChooserTableViewControllerModelDelegate>)
+        modelDelegate {
+  self.tableViewController.modelDelegate = modelDelegate;
+}
+
+- (id<ConsistencyAccountChooserConsumer>)consumer {
+  return self.tableViewController;
+}
+
+- (ConsistencyAccountChooserTableViewController*)tableViewController {
+  if (!_tableViewController) {
+    UITableViewStyle style = base::FeatureList::IsEnabled(kSettingsRefresh)
+                                 ? ChromeTableViewStyle()
+                                 : UITableViewStylePlain;
+    _tableViewController = [[ConsistencyAccountChooserTableViewController alloc]
+        initWithStyle:style];
   }
-}
-
-// Creates the add account section in the table view model.
-- (void)loadAddAccountSection {
-  TableViewModel* model = self.tableViewModel;
-  [model addSectionWithIdentifier:AddAccountSectionIdentifier];
-  TableViewImageItem* item =
-      [[TableViewImageItem alloc] initWithType:AddAccountItemType];
-  item.title = l10n_util::GetNSString(IDS_IOS_CONSISTENCY_PROMO_ADD_ACCOUNT);
-  item.textColor = [UIColor colorNamed:kBlueColor];
-  [model addItem:item toSectionWithIdentifier:AddAccountSectionIdentifier];
+  return _tableViewController;
 }
 
 #pragma mark - ChildBottomSheetViewController
@@ -138,27 +93,4 @@
   return MAX(screenHeight / 2., firstViewHeight);
 }
 
-#pragma mark - ConsistencyAccountChooserConsumer
-
-- (void)reloadAllIdentities {
-  TableViewModel* model = self.tableViewModel;
-  [model deleteAllItemsFromSectionWithIdentifier:IdentitySectionIdentifier];
-  [self loadIdentityItems];
-  [self.tableView reloadData];
-}
-
-- (void)reloadIdentityForIdentityItemConfigurator:
-    (IdentityItemConfigurator*)configurator {
-  TableViewModel* model = self.tableViewModel;
-  NSArray* items =
-      [model itemsInSectionWithIdentifier:IdentitySectionIdentifier];
-  for (TableViewIdentityItem* item in items) {
-    if ([item.gaiaID isEqual:configurator.gaiaID]) {
-      [configurator configureIdentityChooser:item];
-      [self reconfigureCellsForItems:@[ item ]];
-      break;
-    }
-  }
-}
-
 @end
diff --git a/ios/chrome/browser/ui/image_util/BUILD.gn b/ios/chrome/browser/ui/image_util/BUILD.gn
index a1a92d8..e148df8 100644
--- a/ios/chrome/browser/ui/image_util/BUILD.gn
+++ b/ios/chrome/browser/ui/image_util/BUILD.gn
@@ -32,8 +32,5 @@
     "//ui/base",
   ]
   frameworks = [ "Photos.framework" ]
-  configs += [
-    "//build/config/compiler:enable_arc",
-    "//build/config/ios:disable_implicit_retain_self_warning",
-  ]
+  configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/chrome/browser/ui/image_util/image_saver.mm b/ios/chrome/browser/ui/image_util/image_saver.mm
index 9c30561..5601c9de 100644
--- a/ios/chrome/browser/ui/image_util/image_saver.mm
+++ b/ios/chrome/browser/ui/image_util/image_saver.mm
@@ -173,25 +173,31 @@
 
 // Called when Chrome has been denied access to the photos or videos and the
 // user cannot change it.
+- (void)displayPrivacyErrorAlertOnMainQueue:(NSString*)errorContent {
+  __weak ImageSaver* weakSelf = self;
+  dispatch_async(dispatch_get_main_queue(), ^{
+    [weakSelf asyncDisplayPrivacyErrorAlertOnMainQueue:errorContent];
+  });
+}
+
+// Async helper implementation of displayPrivacyErrorAlertOnMainQueue.
 // Shows a privacy alert on the main queue, with errorContent as the message.
 // Dismisses previous alert if it has not been dismissed yet.
-- (void)displayPrivacyErrorAlertOnMainQueue:(NSString*)errorContent {
-  dispatch_async(dispatch_get_main_queue(), ^{
-    NSString* title =
-        l10n_util::GetNSString(IDS_IOS_SAVE_IMAGE_PRIVACY_ALERT_TITLE);
-    // Dismiss current alert.
-    [self.alertCoordinator stop];
+- (void)asyncDisplayPrivacyErrorAlertOnMainQueue:(NSString*)errorContent {
+  NSString* title =
+      l10n_util::GetNSString(IDS_IOS_SAVE_IMAGE_PRIVACY_ALERT_TITLE);
+  // Dismiss current alert.
+  [self.alertCoordinator stop];
 
-    self.alertCoordinator = [[AlertCoordinator alloc]
-        initWithBaseViewController:self.baseViewController
-                           browser:_browser
-                             title:title
-                           message:errorContent];
-    [self.alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_OK)
-                                     action:nil
-                                      style:UIAlertActionStyleDefault];
-    [self.alertCoordinator start];
-  });
+  self.alertCoordinator = [[AlertCoordinator alloc]
+      initWithBaseViewController:self.baseViewController
+                         browser:_browser
+                           title:title
+                         message:errorContent];
+  [self.alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_OK)
+                                   action:nil
+                                    style:UIAlertActionStyleDefault];
+  [self.alertCoordinator start];
 }
 
 // Called after the system attempts to write the image to the saved photos
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index 3e040d3..8717d7e 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -247,6 +248,54 @@
   return initialization_result;
 }
 
+// Microphone volume range in decibels.
+struct VolumeRange {
+  float min_volume_db;  // Range minimum.
+  float max_volume_db;  // Range maximum.
+  // The range above is divided into N uniform intervals of size
+  // `volume_step_db`.
+  float volume_step_db;
+};
+
+constexpr int CountVolumeRangeIntervals(VolumeRange range) {
+  DCHECK_LT(range.min_volume_db, range.max_volume_db);
+  DCHECK_GT(range.volume_step_db, 0.0f);
+  return (range.max_volume_db - range.min_volume_db) / range.volume_step_db;
+}
+
+void LogVolumeRangeUmaHistograms(base::Optional<VolumeRange> range) {
+  base::UmaHistogramBoolean("Media.Audio.Capture.Win.VolumeRangeAvailable",
+                            range.has_value());
+  if (!range.has_value()) {
+    return;
+  }
+
+  // Example of volume range returned by the API.
+  constexpr VolumeRange kSampleRange{.min_volume_db = -17.0f,
+                                     .max_volume_db = 30.0f,
+                                     .volume_step_db = 0.03125f};
+  // Log range.
+  constexpr int kMinDb = -60;
+  constexpr int kMaxDb = 60;
+  static_assert(kMinDb < kMaxDb, "");
+  static_assert(kSampleRange.min_volume_db >= kMinDb, "Decrease `kMinDb`.");
+  static_assert(kSampleRange.max_volume_db <= kMaxDb, "Increase `kMaxDb`.");
+  constexpr int kNumBuckets = kMaxDb - kMinDb + 1;
+  base::UmaHistogramCustomCounts("Media.Audio.Capture.Win.VolumeRangeMin",
+                                 std::floor(range->min_volume_db), kMinDb,
+                                 kMaxDb, kNumBuckets);
+  base::UmaHistogramCustomCounts("Media.Audio.Capture.Win.VolumeRangeMax",
+                                 std::ceil(range->max_volume_db), kMinDb,
+                                 kMaxDb, kNumBuckets);
+  // Log number of intervals in the volume range.
+  constexpr int kMaxVolumeSteps = 2000;
+  static_assert(kMaxVolumeSteps > CountVolumeRangeIntervals(kSampleRange),
+                "Increase `kMaxVolumeSteps`.");
+  base::UmaHistogramCustomCounts("Media.Audio.Capture.Win.VolumeRangeNumSteps",
+                                 CountVolumeRangeIntervals(*range), 0,
+                                 kMaxVolumeSteps, kMaxVolumeSteps + 1);
+}
+
 }  // namespace
 
 WASAPIAudioInputStream::WASAPIAudioInputStream(
@@ -510,6 +559,23 @@
     }
   }
 
+  base::Optional<VolumeRange> volume_range;
+  if (add_uma_histogram && system_audio_volume_ &&
+      !AudioDeviceDescription::IsLoopbackDevice(device_id_)) {
+    VolumeRange range;
+    HRESULT hr = system_audio_volume_->GetVolumeRange(
+        &range.min_volume_db, &range.max_volume_db, &range.volume_step_db);
+    if (FAILED(hr)) {
+      SendLogMessage("%s => (ERROR: IAudioEndpointVolume::GetVolumeRange=[%s])",
+                     __func__, ErrorToString(hr).c_str());
+    } else {
+      SendLogMessage("%s => (IAudioEndpointVolume::GetVolumeRange) %f %f %f",
+                     __func__, range.min_volume_db, range.max_volume_db,
+                     range.volume_step_db);
+      volume_range = range;
+    }
+  }
+
   // Stops periodic AGC microphone measurements.
   StopAgc();
 
@@ -538,6 +604,7 @@
     base::UmaHistogramBoolean("Media.Audio.InputVolumeStartsAtZeroWin",
                               audio_session_starts_at_zero_volume_);
     audio_session_starts_at_zero_volume_ = false;
+    LogVolumeRangeUmaHistograms(volume_range);
   }
 
   SendLogMessage(
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 8f353ba..91964ee7 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -3743,15 +3743,15 @@
   // |session_recv_window_size_ - session_unacked_recv_window_bytes_|, if more
   // data are sent by the peer, that means that the receive window is not being
   // respected.
-  if (delta_window_size >
-      session_recv_window_size_ - session_unacked_recv_window_bytes_) {
+  int32_t receiving_window_size =
+      session_recv_window_size_ - session_unacked_recv_window_bytes_;
+  if (delta_window_size > receiving_window_size) {
     RecordProtocolErrorHistogram(PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION);
     DoDrainSession(
         ERR_HTTP2_FLOW_CONTROL_ERROR,
         "delta_window_size is " + base::NumberToString(delta_window_size) +
             " in DecreaseRecvWindowSize, which is larger than the receive " +
-            "window size of " +
-            base::NumberToString(session_recv_window_size_));
+            "window size of " + base::NumberToString(receiving_window_size));
     return;
   }
 
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index db8a513..b20602a 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -4243,7 +4243,7 @@
   spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(
       0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR,
       "delta_window_size is 400 in DecreaseRecvWindowSize, which is larger "
-      "than the receive window size of 500"));
+      "than the receive window size of 300"));
   MockWrite writes[] = {
       CreateMockWrite(goaway, 4),
   };
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index f49826d5..9cc6521 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -180,10 +180,6 @@
       "CoreFoundation.framework",
       "CoreGraphics.framework",
     ]
-
-    # TODO(crbug.com/1203935) Modernize macOS system API usage so that this
-    # flag can be removed.
-    cflags += [ "-Wno-deprecated-declarations" ]
   }
 
   if (is_win) {
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index ff9b3e08..90da306 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -128,7 +128,7 @@
     __block auto block_callback = std::move(callback);
     [CATransaction setCompletionBlock:^{
       NSInteger selection = [panel runModalWithPrintInfo:print_info];
-      if (selection == NSOKButton) {
+      if (selection == NSModalResponseOK) {
         print_info_.reset([[panel printInfo] retain]);
         settings_->set_ranges(GetPageRangesFromPrintInfo());
         InitPrintSettingsFromPrintInfo();
diff --git a/sql/initialization.cc b/sql/initialization.cc
index 4fa0bc07..58a1ed7a 100644
--- a/sql/initialization.cc
+++ b/sql/initialization.cc
@@ -9,6 +9,7 @@
 #include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "third_party/sqlite/sqlite3.h"
 
@@ -52,6 +53,7 @@
 
   static bool first_call = true;
   if (first_call) {
+    TRACE_EVENT0("sql", "EnsureSqliteInitialized");
     sqlite3_initialize();
 
 #if !defined(OS_IOS)
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 7b9e9cd..f2ba934e 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -5051,490 +5051,6 @@
       }
     ]
   },
-  "android-weblayer-marshmallow-x86-rel-tests": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=89",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 89.0.4389.129"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 89.0.4389.129",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.129"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M90/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=90",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.101"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.101",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.101"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M91/out/Release",
-          "--implementation-outdir",
-          ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--client-version=91",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.29"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.29",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.29"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M89/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=89",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 89.0.4389.129"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 89.0.4389.129",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M89",
-              "revision": "version:89.0.4389.129"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M90/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=90",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.101"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.101",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M90",
-              "revision": "version:90.0.4430.101"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      },
-      {
-        "args": [
-          "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
-          "--test-runner-outdir",
-          ".",
-          "--client-outdir",
-          ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M91/out/Release",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--impl-version=91",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.29"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.29",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "chromium/testing/weblayer-x86",
-              "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.29"
-            },
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
-        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
-      }
-    ]
-  },
   "android-weblayer-pie-x86-wpt-fyi-rel": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 5523d2a..14fb7dc 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -53734,6 +53734,490 @@
       }
     ]
   },
+  "android-weblayer-marshmallow-x86-rel-tests": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M89/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=89",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 89.0.4389.129"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 89.0.4389.129",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.129"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M90/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=90",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.101"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 90.0.4430.101",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M90",
+              "revision": "version:90.0.4430.101"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M91/out/Release",
+          "--implementation-outdir",
+          ".",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--client-version=91",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.29"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Client Library Skew Tests For 91.0.4472.29",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M91",
+              "revision": "version:91.0.4472.29"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M89/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=89",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 89.0.4389.129"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 89.0.4389.129",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M89",
+              "revision": "version:89.0.4389.129"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M90/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=90",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.101"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 90.0.4430.101",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M90",
+              "revision": "version:90.0.4430.101"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      },
+      {
+        "args": [
+          "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--test-runner-outdir",
+          ".",
+          "--client-outdir",
+          ".",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M91/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--impl-version=91",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.29"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "name": "weblayer_instrumentation_test_versions_with_chrome_apk_Implementation Library Skew Tests For 91.0.4472.29",
+        "resultdb": {
+          "enable": true
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/testing/weblayer-x86",
+              "location": "weblayer_instrumentation_test_M91",
+              "revision": "version:91.0.4472.29"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "machine_type": "n1-standard-4",
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "weblayer_instrumentation_test_versions_with_chrome_apk",
+        "test_id_prefix": "ninja://weblayer/browser/android/javatests:weblayer_instrumentation_test_versions_with_chrome_apk/"
+      }
+    ]
+  },
   "android-weblayer-oreo-x86-rel-tests": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 67c3ff41..f1417ad 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1282,6 +1282,30 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "cc_unittests_amd64-generic",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "cpu": "x86",
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "cc_unittests",
+        "test_id_prefix": "ninja://cc:cc_unittests/"
+      },
+      {
+        "args": [
+          "--board=amd64-generic",
+          "--use-vm"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "lacros_smoke_tast_tests_amd64-generic",
         "resultdb": {
           "enable": true
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index b02d4d5..8c2283f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -17130,6 +17130,345 @@
         "test": "web_runner_integration_tests",
         "test_id_prefix": "ninja://fuchsia/runners:web_runner_integration_tests/"
       }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "fuchsia_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "depth_capture_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "info_collection",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--expected-vendor-id",
+          "0",
+          "--expected-device-id",
+          "0"
+        ],
+        "isolate_name": "fuchsia_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "trace_test",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_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,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=web-engine-shell",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+        ],
+        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl_conformance_tests",
+        "resultdb": {
+          "enable": true
+        },
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 18
+        },
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
+      }
     ]
   },
   "ios-asan": {
@@ -49665,6 +50004,1116 @@
       }
     ]
   },
+  "linux-lacros-code-coverage": {
+    "additional_compile_targets": [
+      "chrome"
+    ],
+    "gtest_tests": [
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "absl_hardening_tests",
+        "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "accessibility_unittests",
+        "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/"
+      },
+      {
+        "args": [
+          "angle_unittests"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "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
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "app_shell_unittests",
+        "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "aura_unittests",
+        "test_id_prefix": "ninja://ui/aura:aura_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_unittests",
+        "test_id_prefix": "ninja://base:base_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "base_util_unittests",
+        "test_id_prefix": "ninja://base/util:base_util_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "blink_common_unittests",
+        "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "blink_fuzzer_unittests",
+        "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "blink_heap_unittests",
+        "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "blink_platform_unittests",
+        "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "webkit_unit_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "blink_unittests",
+        "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "boringssl_crypto_tests",
+        "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "boringssl_ssl_tests",
+        "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 10
+        },
+        "test": "browser_tests",
+        "test_id_prefix": "ninja://chrome/test:browser_tests/"
+      },
+      {
+        "args": [
+          "--gtest_filter=-*UsingRealWebcam*"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "capture_unittests",
+        "test_id_prefix": "ninja://media/capture:capture_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "cast_unittests",
+        "test_id_prefix": "ninja://media/cast:cast_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "cc_unittests",
+        "test_id_prefix": "ninja://cc:cc_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "chrome_app_unittests",
+        "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "chromedriver_unittests",
+        "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "chromeos_unittests",
+        "test_id_prefix": "ninja://chromeos:chromeos_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "color_unittests",
+        "test_id_prefix": "ninja://ui/color:color_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "components_browsertests",
+        "test_id_prefix": "ninja://components:components_browsertests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "components_unittests",
+        "test_id_prefix": "ninja://components:components_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "compositor_unittests",
+        "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 6
+        },
+        "test": "content_browsertests",
+        "test_id_prefix": "ninja://content/test:content_browsertests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "content_unittests",
+        "test_id_prefix": "ninja://content/test:content_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "crashpad_tests",
+        "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "crypto_unittests",
+        "test_id_prefix": "ninja://crypto:crypto_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "dbus_unittests",
+        "test_id_prefix": "ninja://dbus:dbus_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "device_unittests",
+        "test_id_prefix": "ninja://device:device_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "display_unittests",
+        "test_id_prefix": "ninja://ui/display:display_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "events_unittests",
+        "test_id_prefix": "ninja://ui/events:events_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "extensions_browsertests",
+        "test_id_prefix": "ninja://extensions:extensions_browsertests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "extensions_unittests",
+        "test_id_prefix": "ninja://extensions:extensions_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "filesystem_service_unittests",
+        "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gcm_unit_tests",
+        "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gfx_unittests",
+        "test_id_prefix": "ninja://ui/gfx:gfx_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gin_unittests",
+        "test_id_prefix": "ninja://gin:gin_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "google_apis_unittests",
+        "test_id_prefix": "ninja://google_apis:google_apis_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gpu_unittests",
+        "test_id_prefix": "ninja://gpu:gpu_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "gwp_asan_unittests",
+        "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test": "interactive_ui_tests",
+        "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "ipc_tests",
+        "test_id_prefix": "ninja://ipc:ipc_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "jingle_unittests",
+        "test_id_prefix": "ninja://jingle:jingle_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "lacros_chrome_browsertests",
+        "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "lacros_chrome_unittests",
+        "test_id_prefix": "ninja://chrome/test:lacros_chrome_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "latency_unittests",
+        "test_id_prefix": "ninja://ui/latency:latency_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "libjingle_xmpp_unittests",
+        "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "liburlpattern_unittests",
+        "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "media_blink_unittests",
+        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "media_unittests",
+        "test_id_prefix": "ninja://media:media_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "message_center_unittests",
+        "test_id_prefix": "ninja://ui/message_center:message_center_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "midi_unittests",
+        "test_id_prefix": "ninja://media/midi:midi_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_core_unittests",
+        "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_unittests",
+        "test_id_prefix": "ninja://mojo:mojo_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "nacl_helper_nonsfi_unittests",
+        "test_id_prefix": "ninja://components/nacl/loader:nacl_helper_nonsfi_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "nacl_loader_unittests",
+        "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "native_theme_unittests",
+        "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "net_unittests",
+        "test_id_prefix": "ninja://net:net_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "pdf_unittests",
+        "test_id_prefix": "ninja://pdf:pdf_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "perfetto_unittests",
+        "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "ppapi_unittests",
+        "test_id_prefix": "ninja://ppapi:ppapi_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "printing_unittests",
+        "test_id_prefix": "ninja://printing:printing_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "remoting_unittests",
+        "test_id_prefix": "ninja://remoting:remoting_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "sandbox_linux_unittests",
+        "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "service_manager_unittests",
+        "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "services_unittests",
+        "test_id_prefix": "ninja://services:services_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "shell_dialogs_unittests",
+        "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "skia_unittests",
+        "test_id_prefix": "ninja://skia:skia_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "snapshot_unittests",
+        "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "sql_unittests",
+        "test_id_prefix": "ninja://sql:sql_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "storage_unittests",
+        "test_id_prefix": "ninja://storage:storage_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "sync_integration_tests",
+        "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "traffic_annotation_auditor_unittests",
+        "test_id_prefix": "ninja://tools/traffic_annotation/auditor:traffic_annotation_auditor_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "ui_base_unittests",
+        "test_id_prefix": "ninja://ui/base:ui_base_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "ui_touch_selection_unittests",
+        "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "unit_tests",
+        "test_id_prefix": "ninja://chrome/test:unit_tests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "url_unittests",
+        "test_id_prefix": "ninja://url:url_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "views_unittests",
+        "test_id_prefix": "ninja://ui/views:views_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "viz_unittests",
+        "test_id_prefix": "ninja://components/viz:viz_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "wm_unittests",
+        "test_id_prefix": "ninja://ui/wm:wm_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "wtf_unittests",
+        "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/"
+      },
+      {
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "zlib_unittests",
+        "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/"
+      }
+    ]
+  },
   "linux-lacros-tester-fyi-rel": {
     "additional_compile_targets": [
       "chrome",
@@ -58873,9 +60322,9 @@
               "os": "Mac-11|Mac-10.16"
             }
           ],
-          "hard_timeout": 900,
+          "hard_timeout": 1800,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 20
+          "shards": 12
         },
         "test_id_prefix": "ninja://:blink_web_tests/"
       }
@@ -62678,7 +64127,7 @@
               "os": "Windows-10-18363"
             }
           ],
-          "hard_timeout": 900,
+          "hard_timeout": 1200,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 12
         },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index c4f364d..5c81fa75 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -4539,76 +4539,6 @@
       },
       {
         "args": [
-          "pixel",
-          "--show-stdout",
-          "--browser=web-engine-shell",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--git-revision=${got_revision}"
-        ],
-        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "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,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "idempotent": false,
-          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
-      },
-      {
-        "args": [
-          "screenshot_sync",
-          "--show-stdout",
-          "--browser=web-engine-shell",
-          "--passthrough",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
-        ],
-        "isolate_name": "fuchsia_telemetry_gpu_integration_test",
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
-        },
-        "name": "screenshot_sync_tests",
-        "resultdb": {
-          "enable": true
-        },
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "idempotent": false,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/"
-      },
-      {
-        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=web-engine-shell",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 9c913d8..12bd2d4 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -3638,7 +3638,6 @@
   "Mac10.13 Tests": {
     "gtest_tests": [
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3648,7 +3647,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3657,7 +3656,6 @@
         "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3667,7 +3665,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3679,7 +3677,6 @@
         "args": [
           "angle_unittests"
         ],
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -3689,7 +3686,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3699,7 +3696,6 @@
         "use_isolated_scripts_api": true
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3709,7 +3705,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3718,7 +3714,6 @@
         "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3728,7 +3723,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3737,7 +3732,6 @@
         "test_id_prefix": "ninja://base:base_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3747,7 +3741,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3756,7 +3750,6 @@
         "test_id_prefix": "ninja://base/util:base_util_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3766,7 +3759,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3775,7 +3768,6 @@
         "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3785,7 +3777,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3794,7 +3786,6 @@
         "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3804,7 +3795,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3813,7 +3804,6 @@
         "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3823,7 +3813,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3832,7 +3822,6 @@
         "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3843,7 +3832,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3852,7 +3841,6 @@
         "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3862,7 +3850,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3871,7 +3859,6 @@
         "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3881,7 +3868,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3893,7 +3880,6 @@
         "args": [
           "--gtest_filter=-*UsingRealWebcam*"
         ],
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3903,7 +3889,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3912,7 +3898,6 @@
         "test_id_prefix": "ninja://media/capture:capture_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3922,7 +3907,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3931,7 +3916,6 @@
         "test_id_prefix": "ninja://media/cast:cast_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3941,7 +3925,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3950,7 +3934,6 @@
         "test_id_prefix": "ninja://cc:cc_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3960,7 +3943,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3969,7 +3952,6 @@
         "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3979,7 +3961,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -3988,7 +3970,6 @@
         "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3998,7 +3979,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4007,7 +3988,6 @@
         "test_id_prefix": "ninja://components:components_browsertests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4017,7 +3997,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4026,7 +4006,6 @@
         "test_id_prefix": "ninja://components:components_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4036,7 +4015,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -4046,7 +4025,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4056,7 +4034,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4065,7 +4043,6 @@
         "test_id_prefix": "ninja://content/test:content_nocompile_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4075,7 +4052,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4084,7 +4061,6 @@
         "test_id_prefix": "ninja://content/test:content_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4094,7 +4070,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4103,7 +4079,6 @@
         "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4113,7 +4088,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4122,7 +4097,6 @@
         "test_id_prefix": "ninja://components/cronet:cronet_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4132,7 +4106,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4141,7 +4115,6 @@
         "test_id_prefix": "ninja://components/cronet:cronet_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4151,7 +4124,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4160,7 +4133,6 @@
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4170,7 +4142,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4179,7 +4151,6 @@
         "test_id_prefix": "ninja://device:device_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4189,7 +4160,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4198,7 +4169,6 @@
         "test_id_prefix": "ninja://ui/display:display_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4208,7 +4178,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4217,7 +4187,6 @@
         "test_id_prefix": "ninja://ui/events:events_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4227,7 +4196,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4236,7 +4205,6 @@
         "test_id_prefix": "ninja://extensions:extensions_browsertests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4246,7 +4214,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4255,7 +4223,6 @@
         "test_id_prefix": "ninja://extensions:extensions_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4265,7 +4232,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4274,7 +4241,6 @@
         "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4284,7 +4250,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4293,7 +4259,6 @@
         "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4303,7 +4268,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4312,7 +4277,6 @@
         "test_id_prefix": "ninja://ui/gfx:gfx_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4322,7 +4286,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4331,7 +4295,6 @@
         "test_id_prefix": "ninja://gin:gin_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4341,7 +4304,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4350,7 +4313,6 @@
         "test_id_prefix": "ninja://google_apis:google_apis_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4360,7 +4322,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4369,7 +4331,6 @@
         "test_id_prefix": "ninja://gpu:gpu_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4379,7 +4340,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4388,7 +4349,6 @@
         "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4398,7 +4358,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4407,7 +4367,6 @@
         "test_id_prefix": "ninja://headless:headless_browsertests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4417,7 +4376,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4426,7 +4385,6 @@
         "test_id_prefix": "ninja://headless:headless_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4436,7 +4394,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -4446,7 +4404,6 @@
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4456,7 +4413,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4465,7 +4422,6 @@
         "test_id_prefix": "ninja://ipc:ipc_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4475,7 +4431,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4484,7 +4440,6 @@
         "test_id_prefix": "ninja://jingle:jingle_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4494,7 +4449,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4503,7 +4458,6 @@
         "test_id_prefix": "ninja://ui/latency:latency_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4513,7 +4467,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4522,7 +4476,6 @@
         "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4532,7 +4485,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4541,7 +4494,6 @@
         "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4551,7 +4503,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4560,7 +4512,6 @@
         "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4570,7 +4521,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4579,7 +4530,6 @@
         "test_id_prefix": "ninja://media:media_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4589,7 +4539,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4598,7 +4548,6 @@
         "test_id_prefix": "ninja://ui/message_center:message_center_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4608,7 +4557,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4617,7 +4566,6 @@
         "test_id_prefix": "ninja://media/midi:midi_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4627,7 +4575,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4636,7 +4584,6 @@
         "test_id_prefix": "ninja://mojo:mojo_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4646,7 +4593,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4655,7 +4602,6 @@
         "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4665,7 +4611,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4674,7 +4620,6 @@
         "test_id_prefix": "ninja://net:net_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4684,7 +4629,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4693,7 +4638,6 @@
         "test_id_prefix": "ninja://chrome/browser/media/router:openscreen_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4703,7 +4647,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4712,7 +4656,6 @@
         "test_id_prefix": "ninja://pdf:pdf_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4722,7 +4665,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4731,7 +4674,6 @@
         "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4741,7 +4683,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4750,7 +4692,6 @@
         "test_id_prefix": "ninja://ppapi:ppapi_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4760,7 +4701,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4769,7 +4710,6 @@
         "test_id_prefix": "ninja://printing:printing_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4779,7 +4719,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4788,7 +4728,6 @@
         "test_id_prefix": "ninja://remoting:remoting_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4798,7 +4737,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4807,7 +4746,6 @@
         "test_id_prefix": "ninja://sandbox/mac:sandbox_mac_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4817,7 +4755,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4826,7 +4764,6 @@
         "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4836,7 +4773,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4845,7 +4782,6 @@
         "test_id_prefix": "ninja://services:services_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4855,7 +4791,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4864,7 +4800,6 @@
         "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4874,7 +4809,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4883,7 +4818,6 @@
         "test_id_prefix": "ninja://skia:skia_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4893,7 +4827,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4902,7 +4836,6 @@
         "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4912,7 +4845,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4921,7 +4854,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4931,7 +4863,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4940,7 +4872,6 @@
         "test_id_prefix": "ninja://storage:storage_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4953,7 +4884,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4962,7 +4893,6 @@
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4972,7 +4902,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -4981,7 +4911,6 @@
         "test_id_prefix": "ninja://ui/base:ui_base_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -4991,7 +4920,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5000,7 +4929,6 @@
         "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5010,7 +4938,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5019,7 +4947,6 @@
         "test_id_prefix": "ninja://chrome/test:unit_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5029,7 +4956,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5038,7 +4965,6 @@
         "test_id_prefix": "ninja://chrome/updater:updater_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5048,7 +4974,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5057,7 +4983,6 @@
         "test_id_prefix": "ninja://url:url_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5067,7 +4992,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5076,7 +5001,6 @@
         "test_id_prefix": "ninja://ui/views:views_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5086,7 +5010,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5095,7 +5019,6 @@
         "test_id_prefix": "ninja://components/viz:viz_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5105,7 +5028,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5114,7 +5037,6 @@
         "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5125,7 +5047,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5134,7 +5056,6 @@
         "test_id_prefix": "ninja://chrome/test:xr_browser_tests/"
       },
       {
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5144,7 +5065,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5156,7 +5077,6 @@
     "isolated_scripts": [
       {
         "isolate_name": "blink_python_tests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5170,7 +5090,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5182,7 +5102,6 @@
           "--num-retries=3"
         ],
         "isolate_name": "blink_web_tests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [
             "--verbose"
@@ -5199,7 +5118,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -5212,7 +5131,6 @@
           "--test-type=integration"
         ],
         "isolate_name": "chromedriver_py_tests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5226,7 +5144,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5235,7 +5153,6 @@
       },
       {
         "isolate_name": "chromedriver_replay_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5246,7 +5163,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5258,7 +5175,6 @@
           "--gtest-benchmark-name=components_perftests"
         ],
         "isolate_name": "components_perftests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [
             "--smoke-test-mode"
@@ -5271,7 +5187,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5280,7 +5196,6 @@
       },
       {
         "isolate_name": "content_shell_crash_test",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5295,7 +5210,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5304,7 +5219,6 @@
       },
       {
         "isolate_name": "flatbuffers_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5319,7 +5233,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5328,7 +5242,6 @@
       },
       {
         "isolate_name": "grit_python_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5342,7 +5255,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5351,7 +5264,6 @@
       },
       {
         "isolate_name": "mac_signing_tests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5362,7 +5274,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5371,7 +5283,6 @@
       },
       {
         "isolate_name": "metrics_python_tests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5385,7 +5296,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5394,7 +5305,6 @@
       },
       {
         "isolate_name": "mojo_python_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5408,7 +5318,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -5417,7 +5327,6 @@
       },
       {
         "isolate_name": "telemetry_gpu_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5431,7 +5340,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "idempotent": false,
@@ -5445,7 +5354,6 @@
           "--extra-browser-args=--disable-gpu"
         ],
         "isolate_name": "telemetry_unittests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
@@ -5459,7 +5367,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "idempotent": false,
@@ -5473,7 +5381,6 @@
           "--gtest-benchmark-name=views_perftests"
         ],
         "isolate_name": "views_perftests",
-        "isolate_profile_data": true,
         "merge": {
           "args": [
             "--smoke-test-mode"
@@ -5486,7 +5393,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "os": "Mac-10.15"
+              "os": "Mac-10.13.6"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -10794,9 +10701,6 @@
           "script": "//tools/perf/process_perf_results.py"
         },
         "name": "performance_test_suite",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index f0b994c1b..65c179a 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -5974,9 +5974,6 @@
           "script": "//tools/perf/process_perf_results.py"
         },
         "name": "performance_test_suite",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -9077,9 +9074,6 @@
           "script": "//tools/perf/process_perf_results.py"
         },
         "name": "performance_test_suite",
-        "resultdb": {
-          "enable": true
-        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "hard_timeout": 960,
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 83352887..14ac0ed1 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -160,6 +160,12 @@
       },
     },
   },
+  'aura_unittests_amd64-generic': {
+    'remove_from': [
+      # TODO(crbug.com/1204231): Re-enable.
+      'lacros-amd64-generic-rel',
+    ]
+  },
   'base_unittests': {
     'modifications': {
       'android-11-x86-fyi-rel': {
@@ -498,7 +504,14 @@
       },
       'mac11.0-blink-rel-dummy': {
         'swarming': {
-          'shards': 20,
+          # Increase timeout and reduce shards.
+          'shards': 12,
+          'hard_timeout': 1800,
+        },
+      },
+      'win10-blink-rel-dummy': {
+        'swarming': {
+          'hard_timeout': 1200,
         },
       },
     },
@@ -1832,6 +1845,12 @@
       },
     },
   },
+  'interactive_ui_tests_amd64-generic': {
+    'remove_from': [
+      # TODO(crbug.com/1204231): Re-enable.
+      'lacros-amd64-generic-rel',
+    ]
+  },
   'interactive_ui_tests_wayland': {
     'modifications': {
       # CQ tester.
@@ -2317,6 +2336,12 @@
       },
     },
   },
+  'ozone_unittests_amd64-generic': {
+    'remove_from': [
+      # TODO(crbug.com/1204231): Re-enable.
+      'lacros-amd64-generic-rel',
+    ]
+  },
   'perfetto_unittests': {
     'remove_from': [
       # TODO(crbug.com/931138): Fix permission issue when creating tmp files
@@ -2438,6 +2463,11 @@
       },
     },
   },
+  'pixel_tests': {
+    'remove_from': [
+      'Fuchsia x64' # https://crbug.com/1203236
+    ],
+  },
   'rendering_representative_perf_tests': {
     'modifications': {
       'Win10 FYI x64 Exp Release (Intel HD 630)': {
@@ -2499,6 +2529,11 @@
       'android-asan',  # https://crbug.com/962650
     ],
   },
+  'screenshot_sync_tests': {
+    'remove_from': [
+      'Fuchsia x64' # https://crbug.com/1203236
+    ],
+  },
   'screenshot_sync_validating_tests': {
     'modifications': {
       'Android FYI Release (Pixel 4)': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 862991e..76131eb 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -4621,9 +4621,6 @@
           ],
           'script': '//tools/perf/process_perf_results.py',
         },
-        'resultdb': {
-          'enable': True,
-        },
       },
     },
 
@@ -7193,6 +7190,20 @@
     },
 
     # TODO(crbug.com/1195415): Add EVE variant once HW arrives and is deployed.
+    'lacros_device_or_vm_tests': {
+      'lacros_smoke_tast_tests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+        ]
+      },
+      'lacros_device_or_vm_gtests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+        ]
+      },
+    },
+
+    # TODO(crbug.com/1195415): Add EVE variant once HW arrives and is deployed.
     'lacros_device_or_vm_tests_fyi': {
       'lacros_all_tast_tests': {
         'variants': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index b3dcbe6..ca94c04 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1170,6 +1170,19 @@
           'gtest_tests': 'android_pie_rel_gtests',
         }
       },
+      'android-weblayer-marshmallow-x86-rel-tests': {
+        'mixins': [
+          'enable_resultdb',
+          'marshmallow-x86-emulator',
+          'emulator-4-cores',
+          'linux-xenial',
+          'x86-64',
+        ],
+        'os_type': 'android',
+        'test_suites': {
+          'gtest_tests': 'android_weblayer_x86_marshmallow_gtests',
+        }
+      },
       'android-weblayer-oreo-x86-rel-tests': {
         'mixins': [
           'enable_resultdb',
@@ -1276,19 +1289,6 @@
           'gtest_tests': 'android_weblayer_x86_10_gtests',
         }
       },
-      'android-weblayer-marshmallow-x86-rel-tests': {
-        'mixins': [
-          'enable_resultdb',
-          'marshmallow-x86-emulator',
-          'emulator-4-cores',
-          'linux-xenial',
-          'x86-64',
-        ],
-        'os_type': 'android',
-        'test_suites': {
-          'gtest_tests': 'android_weblayer_x86_marshmallow_gtests',
-        }
-      },
       'android-weblayer-pie-x86-wpt-fyi-rel': {
         'mixins': [
           'enable_resultdb',
@@ -1713,7 +1713,7 @@
           'chrome',
         ],
         'test_suites': {
-          'gtest_tests': 'lacros_smoke_tast_tests_amd64_generic',
+          'gtest_tests': 'lacros_device_or_vm_tests',
         },
         'os_type': 'chromeos'
       },
@@ -2968,6 +2968,7 @@
           ],
         },
         'test_suites': {
+          'gpu_telemetry_tests': 'fuchsia_gpu_telemetry_tests',
           'gtest_tests': 'web_engine_gtests',
         },
       },
@@ -3243,6 +3244,17 @@
           'gtest_tests': 'fieldtrial_browser_tests',
         },
       },
+      'linux-lacros-code-coverage': {
+        'additional_compile_targets': [
+          'chrome',
+        ],
+        'mixins': [
+          'isolate_profile_data',
+        ],
+        'test_suites': {
+          'gtest_tests': 'linux_lacros_gtests',
+        },
+      },
       'linux-lacros-tester-fyi-rel': {
         'additional_compile_targets': [
           'chrome',
@@ -5151,8 +5163,7 @@
       },
       'Mac10.13 Tests': {
         'mixins': [
-            'isolate_profile_data',
-            'mac_10.15',
+            'mac_10.13',
         ],
         'test_suites': {
           'gtest_tests': 'chromium_mac_gtests_no_nacl',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e09290f..1922c69 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1526,6 +1526,21 @@
             ]
         }
     ],
+    "ChromeCleanupResetShortcuts": [
+        {
+            "platforms": [
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "ChromeCleanupResetShortcuts"
+                    ]
+                }
+            ]
+        }
+    ],
     "ChromeLabs": [
         {
             "platforms": [
@@ -6977,6 +6992,11 @@
             "experiments": [
                 {
                     "name": "Enabled",
+                    "params": {
+                        "disable_background_log_with_TabRanker": "false",
+                        "number_of_oldest_tabs_to_log_with_TabRanker": "0",
+                        "number_of_oldest_tabs_to_score_with_TabRanker": "0"
+                    },
                     "enable_features": [
                         "TabRanker"
                     ]
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index a7ce4f5..ec844c3 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -917,5 +917,18 @@
 const base::Feature kThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes{
     "ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes",
     base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Kill switch for the Fledge Interest Group API, i.e. if disabled, the
+// API exposure will be disabled regardless of the OT config.
+// (See https://github.com/WICG/turtledove/blob/main/FLEDGE.md.)
+// Enables FLEDGE implementation. See https://crbug.com/1186444.
+const base::Feature kFledgeInterestGroups{"kFledgeInterestGroups",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enable the availability of the Fledge interest group API as part of the
+// origin trial.
+const base::Feature kFledgeInterestGroupAPI{"kFledgeInterestGroupAPI",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 6296c354..8107f8aa 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -385,6 +385,10 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes;
 
+// Master control for Fledge Interest Group feature
+BLINK_COMMON_EXPORT extern const base::Feature kFledgeInterestGroups;
+BLINK_COMMON_EXPORT extern const base::Feature kFledgeInterestGroupAPI;
+
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 380444b8..cded22b 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -326,7 +326,8 @@
 
 void NGFragmentItem::ConvertToSVGText(const PhysicalRect& unscaled_rect,
                                       const FloatRect& scaled_rect,
-                                      float length_adjust_scale) {
+                                      float length_adjust_scale,
+                                      float angle) {
   DCHECK(RuntimeEnabledFeatures::SVGTextNGEnabled());
   DCHECK_EQ(Type(), kText);
   auto data = std::make_unique<NGSVGFragmentData>();
@@ -334,6 +335,7 @@
   data->text_offset = std::move(text_.text_offset);
   data->rect = scaled_rect;
   data->length_adjust_scale = length_adjust_scale;
+  data->angle = angle;
   text_.~TextItem();
   new (&svg_text_) SVGTextItem();
   svg_text_.data = std::move(data);
@@ -510,6 +512,60 @@
   return static_cast<TextDirection>(text_direction_);
 }
 
+bool NGFragmentItem::HasSVGTransformForPaint() const {
+  return Type() == kSVGText && (svg_text_.data->length_adjust_scale != 1.0f ||
+                                svg_text_.data->angle != 0.0f);
+}
+
+bool NGFragmentItem::HasSVGTransformForBoundingBox() const {
+  return Type() == kSVGText && svg_text_.data->angle != 0.0f;
+}
+
+AffineTransform NGFragmentItem::BuildSVGTransformForPaint() const {
+  DCHECK_EQ(Type(), kSVGText);
+  const NGSVGFragmentData& svg_data = *svg_text_.data;
+  const bool is_horizontal = IsHorizontal();
+  AffineTransform transform = BuildSVGTransformForBoundingBox();
+  float scale = svg_data.length_adjust_scale;
+  if (scale != 1.0f) {
+    AffineTransform scale_transform;
+    // We'd like to scale only inline-size without moving inline position.
+    if (is_horizontal) {
+      float x = svg_data.rect.X();
+      scale_transform.SetMatrix(scale, 0, 0, 1, x - scale * x, 0);
+    } else {
+      float y = svg_data.rect.Y();
+      scale_transform.SetMatrix(1, 0, 0, scale, 0, y - scale * y);
+    }
+    transform.PreMultiply(scale_transform);
+  }
+  return transform;
+}
+
+AffineTransform NGFragmentItem::BuildSVGTransformForBoundingBox() const {
+  DCHECK_EQ(Type(), kSVGText);
+  const NGSVGFragmentData& svg_data = *svg_text_.data;
+  AffineTransform transform;
+  if (svg_data.angle != 0.0f) {
+    // https://svgwg.org/svg2-draft/text.html#TextElementRotateAttribute
+    // > The supplemental rotation, in degrees, about the current text position
+    //
+    // TODO(crbug.com/1179585): The following code is equivalent to the legacy
+    // SVG. That is to say, rotation around the left edge of the baseline.
+    // However it doesn't look correct for RTL and vertical text.
+    const SimpleFontData* font_data =
+        To<LayoutSVGInlineText>(GetLayoutObject())->ScaledFont().PrimaryFont();
+    float ascent =
+        font_data ? font_data->GetFontMetrics().FixedAscent().ToFloat() : 0.0f;
+    transform.Rotate(svg_data.angle);
+    float y = svg_data.rect.Y() + ascent;
+    transform.SetE(transform.E() + svg_data.rect.X());
+    transform.SetF(transform.F() + y);
+    transform.Translate(-svg_data.rect.X(), -y);
+  }
+  return transform;
+}
+
 String NGFragmentItem::ToString() const {
   // TODO(yosin): Once |NGPaintFragment| is removed, we should get rid of
   // following if-statements.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index ab933cef..24048cd 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -32,6 +32,7 @@
   NGTextOffset text_offset;
   FloatRect rect;
   float length_adjust_scale;
+  float angle;
 };
 
 // This class represents a text run or a box in an inline formatting context.
@@ -122,7 +123,8 @@
   // Make this kSVGText type. |this| type must be kText.
   void ConvertToSVGText(const PhysicalRect& unscaled_rect,
                         const FloatRect& scaled_rect,
-                        float length_adjust_scale);
+                        float length_adjust_scale,
+                        float angle);
 
   // A sequence number of fragments generated from a |LayoutObject|.
   // For line boxes, please see |kInitialLineFragmentId|.
@@ -421,6 +423,19 @@
   const NGSVGFragmentData* SVGFragmentData() const {
     return Type() == kSVGText ? svg_text_.data.get() : nullptr;
   }
+  // Returns true if BuildSVGTransformForPaint() returns non-identity transform.
+  bool HasSVGTransformForPaint() const;
+  // A transform which should be used on painting this fragment.
+  // This contains a transform for lengthAdjust=spacingAndGlyphs.
+  AffineTransform BuildSVGTransformForPaint() const;
+  // Returns true if BuildSVGTransformForBoundingBox() returns non-identity
+  // transform.
+  bool HasSVGTransformForBoundingBox() const;
+  // A transform which should be used on computing a bounding box.
+  // This contains no transform for lengthAdjust=spacingAndGlyphs because
+  // FloatRectInContainerFragment() already takes into account of
+  // lengthAdjust=spacingAndGlyphs.
+  AffineTransform BuildSVGTransformForBoundingBox() const;
 
   // Get a description of |this| for the debug purposes.
   String ToString() const;
diff --git a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
index 139257c2..5a08b3d 100644
--- a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
+++ b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
@@ -128,7 +128,10 @@
           continue;
         // Do not use item.RectInContainerFragment() in order to avoid
         // precision loss.
-        bbox.Unite(item.FloatRectInContainerFragment());
+        FloatRect item_rect = item.FloatRectInContainerFragment();
+        if (item.HasSVGTransformForBoundingBox())
+          item_rect = item.BuildSVGTransformForBoundingBox().MapRect(item_rect);
+        bbox.Unite(item_rect);
       }
     }
     bounding_box_ = bbox;
diff --git a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
index 31d0a5e..8f9f10a 100644
--- a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
@@ -103,7 +103,8 @@
   ResolvedIterator iterator(inline_node_.SVGCharacterDataList());
   for (wtf_size_t i = 0; i < result_.size(); ++i) {
     const NGSVGCharacterData& resolve = iterator.AdvanceTo(i);
-    result_[i].rotate = resolve.rotate;
+    if (resolve.HasRotate())
+      result_[i].rotate = resolve.rotate;
     if (resolve.anchored_chunk)
       result_[i].anchored_chunk = true;
   }
@@ -145,7 +146,8 @@
                                LayoutUnit(width / scaling_factor),
                                LayoutUnit(height / scaling_factor));
     item.item.ConvertToSVGText(unscaled_rect, scaled_rect,
-                               info.length_adjust_scale);
+                               info.length_adjust_scale,
+                               info.rotate.value_or(0.0f));
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
index 026fdc6..504c5f74 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
@@ -82,8 +82,12 @@
     for (cursor.MoveToIncludingCulledInline(*this); cursor;
          cursor.MoveToNextForSameLayoutObject()) {
       const NGFragmentItem& item = *cursor.CurrentItem();
-      if (item.Type() == NGFragmentItem::kSVGText)
-        bounds.Unite(item.FloatRectInContainerFragment());
+      if (item.Type() != NGFragmentItem::kSVGText)
+        continue;
+      FloatRect item_rect = item.FloatRectInContainerFragment();
+      if (item.HasSVGTransformForBoundingBox())
+        item_rect = item.BuildSVGTransformForBoundingBox().MapRect(item_rect);
+      bounds.Unite(item_rect);
     }
     return bounds;
   }
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index 20d02db..6f5813d 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -6,6 +6,7 @@
 
 #include <ostream>
 
+#include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
 #include "services/network/public/cpp/features.h"
@@ -435,6 +436,10 @@
       !base::FeatureList::IsEnabled(features::kAppCache)) {
     return false;
   }
+  if (trial_name == "FledgeInterestGroupAPI" &&
+      !base::FeatureList::IsEnabled(features::kFledgeInterestGroups)) {
+    return false;
+  }
   if (trial_name == "TrustTokens" &&
       !base::FeatureList::IsEnabled(network::features::kTrustTokens)) {
     return false;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
index 4fc4a4e..aca4ede1 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -272,22 +272,10 @@
     state_saver.emplace(context);
     context.Scale(1 / scaling_factor, 1 / scaling_factor);
   }
-  if (const auto* svg_data = text_item.SVGFragmentData()) {
-    float scale = svg_data->length_adjust_scale;
-    if (scale != 1.0f) {
-      if (!state_saver)
-        state_saver.emplace(context);
-      AffineTransform transform;
-      // We'd like to scale only inline-size without moving inline position.
-      if (is_horizontal) {
-        float x = svg_data->rect.X();
-        transform.SetMatrix(scale, 0, 0, 1, x - scale * x, 0);
-      } else {
-        float y = svg_data->rect.Y();
-        transform.SetMatrix(1, 0, 0, scale, 0, y - scale * y);
-      }
-      context.ConcatCTM(transform);
-    }
+  if (text_item.HasSVGTransformForPaint()) {
+    if (!state_saver)
+      state_saver.emplace(context);
+    context.ConcatCTM(text_item.BuildSVGTransformForPaint());
   }
   NGTextPainter text_painter(context, font, fragment_paint_info, visual_rect,
                              text_origin, box_rect, is_horizontal);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index beb265ef..54eed64fe 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -627,7 +627,6 @@
     state.direct_compositing_reasons =
         full_context_.direct_compositing_reasons &
         CompositingReason::kDirectReasonsForPaintOffsetTranslationProperty;
-    state.rendering_context_id = context_.current.rendering_context_id;
     if (IsA<LayoutView>(object_)) {
       DCHECK(object_.GetFrame());
       state.flags.is_frame_paint_offset_translation = true;
@@ -2135,7 +2134,6 @@
       state.direct_compositing_reasons =
           full_context_.direct_compositing_reasons &
           CompositingReason::kDirectReasonsForScrollTranslationProperty;
-      state.rendering_context_id = context_.current.rendering_context_id;
       state.scroll = properties_->Scroll();
       // If scroll and transform are both present, we should use the
       // transform property tree node to determine visibility of the
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 7927b088..f81afdf 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -139,6 +139,27 @@
   return ui::IsCellOrTableHeader(AXObject::AriaRoleStringToRoleEnum(role_str));
 }
 
+// How deep can role="presentation" propagate from this node (inclusive)?
+// For example, propagates from table->tbody->tr->td (4).
+// Limiting the depth is an optimization that keeps recursion under control.
+int RolePresentationPropagationDepth(Node* node) {
+  // Check for list markup.
+  if (IsA<HTMLMenuElement>(node) || IsA<HTMLUListElement>(node) ||
+      IsA<HTMLOListElement>(node)) {
+    return 2;
+  }
+
+  // Check for <table>
+  if (IsA<HTMLTableElement>(node))
+    return 4;  // table section, table row, table cells,
+
+  // Check for display: table CSS.
+  if (node->GetLayoutObject() && node->GetLayoutObject()->IsTable())
+    return 4;
+
+  return 0;
+}
+
 // Return true if whitespace is not necessary to keep adjacent_node separate
 // in screen reader output from surrounding nodes.
 bool CanIgnoreSpaceNextTo(LayoutObject* layout_object,
@@ -1162,15 +1183,18 @@
   return obj;
 }
 
-void AXObjectCacheImpl::RemoveAXObjectsInLayoutSubtree(AXObject* subtree) {
-  if (!subtree)
+void AXObjectCacheImpl::RemoveAXObjectsInLayoutSubtree(AXObject* subtree,
+                                                       int depth) {
+  if (!subtree || depth <= 0)
     return;
 
+  depth--;
+
   LayoutObject* layout_object = subtree->GetLayoutObject();
   if (layout_object) {
     LayoutObject* layout_child = layout_object->SlowFirstChild();
     while (layout_child) {
-      RemoveAXObjectsInLayoutSubtree(Get(layout_child));
+      RemoveAXObjectsInLayoutSubtree(Get(layout_child), depth);
       layout_child = layout_child->NextSibling();
     }
   }
@@ -2441,12 +2465,12 @@
     // AXObject in this method and call ChildrenChangeWithCleanLayout() on the
     // parent so that future updates to its children will create the alert.
     ChildrenChangedWithCleanLayout(nullptr, obj->CachedParentObject());
-    LayoutObject* layout_object = node->GetLayoutObject();
-    if (layout_object && layout_object->IsTable()) {
-      // If role changes on a table, invalidate the entire table subtree as many
-      // objects may suddenly need to change, because presentation is inherited
-      // from the table to rows and cells.
-      RemoveAXObjectsInLayoutSubtree(obj);
+    if (int depth = RolePresentationPropagationDepth(node)) {
+      // If role changes on a table, menu, or list invalidate the subtree of
+      // objects that may require a specific parent role in order to keep their
+      // role. For example, rows and cells require a table ancestor, and list
+      // items require a parent list (must be direct DOM parent).
+      RemoveAXObjectsInLayoutSubtree(obj, depth);
     } else {
       // The children of this thing need to detach from parent.
       Remove(obj);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index 5e7dbd8..e6b2092 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -503,7 +503,7 @@
   void ContainingTableRowsOrColsMaybeChanged(Node*);
 
   // Must be called an entire subtree of accessible objects are no longer valid.
-  void RemoveAXObjectsInLayoutSubtree(AXObject* subtree);
+  void RemoveAXObjectsInLayoutSubtree(AXObject* subtree, int depth);
 
   // Object for HTML validation alerts. Created at most once per object cache.
   AXObject* GetOrCreateValidationMessageObject();
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl b/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
index bbde13d..44f95cbb 100644
--- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
+++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
@@ -7,7 +7,7 @@
 
 [
   ImplementedAs=NavigatorAuction,
-  RuntimeEnabled=FledgeInterestGroups,
+  RuntimeEnabled=FledgeInterestGroupAPI,
   SecureContext
 ] partial interface Navigator {
   [CallWith=ScriptState, Measure, RaisesException]
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 a1de5de..c5d329a 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -687,10 +687,12 @@
 
   // For WebGpu RecyclableCanvasResource.
   void OnAcquireRecyclableCanvasResource() override { EnsureWriteAccess(); }
-  void OnDestroyRecyclableCanvasResource() override {
+  void OnDestroyRecyclableCanvasResource(
+      const gpu::SyncToken& sync_token) override {
     // RecyclableCanvasResource should be the only one that holds onto
     // |resource_|.
     DCHECK(resource_->HasOneRef());
+    resource_->WaitSyncToken(sync_token);
   }
 
   const bool is_accelerated_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index 6d0153a6..708db3ad 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -237,7 +237,8 @@
   // for in the digest.
   const IdentifiabilityPaintOpDigest& GetIdentifiablityPaintOpDigest();
   virtual void OnAcquireRecyclableCanvasResource() {}
-  virtual void OnDestroyRecyclableCanvasResource() {}
+  virtual void OnDestroyRecyclableCanvasResource(
+      const gpu::SyncToken& sync_token) {}
 
  protected:
   class CanvasImageProvider;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
index 5c51e77a..dd58a01 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
@@ -15,7 +15,8 @@
     : context_provider_(std::make_unique<WebGraphicsContext3DProviderWrapper>(
           std::move(context_provider))),
       interface_(GetContextProvider()->WebGPUInterface()),
-      procs_(interface_->GetProcs()) {}
+      procs_(interface_->GetProcs()),
+      recyclable_resource_cache_(interface_) {}
 
 void DawnControlClientHolder::SetLostContextCallback() {
   GetContextProvider()->SetLostContextCallback(WTF::BindRepeating(
diff --git a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
index 94ab5df1..9482ad60 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
@@ -23,10 +23,6 @@
 
 namespace blink {
 
-// TODO(magchen@): Increase the size after the timer for cleaning up stale
-// resources is added.
-constexpr wtf_size_t kWebGPUMaxRecyclableResourceCaches = 4;
-
 // This class holds the WebGPUInterface and a |destroyed_| flag.
 // DawnControlClientHolder::Destroy() should be called to destroy the backing
 // WebGPUInterface.
@@ -59,8 +55,7 @@
   gpu::webgpu::WebGPUInterface* interface_;
   DawnProcTable procs_;
   bool lost_ = false;
-  WebGPURecyclableResourceCache recyclable_resource_cache_{
-      kWebGPUMaxRecyclableResourceCaches};
+  WebGPURecyclableResourceCache recyclable_resource_cache_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
index 6013ff7..4651c0b 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_mailbox_texture.cc
@@ -38,16 +38,12 @@
   DCHECK(canvas_resource->IsValid());
   DCHECK(canvas_resource->IsAccelerated());
 
-  // TODO(magchen@): move WaitSyncToken into ~RecyclableCanvasResource().
-  auto finished_access_callback = WTF::Bind(&CanvasResource::WaitSyncToken,
-                                            WTF::RetainedRef(canvas_resource));
-
   const gpu::Mailbox& mailbox =
       canvas_resource->GetOrCreateGpuMailbox(kUnverifiedSyncToken);
   gpu::SyncToken sync_token = canvas_resource->GetSyncToken();
   return base::AdoptRef(new WebGPUMailboxTexture(
       std::move(dawn_control_client), device, usage, mailbox, sync_token,
-      std::move(finished_access_callback),
+      base::OnceCallback<void(const gpu::SyncToken&)>(),
       std::move(recyclable_canvas_resource)));
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
index 95d4c254..5b4b78f 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.cc
@@ -58,8 +58,8 @@
 }
 
 WebGPURecyclableResourceCache::WebGPURecyclableResourceCache(
-    wtf_size_t capacity)
-    : capacity_(capacity) {
+    gpu::webgpu::WebGPUInterface* webgpu_interface)
+    : webgpu_interface_(webgpu_interface) {
   weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
 }
 
@@ -86,7 +86,11 @@
 
 void WebGPURecyclableResourceCache::OnDestroyRecyclableResource(
     std::unique_ptr<CanvasResourceProvider> resource_provider) {
-  resource_provider->OnDestroyRecyclableCanvasResource();
+  // WaitSyncToken on the canvas resource.
+  gpu::SyncToken finished_access_token;
+  webgpu_interface_->GenUnverifiedSyncTokenCHROMIUM(
+      finished_access_token.GetData());
+  resource_provider->OnDestroyRecyclableCanvasResource(finished_access_token);
 
   // Transfer to |unused_providers_|.  MRU goes to the front.
   unused_providers_.push_front(std::move(resource_provider));
@@ -126,4 +130,9 @@
   return nullptr;
 }
 
+void WebGPURecyclableResourceCache::SetWebGPUInterfaceForTesting(
+    gpu::webgpu::WebGPUInterface* webgpu_interface) {
+  webgpu_interface_ = webgpu_interface;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
index c0201e2..b1ba772 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_RESOURCE_PROVIDER_CACHE_H_
 
 #include "base/threading/thread_checker.h"
+#include "gpu/command_buffer/client/webgpu_interface.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
@@ -49,7 +50,8 @@
 
 class PLATFORM_EXPORT WebGPURecyclableResourceCache {
  public:
-  explicit WebGPURecyclableResourceCache(wtf_size_t capacity);
+  explicit WebGPURecyclableResourceCache(
+      gpu::webgpu::WebGPUInterface* webgpu_interface);
   ~WebGPURecyclableResourceCache() = default;
 
   std::unique_ptr<RecyclableCanvasResource> GetOrCreateCanvasResource(
@@ -62,7 +64,13 @@
   void OnDestroyRecyclableResource(
       std::unique_ptr<CanvasResourceProvider> resource_provider);
 
+  void SetWebGPUInterfaceForTesting(
+      gpu::webgpu::WebGPUInterface* webgpu_interface);
+
  private:
+  // TODO(magchen@): Increase the size after the timer for cleaning up stale
+  // resources is added.
+  static constexpr wtf_size_t kMaxRecyclableResourceCaches = 4;
   using DequeResourceProvider =
       WTF::Deque<std::unique_ptr<CanvasResourceProvider>>;
 
@@ -76,7 +84,9 @@
   DequeResourceProvider unused_providers_;
 
   // The maximum number of unused CanvasResourceProviders that we can cached.
-  const wtf_size_t capacity_;
+  const wtf_size_t capacity_ = kMaxRecyclableResourceCaches;
+
+  gpu::webgpu::WebGPUInterface* webgpu_interface_;
 
   THREAD_CHECKER(thread_checker_);
   base::WeakPtr<WebGPURecyclableResourceCache> weak_ptr_;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
index 2e3aa55..e36e084 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache_test.cc
@@ -24,8 +24,7 @@
   void TearDown() override;
 
  protected:
-  WebGPURecyclableResourceCache recyclable_resource_cache_{
-      kWebGPUMaxRecyclableResourceCaches};
+  WebGPURecyclableResourceCache recyclable_resource_cache_{nullptr};
   scoped_refptr<base::NullTaskRunner> task_runner_;
   std::unique_ptr<base::ThreadTaskRunnerHandle> handle_;
   cc::StubDecodeCache image_decode_cache_;
@@ -38,6 +37,11 @@
   test_context_provider_ = viz::TestContextProvider::Create();
   InitializeSharedGpuContext(test_context_provider_.get(),
                              &image_decode_cache_);
+
+  auto* webgpu_interface = SharedGpuContext::ContextProviderWrapper()
+                               ->ContextProvider()
+                               ->WebGPUInterface();
+  recyclable_resource_cache_.SetWebGPUInterfaceForTesting(webgpu_interface);
 }
 
 void WebGPURecyclableResourceCacheTest::TearDown() {
diff --git a/third_party/blink/renderer/platform/graphics/test/DEPS b/third_party/blink/renderer/platform/graphics/test/DEPS
index 58c1870..08ac18fb 100644
--- a/third_party/blink/renderer/platform/graphics/test/DEPS
+++ b/third_party/blink/renderer/platform/graphics/test/DEPS
@@ -4,5 +4,6 @@
     "+components/viz/test/test_context_provider.h",
     "+gpu/command_buffer/client/gles2_interface_stub.h",
     "+gpu/command_buffer/client/raster_implementation_gles.h",
+    "+gpu/command_buffer/client/webgpu_interface_stub.h",
     "+gpu/config/gpu_feature_info.h",
 ]
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
index 99c4843..bab23053 100644
--- a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
+++ b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
@@ -10,6 +10,7 @@
 #include "components/viz/test/test_context_provider.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/raster_implementation_gles.h"
+#include "gpu/command_buffer/client/webgpu_interface_stub.h"
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
@@ -41,6 +42,8 @@
     raster_interface_ =
         std::make_unique<gpu::raster::RasterImplementationGLES>(gl_, nullptr);
 
+    webgpu_interface_ = std::make_unique<gpu::webgpu::WebGPUInterfaceStub>();
+
     // enable all gpu features.
     for (unsigned feature = 0; feature < gpu::NUMBER_OF_GPU_FEATURE_TYPES;
          ++feature) {
@@ -78,7 +81,9 @@
     return RasterInterface() &&
            RasterInterface()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
   }
-  gpu::webgpu::WebGPUInterface* WebGPUInterface() override { return nullptr; }
+  gpu::webgpu::WebGPUInterface* WebGPUInterface() override {
+    return webgpu_interface_.get();
+  }
 
   bool BindToCurrentThread() override { return false; }
   void SetLostContextCallback(base::RepeatingClosure) override {}
@@ -102,6 +107,7 @@
   viz::TestSharedImageInterface test_shared_image_interface_;
   gpu::gles2::GLES2Interface* gl_;
   std::unique_ptr<gpu::raster::RasterInterface> raster_interface_;
+  std::unique_ptr<gpu::webgpu::WebGPUInterfaceStub> webgpu_interface_;
   sk_sp<GrDirectContext> gr_context_;
   gpu::Capabilities capabilities_;
   gpu::GpuFeatureInfo gpu_feature_info_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7dc97f5..1e74857 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -952,8 +952,8 @@
       status: "experimental",
     },
     {
-      name: "FledgeInterestGroups",
-      origin_trial_feature_name: "FledgeInterestGroups",
+      name: "FledgeInterestGroupAPI",
+      origin_trial_feature_name: "FledgeInterestGroupAPI",
     },
     {
       name: "FocuslessSpatialNavigation",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 026c29e..ab4d63ad 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -485,7 +485,6 @@
       virtual_time_pause_count(0),
       max_virtual_time_task_starvation_count(0),
       virtual_time_stopped(false),
-      nested_runloop(false),
       prioritize_compositing_after_input(
           false,
           "Scheduler.PrioritizeCompositingAfterInput",
@@ -503,6 +502,10 @@
 
 MainThreadSchedulerImpl::MainThreadOnly::~MainThreadOnly() = default;
 
+bool MainThreadSchedulerImpl::MainThreadOnly::IsInNestedRunloop() {
+  return nested_runloop_depth != 0;
+}
+
 MainThreadSchedulerImpl::AnyThread::AnyThread(
     MainThreadSchedulerImpl* main_thread_scheduler_impl)
     : awaiting_touch_start_response(
@@ -2035,7 +2038,7 @@
     case VirtualTimePolicy::kAdvance:
       if (virtual_time_domain_) {
         virtual_time_domain_->SetMaxVirtualTimeTaskStarvationCount(
-            main_thread_only().nested_runloop
+            main_thread_only().IsInNestedRunloop()
                 ? 0
                 : main_thread_only().max_virtual_time_task_starvation_count);
         virtual_time_domain_->SetVirtualTimeFence(base::TimeTicks());
@@ -2052,7 +2055,7 @@
     case VirtualTimePolicy::kDeterministicLoading:
       if (virtual_time_domain_) {
         virtual_time_domain_->SetMaxVirtualTimeTaskStarvationCount(
-            main_thread_only().nested_runloop
+            main_thread_only().IsInNestedRunloop()
                 ? 0
                 : main_thread_only().max_virtual_time_task_starvation_count);
       }
@@ -2062,7 +2065,7 @@
       // system. We also pause while the renderer is waiting for various
       // asynchronous things e.g. resource load or navigation.
       SetVirtualTimeStopped(main_thread_only().virtual_time_pause_count != 0 ||
-                            main_thread_only().nested_runloop);
+                            main_thread_only().IsInNestedRunloop());
       break;
   }
 }
@@ -2680,7 +2683,7 @@
   }
 
   main_thread_only().running_queues.push(queue);
-  if (main_thread_only().nested_runloop)
+  if (main_thread_only().IsInNestedRunloop())
     return;
 
   main_thread_only().current_task_start_time = task_timing.start_time();
@@ -2718,7 +2721,7 @@
   if (scheduling_settings().mbi_override_task_runner_handle)
     EndAgentGroupSchedulerScope();
 
-  if (main_thread_only().nested_runloop)
+  if (main_thread_only().IsInNestedRunloop())
     return;
 
   DispatchOnTaskCompletionCallbacks();
@@ -2861,13 +2864,13 @@
 
 void MainThreadSchedulerImpl::OnBeginNestedRunLoop() {
   DCHECK(!main_thread_only().running_queues.empty());
-  main_thread_only().nested_runloop = true;
+  main_thread_only().nested_runloop_depth++;
   ApplyVirtualTimePolicy();
 }
 
 void MainThreadSchedulerImpl::OnExitNestedRunLoop() {
   DCHECK(!main_thread_only().running_queues.empty());
-  main_thread_only().nested_runloop = false;
+  main_thread_only().nested_runloop_depth--;
   ApplyVirtualTimePolicy();
 }
 
@@ -3021,13 +3024,13 @@
 
 void MainThreadSchedulerImpl::OnSafepointEntered() {
   DCHECK(WTF::IsMainThread());
-  DCHECK(!main_thread_only().nested_runloop);
+  DCHECK(!main_thread_only().IsInNestedRunloop());
   main_thread_only().metrics_helper.OnSafepointEntered(helper_.NowTicks());
 }
 
 void MainThreadSchedulerImpl::OnSafepointExited() {
   DCHECK(WTF::IsMainThread());
-  DCHECK(!main_thread_only().nested_runloop);
+  DCHECK(!main_thread_only().IsInNestedRunloop());
   main_thread_only().metrics_helper.OnSafepointExited(helper_.NowTicks());
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index f402f39..6771de5 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -876,6 +876,8 @@
         base::TimeTicks now);
     ~MainThreadOnly();
 
+    bool IsInNestedRunloop();
+
     IdleTimeEstimator idle_time_estimator;
     TraceableState<UseCase, TracingCategoryName::kDefault> current_use_case;
     Policy current_policy;
@@ -953,8 +955,8 @@
                std::vector<scoped_refptr<MainThreadTaskQueue>>>
         running_queues;
 
-    // True if a nested RunLoop is running.
-    bool nested_runloop;
+    // Depth of nested_runloop.
+    int nested_runloop_depth = 0;
 
     // High-priority for compositing events after input. This will cause
     // compositing events get a higher priority until the start of the next
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f2ab9c1..faa1fe4 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4090,7 +4090,6 @@
 crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-031.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-035.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/alignment/grid-alignment-implies-size-change-036.html [ Failure ]
-crbug.com/1202031 external/wpt/css/css-grid/alignment/grid-baseline-004.html [ Failure ]
 crbug.com/941987 external/wpt/css/css-grid/alignment/grid-baseline-align-cycles-001.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-001.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-002.html [ Failure ]
@@ -4102,9 +4101,7 @@
 crbug.com/759665 external/wpt/css/css-grid/animation/grid-template-rows-001.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/layout-algorithm/flex-sizing-rows-indefinite-height.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-002.html [ Failure ]
-crbug.com/935102 external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-001.html [ Failure ]
 crbug.com/935102 external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-002.html [ Failure ]
-crbug.com/1024927 external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-003.html [ Failure ]
 crbug.com/707359 [ Mac ] external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-003.html [ Failure ]
 crbug.com/1102918 external/wpt/css/css-grid/grid-definition/grid-auto-fill-columns-001.html [ Failure ]
 crbug.com/1102918 external/wpt/css/css-grid/grid-definition/grid-auto-fill-rows-001.html [ Failure ]
@@ -4114,27 +4111,12 @@
 crbug.com/1045599 external/wpt/css/css-grid/grid-definition/grid-auto-repeat-aspect-ratio-002.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/grid-definition/grid-auto-repeat-dynamic-001.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/grid-definition/grid-auto-repeat-dynamic-003.html [ Failure ]
-crbug.com/1005519 external/wpt/css/css-grid/grid-definition/grid-auto-repeat-max-size-001.html [ Failure ]
-crbug.com/1024927 external/wpt/css/css-grid/grid-definition/grid-inline-template-columns-rows-resolved-values-001.tentative.html [ Failure ]
-crbug.com/1053825 external/wpt/css/css-grid/grid-definition/grid-limits-001.html [ Failure ]
-crbug.com/1024927 external/wpt/css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.tentative.html [ Failure ]
 crbug.com/1114280 external/wpt/css/css-grid/grid-items/aspect-ratio-004.html [ Failure ]
-crbug.com/511177 external/wpt/css/css-grid/grid-layout-properties.html [ Failure ]
 crbug.com/1053825 external/wpt/css/css-grid/grid-model/grid-overflow-padding-001.html [ Failure ]
 crbug.com/1053825 external/wpt/css/css-grid/grid-model/grid-overflow-padding-002.html [ Failure ]
 crbug.com/1053825 external/wpt/css/css-grid/grid-model/grid-areas-overflowing-grid-container-001.html [ Failure ]
 crbug.com/1053825 external/wpt/css/css-grid/grid-model/grid-areas-overflowing-grid-container-002.html [ Failure ]
 crbug.com/1053825 external/wpt/css/css-grid/grid-model/grid-areas-overflowing-grid-container-003.html [ Failure ]
-crbug.com/916827 external/wpt/css/css-grid/parsing/grid-area-computed.html [ Failure ]
-crbug.com/511177 external/wpt/css/css-grid/parsing/grid-area-valid.html [ Failure ]
-crbug.com/1156390 external/wpt/css/css-grid/parsing/grid-auto-flow-computed.html [ Failure ]
-crbug.com/1156390 external/wpt/css/css-grid/parsing/grid-auto-flow-valid.html [ Failure ]
-crbug.com/1050968 external/wpt/css/css-grid/parsing/grid-columns-rows-get-set-multiple.html [ Failure ]
-crbug.com/1028283 external/wpt/css/css-grid/parsing/grid-shorthand-valid.html [ Failure ]
-crbug.com/501673 external/wpt/css/css-grid/parsing/grid-shorthand.html [ Failure ]
-crbug.com/989004 external/wpt/css/css-grid/parsing/grid-template-columns-computed-nogrid.html [ Failure ]
-crbug.com/989004 external/wpt/css/css-grid/parsing/grid-template-rows-computed-nogrid.html [ Failure ]
-crbug.com/1028283 external/wpt/css/css-grid/parsing/grid-template-shorthand-valid.html [ Failure ]
 crbug.com/1045599 fast/css-grid-layout/maximize-tracks-definite-indefinite-height.html [ Failure ]
 
 # Bad stretching of svgs without aspect-ratio.
@@ -4244,6 +4226,7 @@
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html [ Crash Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-negative-indices-003.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-align-justify-overflow.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-004.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-self-baseline-synthesized-001.html [ Failure ]
@@ -4265,14 +4248,14 @@
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-002.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-003.html [ Failure ]
-crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/animation/grid-template-columns-001.html [ Failure ]
-crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/animation/grid-template-rows-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-definition/grid-auto-repeat-intrinsic-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-definition/grid-change-fit-content-argument-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-definition/grid-change-intrinsic-size-with-auto-repeat-tracks-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-as-flex-item-should-not-shrink-to-fit-007.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-001.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-003.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-fit-content-percentage.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-intrinsic-size-with-orthogonal-items.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/grid-minimum-contribution-baseline-shim-vertical-lr.html [ Failure ]
@@ -4525,7 +4508,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/textPath-change-reference2-using-baseval.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/textPath-change-reference2.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/text-rotated-gradient.svg [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/text-rotation.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/text-whitespace-handling.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/text-x-dy-lists.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/transformed-outlines.svg [ Failure ]
@@ -4556,7 +4538,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-dx-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-dy-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-lengthAdjust-attr.html [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-rotate-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-textLength-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-transform-attr.html [ Pass Failure ]
 crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-x-attr.html [ Failure ]
diff --git a/third_party/blink/web_tests/accessibility/role-change.html b/third_party/blink/web_tests/accessibility/role-change.html
index ea18eb6..b3bc8eb 100644
--- a/third_party/blink/web_tests/accessibility/role-change.html
+++ b/third_party/blink/web_tests/accessibility/role-change.html
@@ -16,6 +16,10 @@
   </tr>
 </table>
 
+<ul role="presentation" id="list1">
+    <li id="listitem1">List item</li>
+</ul>
+
 <canvas id="myCanvas" width="300" height="300">
   <input type="radio" id="input">
 </canvas>
@@ -69,6 +73,23 @@
 }, "Role presentation toggled on table.");
 
 test(function(t) {
+    assert_equals(axElementById('list1'), undefined);
+    assert_equals(axElementById('listitem1').role, "AXRole: AXNone");
+
+    // Change role="presentation"
+    document.getElementById('list1').removeAttribute('role');
+
+    assert_equals(axElementById('list1').role, 'AXRole: AXList');
+    assert_equals(axElementById('listitem1').role, 'AXRole: AXListItem');
+
+    // Change role attribute back to "presentation"
+    document.getElementById('list1').setAttribute('role', 'presentation');
+
+    assert_equals(axElementById('list1'), undefined);
+    assert_equals(axElementById('listitem1').role, "AXRole: AXNone");
+}, "Role presentation toggled on list.");
+
+test(function(t) {
     assert_equals(axElementById('opt1').role, "AXRole: AXListBoxOption");
     assert_equals(axElementById('select1').role, "AXRole: AXListBox");
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-baseline-004-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-baseline-004-expected.txt
new file mode 100644
index 0000000..7d26c42
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-baseline-004-expected.txt
@@ -0,0 +1,75 @@
+This is a testharness.js-based test.
+PASS .grid, container 1
+PASS .grid, container 2
+PASS .grid, container 3
+PASS .grid, container 4
+PASS .grid, container 5
+PASS .grid, container 6
+PASS .grid, container 7
+PASS .grid, container 8
+PASS .grid, container 9
+PASS .grid, container 10
+PASS .grid, container 11
+PASS .grid, container 12
+PASS .grid, container 13
+PASS .grid, container 14
+PASS .grid, container 15
+FAIL .grid, container 16 assert_equals: 
+<div class="container" data-expected-width="480" data-expected-height="250">
+    <div id="first" class="grid twoRows" data-offset-x="0" data-offset-y="80">
+        <div class="firstRowFirstColumn target" data-offset-x="0" data-offset-y="0"></div>
+        <div class="firstRowBothColumn" data-offset-x="0" data-offset-y="15"></div>
+        <div class="bothRowFirstColumn" data-offset-x="0" data-offset-y="10"></div>
+    </div>
+    <div id="second" class="grid threeRows" data-offset-x="160" data-offset-y="55">
+        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="100"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="65"></div>
+        <div class="secondRowSecondColumn style3 alignSelfBaseline target" id="first" data-offset-x="0" data-offset-y="80"></div>
+    </div>
+    <div class="grid empty threeRows" data-offset-x="320" data-offset-y="15">
+        <div class="thirdRowSecondColumn" data-offset-x="50" data-offset-y="110"></div>
+        <div class="secondRowFirstColumn target" data-offset-x="0" data-offset-y="60"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="75"></div>
+    </div>
+</div>
+height expected 250 but got 300
+FAIL .grid, container 17 assert_equals: 
+<div class="container" data-expected-width="480" data-expected-height="250">
+    <div id="first" class="grid twoRows" data-offset-x="0" data-offset-y="80">
+        <div class="firstRowFirstColumn target" data-offset-x="0" data-offset-y="0"></div>
+        <div class="firstRowBothColumn" data-offset-x="0" data-offset-y="15"></div>
+        <div class="bothRowFirstColumn" data-offset-x="0" data-offset-y="10"></div>
+    </div>
+    <div id="second" class="grid threeRows" data-offset-x="160" data-offset-y="55">
+        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="100"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="65"></div>
+        <div class="secondRowSecondColumn style3 alignSelfBaseline target" id="first" data-offset-x="0" data-offset-y="80"></div>
+    </div>
+    <div class="grid empty threeRows" data-offset-x="320" data-offset-y="15">
+        <div class="thirdRowSecondColumn" data-offset-x="50" data-offset-y="110"></div>
+        <div class="secondRowFirstColumn target" data-offset-x="0" data-offset-y="60"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="75"></div>
+    </div>
+</div>
+height expected 250 but got 300
+FAIL .grid, container 18 assert_equals: 
+<div class="container" data-expected-width="480" data-expected-height="250">
+    <div id="first" class="grid twoRows" data-offset-x="0" data-offset-y="80">
+        <div class="firstRowFirstColumn target" data-offset-x="0" data-offset-y="0"></div>
+        <div class="firstRowBothColumn" data-offset-x="0" data-offset-y="15"></div>
+        <div class="bothRowFirstColumn" data-offset-x="0" data-offset-y="10"></div>
+    </div>
+    <div id="second" class="grid threeRows" data-offset-x="160" data-offset-y="55">
+        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="100"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="65"></div>
+        <div class="secondRowSecondColumn style3 alignSelfBaseline target" id="first" data-offset-x="0" data-offset-y="80"></div>
+    </div>
+    <div class="grid empty threeRows" data-offset-x="320" data-offset-y="15">
+        <div class="thirdRowSecondColumn" data-offset-x="50" data-offset-y="110"></div>
+        <div class="secondRowFirstColumn target" data-offset-x="0" data-offset-y="60"></div>
+        <div class="secondRowBothColumn" data-offset-x="0" data-offset-y="75"></div>
+    </div>
+</div>
+height expected 250 but got 300
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-auto-repeat-max-size-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-auto-repeat-max-size-001-expected.txt
new file mode 100644
index 0000000..b48bf64
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-auto-repeat-max-size-001-expected.txt
@@ -0,0 +1,31 @@
+This is a testharness.js-based test.
+PASS .grid 1
+PASS .grid 2
+PASS .grid 3
+PASS .grid 4
+PASS .grid 5
+PASS .grid 6
+PASS .grid 7
+PASS .grid 8
+PASS .grid 9
+PASS .grid 10
+PASS .grid 11
+PASS .grid 12
+PASS .grid 13
+PASS .grid 14
+PASS .grid 15
+FAIL .grid 16 assert_equals: 
+<div class="grid border border-box pad-percent" style="width: min-content; height: min-content;" data-expected-width="300" data-expected-height="160">
+    <div class="item" data-offset-x="130" data-offset-y="80" data-expected-width="100" data-expected-height="50"></div>
+  </div>
+width expected 300 but got 260
+PASS .grid 17
+PASS .grid 18
+FAIL .grid 19 assert_equals: 
+<div class="grid border border-box pad-percent" style="width: max-content; height: max-content;" data-expected-width="300" data-expected-height="160">
+    <div class="item" data-offset-x="130" data-offset-y="80" data-expected-width="100" data-expected-height="50"></div>
+  </div>
+width expected 300 but got 260
+PASS .grid 20
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-inline-template-columns-rows-resolved-values-001.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-inline-template-columns-rows-resolved-values-001.tentative-expected.txt
new file mode 100644
index 0000000..c9eac7b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-inline-template-columns-rows-resolved-values-001.tentative-expected.txt
@@ -0,0 +1,80 @@
+This is a testharness.js-based test.
+Found 76 tests; 40 PASS, 36 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: auto auto; and grid-template-rows: ; assert_in_array: gridTemplateRows value "10px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: auto auto; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateRows value "20px 20px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: ; assert_in_array: gridTemplateRows value "20px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: 50px;
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: 50px 30px;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateRows value "50px 20px 20px" not in array ["50px"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateRows value "50px 30px 20px" not in array ["50px 30px"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px;
+FAIL 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateRows value "50px 20px" not in array ["50px"]
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px;
+PASS 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 50px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 50px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "100px 110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: auto auto; assert_in_array: gridTemplateColumns value "110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: auto auto;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 110px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "100px 60px 50px" not in array ["100px 60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "100px 110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "60px 110px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "60px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "100px 60px 50px" not in array ["100px 60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px;
+PASS 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 70px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 70px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px 70px;
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-limits-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-limits-001-expected.txt
new file mode 100644
index 0000000..335937d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-limits-001-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL repeat(9999) should be supported in both axises assert_equals: repeat(9999, 1px) should make grid height 9999px expected "9999px" but got "1000px"
+FAIL Implicit grid should support lines [-10k, 10k]. assert_equals: Positioning children at lines -10k and 10k should generate 19998 implicit 1px tracks. expected "19998px" but got "1000px"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.tentative-expected.txt
new file mode 100644
index 0000000..c9eac7b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.tentative-expected.txt
@@ -0,0 +1,80 @@
+This is a testharness.js-based test.
+Found 76 tests; 40 PASS, 36 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: auto auto; and grid-template-rows: ; assert_in_array: gridTemplateRows value "10px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: auto auto; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateRows value "20px 20px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: ; assert_in_array: gridTemplateRows value "20px 20px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: ;
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: 50px;
+FAIL 'grid' with: grid-template-columns: ; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "110px" not in array ["none"]
+PASS Children of 'grid' with: grid-template-columns: ; and grid-template-rows: 50px 30px;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateRows value "50px 20px 20px" not in array ["50px"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px;
+FAIL 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateRows value "50px 30px 20px" not in array ["50px 30px"]
+PASS Children of 'grid' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px;
+FAIL 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateRows value "50px 20px" not in array ["50px"]
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px;
+PASS 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+PASS Children of 'grid' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: ;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "110px 0px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 50px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "60px 0px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 50px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px;
+FAIL 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px 50px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px 50px"]
+PASS Children of 'gridItemsPositions' with: grid-template-columns: 60px 50px; and grid-template-rows: 60px 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "100px 110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: auto auto; assert_in_array: gridTemplateColumns value "110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: auto auto;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 110px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "100px 60px 50px" not in array ["100px 60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "100px 110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "110px 50px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: ; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "60px 110px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px; assert_in_array: gridTemplateColumns value "60px 50px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px; assert_in_array: gridTemplateColumns value "100px 60px 50px" not in array ["100px 60px"]
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px;
+PASS 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+PASS Children of 'gridAutoFlowColumn' with: grid-template-columns: 100px 60px; and grid-template-rows: 50px 30px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: ; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: ;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "110px 50px 0px 0px 100px" not in array ["none"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: ; and grid-template-rows: 60px 70px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "60px 50px 0px 0px 100px" not in array ["60px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px; and grid-template-rows: 60px 70px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px;
+FAIL 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px 70px; assert_in_array: gridTemplateColumns value "60px 70px 0px 0px 100px" not in array ["60px 70px"]
+PASS Children of 'gridAutoFlowColumnItemsPositions' with: grid-template-columns: 60px 70px; and grid-template-rows: 60px 70px;
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties-expected.txt
new file mode 100644
index 0000000..780654b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties-expected.txt
@@ -0,0 +1,144 @@
+This is a testharness.js-based test.
+Found 140 tests; 119 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS display: grid
+PASS display: inline-grid
+PASS grid-template-columns
+PASS grid-template-columns.initial
+PASS grid-template-columns.none
+PASS grid-template-columns.<line-names>
+PASS grid-template-columns.<track-size>.auto
+PASS grid-template-columns.<track-size>.<track-breadth>.<length>
+PASS grid-template-columns.<track-size>.<track-breadth>.<percentage>
+PASS grid-template-columns.<track-size>.<track-breadth>.<flex>
+PASS grid-template-columns.<track-size>.<track-breadth>.min-content
+PASS grid-template-columns.<track-size>.<track-breadth>.max-content
+PASS grid-template-columns.<track-size>.<track-breadth>.minmax()
+PASS grid-template-columns.reset
+PASS grid-template-rows
+PASS grid-template-rows.initial
+PASS grid-template-rows.none
+PASS grid-template-rows.<line-names>
+PASS grid-template-rows.<track-size>.auto
+PASS grid-template-rows.<track-size>.<track-breadth>.<length>
+PASS grid-template-rows.<track-size>.<track-breadth>.<percentage>
+PASS grid-template-rows.<track-size>.<track-breadth>.<flex>
+PASS grid-template-rows.<track-size>.<track-breadth>.min-content
+PASS grid-template-rows.<track-size>.<track-breadth>.max-content
+PASS grid-template-rows.<track-size>.<track-breadth>.minmax()
+PASS grid-template-rows.reset
+PASS grid-template-areas
+PASS grid-template-areas.initial
+PASS grid-template-areas.none
+PASS grid-template-areas.<string>+
+PASS grid-template-areas.reset
+PASS grid-template
+FAIL grid-template.initial assert_equals: initial value of grid-template should be 50px 50px 50px / 150px expected "50px 50px 50px / 150px" but got "50px 50px 50px / 150px / none"
+FAIL grid-template.none assert_equals: none expected "50px 50px 50px / 150px" but got "50px 50px 50px / 150px / none"
+FAIL grid-template.<grid-template-rows> / <grid-template-columns> assert_equals: <grid-template-rows> / <grid-template-columns> expected "100px 100px / 200px 200px" but got ""
+FAIL grid-template.<line-names> assert_equals: <line-names> expected "[a] auto [b] auto [c] / [d] auto [e] auto [f]" but got ""
+FAIL grid-template.<string>+ assert_equals: <string>+ expected "\"a b\" \"a b\"" but got ""
+FAIL grid-template.<string><track-size>+ assert_equals: <string><track-size>+ expected "100px / \"a b\" 50px" but got ""
+FAIL grid-template.reset assert_equals: reset expected "50px 50px 50px / 150px" but got "50px 50px 50px / 150px / none"
+PASS grid-auto-columns
+PASS grid-auto-columns.initial
+PASS grid-auto-columns.<track-size>.auto
+PASS grid-auto-columns.<track-size>.<track-breadth>.<length>
+PASS grid-auto-columns.<track-size>.<track-breadth>.<percentage>
+PASS grid-auto-columns.<track-size>.<track-breadth>.<flex>
+PASS grid-auto-columns.<track-size>.<track-breadth>.min-content
+PASS grid-auto-columns.<track-size>.<track-breadth>.max-content
+PASS grid-auto-columns.<track-size>.<track-breadth>.minmax()
+PASS grid-auto-columns.reset
+PASS grid-auto-rows
+PASS grid-auto-rows.initial
+PASS grid-auto-rows.<track-size>.auto
+PASS grid-auto-rows.<track-size>.<track-breadth>.<length>
+PASS grid-auto-rows.<track-size>.<track-breadth>.<percentage>
+PASS grid-auto-rows.<track-size>.<track-breadth>.<flex>
+PASS grid-auto-rows.<track-size>.<track-breadth>.min-content
+PASS grid-auto-rows.<track-size>.<track-breadth>.max-content
+PASS grid-auto-rows.<track-size>.<track-breadth>.minmax()
+PASS grid-auto-rows.reset
+PASS grid-auto-flow
+PASS grid-auto-flow.initial
+PASS grid-auto-flow.row
+PASS grid-auto-flow.column
+FAIL grid-auto-flow.dense assert_equals: dense expected "dense" but got "row dense"
+FAIL grid-auto-flow.row dense assert_equals: row dense expected "dense" but got "row dense"
+PASS grid-auto-flow.column dense
+PASS grid-auto-flow.reset
+PASS grid-row-start
+PASS grid-row-start.initial
+PASS grid-row-start.auto
+PASS grid-row-start.<custom-ident>
+PASS grid-row-start.<integer>
+PASS grid-row-start.<integer> <ident>
+PASS grid-row-start.span <integer>
+PASS grid-row-start.span <custom-ident>
+PASS grid-row-start.span <integer> <custom-ident>
+PASS grid-row-start.reset
+PASS grid-column-start
+PASS grid-column-start.initial
+PASS grid-column-start.auto
+PASS grid-column-start.<custom-ident>
+PASS grid-column-start.<integer>
+PASS grid-column-start.<integer> <ident>
+PASS grid-column-start.span <integer>
+PASS grid-column-start.span <custom-ident>
+PASS grid-column-start.span <integer> <custom-ident>
+PASS grid-column-start.reset
+PASS grid-row-end
+PASS grid-row-end.initial
+PASS grid-row-end.auto
+PASS grid-row-end.<custom-ident>
+PASS grid-row-end.<integer>
+PASS grid-row-end.<integer> <ident>
+PASS grid-row-end.span <integer>
+PASS grid-row-end.span <custom-ident>
+PASS grid-row-end.span <integer> <custom-ident>
+PASS grid-row-end.reset
+PASS grid-column-end
+PASS grid-column-end.initial
+PASS grid-column-end.auto
+PASS grid-column-end.<custom-ident>
+PASS grid-column-end.<integer>
+PASS grid-column-end.<integer> <ident>
+PASS grid-column-end.span <integer>
+PASS grid-column-end.span <custom-ident>
+PASS grid-column-end.span <integer> <custom-ident>
+PASS grid-column-end.reset
+PASS grid-column
+FAIL grid-column.initial assert_equals: initial value of grid-column should be auto expected "auto" but got "auto / auto"
+FAIL grid-column.auto assert_equals: auto expected "auto" but got "auto / auto"
+PASS grid-column.<custom-ident>
+FAIL grid-column.<integer> start assert_equals: <integer> start expected "1" but got "1 / auto"
+PASS grid-column.<integer>
+PASS grid-column.<integer> <ident>
+PASS grid-column.span <integer>
+PASS grid-column.span <custom-ident>
+PASS grid-column.span <integer> <custom-ident>
+FAIL grid-column.reset assert_equals: reset expected "auto" but got "auto / auto"
+PASS grid-row
+FAIL grid-row.initial assert_equals: initial value of grid-row should be auto expected "auto" but got "auto / auto"
+FAIL grid-row.auto assert_equals: auto expected "auto" but got "auto / auto"
+PASS grid-row.<custom-ident>
+FAIL grid-row.<integer> start assert_equals: <integer> start expected "1" but got "1 / auto"
+PASS grid-row.<integer>
+PASS grid-row.<integer> <ident>
+PASS grid-row.span <integer>
+PASS grid-row.span <custom-ident>
+PASS grid-row.span <integer> <custom-ident>
+FAIL grid-row.reset assert_equals: reset expected "auto" but got "auto / auto"
+PASS grid-area
+FAIL grid-area.initial assert_equals: initial value of grid-area should be auto expected "auto" but got "auto / auto / auto / auto"
+FAIL grid-area.auto assert_equals: auto expected "auto" but got "auto / auto / auto / auto"
+PASS grid-area.<custom-ident>
+FAIL grid-area.<integer> start assert_equals: <integer> start expected "1 / 2" but got "1 / 2 / auto / auto"
+PASS grid-area.<integer>
+PASS grid-area.<integer> <ident>
+PASS grid-area.span <integer>
+PASS grid-area.span <custom-ident>
+PASS grid-area.span <integer> <custom-ident>
+FAIL grid-area.reset assert_equals: reset expected "auto" but got "auto / auto / auto / auto"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-001-expected.txt
new file mode 100644
index 0000000..549da5a5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-001-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS 'grid' with: grid-template-columns: 0fr; and grid-template-rows: 0fr;
+PASS 'grid' with: grid-template-columns: 1fr; and grid-template-rows: 1fr;
+PASS 'grid' with: grid-template-columns: 2fr; and grid-template-rows: 2fr;
+PASS 'grid' with: grid-template-columns: minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr);
+PASS 'grid' with: grid-template-columns: minmax(0, .5fr); and grid-template-rows: minmax(0, .5fr);
+PASS 'grid' with: grid-template-columns: minmax(0, 1fr); and grid-template-rows: minmax(0, 1fr);
+PASS 'grid' with: grid-template-columns: minmax(0, 2fr); and grid-template-rows: minmax(0, 2fr);
+PASS 'grid' with: grid-template-columns: minmax(75px, 1fr); and grid-template-rows: minmax(75px, 1fr);
+FAIL 'grid' with: grid-template-columns: 0fr 0fr; and grid-template-rows: 0fr 0fr; assert_in_array: gridTemplateColumns value "0px 0px" not in array ["50px 50px"]
+FAIL 'grid' with: grid-template-columns: 0fr 1fr; and grid-template-rows: 0fr 1fr; assert_in_array: gridTemplateColumns value "0px 50px" not in array ["0px 100px"]
+FAIL 'grid' with: grid-template-columns: 1fr 0fr; and grid-template-rows: 1fr 0fr; assert_in_array: gridTemplateColumns value "50px 0px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 1fr 1fr; and grid-template-rows: 1fr 1fr; assert_in_array: gridTemplateColumns value "25px 25px" not in array ["50px 50px"]
+FAIL 'grid' with: grid-template-columns: 1fr 3fr; and grid-template-rows: 1fr 3fr; assert_in_array: gridTemplateColumns value "12.5px 37.5px" not in array ["25px 75px"]
+FAIL 'grid' with: grid-template-columns: 0fr 0fr 1fr; and grid-template-rows: 0fr 0fr 1fr; assert_in_array: gridTemplateColumns value "0px 0px 50px" not in array ["50px 50px 0px"]
+PASS 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 0fr);
+PASS 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 1fr);
+PASS 'grid' with: grid-template-columns: minmax(15px, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(15px, 0fr) minmax(0, 1fr);
+PASS 'grid' with: grid-template-columns: minmax(20px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(20px, 1fr) minmax(0, 1fr);
+PASS 'grid' with: grid-template-columns: minmax(30px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(30px, 1fr) minmax(0, 1fr);
+FAIL 'grid' with: grid-template-columns: 0fr minmax(0, 0fr); and grid-template-rows: 0fr minmax(0, 0fr); assert_in_array: gridTemplateColumns value "0px 0px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 0fr minmax(0, 1fr); and grid-template-rows: 0fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "0px 50px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 1fr minmax(0, 1fr); and grid-template-rows: 1fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "25px 25px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 1fr minmax(25px, 1fr); and grid-template-rows: 1fr minmax(25px, 1fr); assert_in_array: gridTemplateColumns value "25px 25px" not in array ["75px 25px"]
+FAIL 'grid' with: grid-template-columns: 0fr auto; and grid-template-rows: 0fr auto; assert_in_array: gridTemplateColumns value "0px 50px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 1fr auto; and grid-template-rows: 1fr auto; assert_in_array: gridTemplateColumns value "50px 0px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: 1fr max-content; and grid-template-rows: 1fr max-content; assert_in_array: gridTemplateColumns value "50px 0px" not in array ["100px 0px"]
+FAIL 'grid' with: grid-template-columns: minmax(0, 0fr) auto; and grid-template-rows: minmax(0, 0fr) auto; assert_in_array: gridTemplateColumns value "0px 50px" not in array ["0px 100px"]
+FAIL 'grid' with: grid-template-columns: minmax(0, 1fr) auto; and grid-template-rows: minmax(0, 1fr) auto; assert_in_array: gridTemplateColumns value "50px 0px" not in array ["0px 100px"]
+FAIL 'grid' with: grid-template-columns: minmax(25px, 0fr) auto; and grid-template-rows: minmax(25px, 0fr) auto; assert_in_array: gridTemplateColumns value "25px 25px" not in array ["25px 75px"]
+FAIL 'grid' with: grid-template-columns: minmax(25px, 1fr) auto; and grid-template-rows: minmax(25px, 1fr) auto; assert_in_array: gridTemplateColumns value "50px 0px" not in array ["25px 75px"]
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-003-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-003-expected.txt
new file mode 100644
index 0000000..b2c708e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/grid-flex-track-intrinsic-sizes-003-expected.txt
@@ -0,0 +1,106 @@
+This is a testharness.js-based test.
+Found 102 tests; 78 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS auto min item 'grid' with: grid-template-columns: 0fr; and grid-template-rows: 0fr;
+PASS auto min item 'grid' with: grid-template-columns: 1fr; and grid-template-rows: 1fr;
+PASS auto min item 'grid' with: grid-template-columns: 2fr; and grid-template-rows: 2fr;
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, .5fr); and grid-template-rows: minmax(0, .5fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 1fr); and grid-template-rows: minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 2fr); and grid-template-rows: minmax(0, 2fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(75px, 1fr); and grid-template-rows: minmax(75px, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: 0fr 0fr; and grid-template-rows: 0fr 0fr;
+PASS auto min item 'grid' with: grid-template-columns: 0fr 1fr; and grid-template-rows: 0fr 1fr;
+PASS auto min item 'grid' with: grid-template-columns: 1fr 0fr; and grid-template-rows: 1fr 0fr;
+PASS auto min item 'grid' with: grid-template-columns: 1fr 1fr; and grid-template-rows: 1fr 1fr;
+PASS auto min item 'grid' with: grid-template-columns: 1fr 3fr; and grid-template-rows: 1fr 3fr;
+PASS auto min item 'grid' with: grid-template-columns: 0fr 0fr 1fr; and grid-template-rows: 0fr 0fr 1fr;
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 0fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(15px, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(15px, 0fr) minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(20px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(20px, 1fr) minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: minmax(40px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(40px, 1fr) minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: 0fr minmax(0, 0fr); and grid-template-rows: 0fr minmax(0, 0fr);
+PASS auto min item 'grid' with: grid-template-columns: 0fr minmax(0, 1fr); and grid-template-rows: 0fr minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: 1fr minmax(0, 1fr); and grid-template-rows: 1fr minmax(0, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: 1fr minmax(25px, 1fr); and grid-template-rows: 1fr minmax(25px, 1fr);
+PASS auto min item 'grid' with: grid-template-columns: 0fr min-content; and grid-template-rows: 0fr min-content;
+PASS auto min item 'grid' with: grid-template-columns: 0fr auto; and grid-template-rows: 0fr auto;
+PASS auto min item 'grid' with: grid-template-columns: 0.5fr auto; and grid-template-rows: 0.5fr auto;
+PASS auto min item 'grid' with: grid-template-columns: 1fr auto; and grid-template-rows: 1fr auto;
+PASS auto min item 'grid' with: grid-template-columns: 1fr max-content; and grid-template-rows: 1fr max-content;
+PASS auto min item 'grid' with: grid-template-columns: 1fr min-content; and grid-template-rows: 1fr min-content;
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 0fr) min-content; and grid-template-rows: minmax(0, 0fr) min-content;
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 0fr) auto; and grid-template-rows: minmax(0, 0fr) auto;
+PASS auto min item 'grid' with: grid-template-columns: minmax(0, 1fr) auto; and grid-template-rows: minmax(0, 1fr) auto;
+PASS auto min item 'grid' with: grid-template-columns: minmax(25px, 0fr) auto; and grid-template-rows: minmax(25px, 0fr) auto;
+PASS auto min item 'grid' with: grid-template-columns: minmax(25px, 1fr) auto; and grid-template-rows: minmax(25px, 1fr) auto;
+PASS min-content min item 'grid' with: grid-template-columns: 0fr; and grid-template-rows: 0fr;
+PASS min-content min item 'grid' with: grid-template-columns: 1fr; and grid-template-rows: 1fr;
+PASS min-content min item 'grid' with: grid-template-columns: 2fr; and grid-template-rows: 2fr;
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, .5fr); and grid-template-rows: minmax(0, .5fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 1fr); and grid-template-rows: minmax(0, 1fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 2fr); and grid-template-rows: minmax(0, 2fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(75px, 1fr); and grid-template-rows: minmax(75px, 1fr);
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr 0fr; and grid-template-rows: 0fr 0fr; assert_in_array: gridTemplateColumns value "0px 0px" not in array ["50px 50px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr 1fr; and grid-template-rows: 0fr 1fr; assert_in_array: gridTemplateColumns value "0px 60px" not in array ["0px 100px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr 0fr; and grid-template-rows: 1fr 0fr; assert_in_array: gridTemplateColumns value "60px 0px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr 1fr; and grid-template-rows: 1fr 1fr; assert_in_array: gridTemplateColumns value "30px 30px" not in array ["50px 50px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr 3fr; and grid-template-rows: 1fr 3fr; assert_in_array: gridTemplateColumns value "15px 45px" not in array ["25px 75px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr 0fr 1fr; and grid-template-rows: 0fr 0fr 1fr; assert_in_array: gridTemplateColumns value "0px 0px 60px" not in array ["50px 50px 0px"]
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 0fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 1fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(15px, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(15px, 0fr) minmax(0, 1fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(20px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(20px, 1fr) minmax(0, 1fr);
+PASS min-content min item 'grid' with: grid-template-columns: minmax(40px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(40px, 1fr) minmax(0, 1fr);
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr minmax(0, 0fr); and grid-template-rows: 0fr minmax(0, 0fr); assert_in_array: gridTemplateColumns value "0px 0px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr minmax(0, 1fr); and grid-template-rows: 0fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "0px 60px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr minmax(0, 1fr); and grid-template-rows: 1fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "30px 30px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr minmax(25px, 1fr); and grid-template-rows: 1fr minmax(25px, 1fr); assert_in_array: gridTemplateColumns value "30px 30px" not in array ["75px 25px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr min-content; and grid-template-rows: 0fr min-content; assert_in_array: gridTemplateColumns value "0px 0px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0fr auto; and grid-template-rows: 0fr auto; assert_in_array: gridTemplateColumns value "0px 60px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 0.5fr auto; and grid-template-rows: 0.5fr auto; assert_in_array: gridTemplateColumns value "30px 30px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr auto; and grid-template-rows: 1fr auto; assert_in_array: gridTemplateColumns value "60px 0px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr max-content; and grid-template-rows: 1fr max-content; assert_in_array: gridTemplateColumns value "60px 0px" not in array ["100px 0px"]
+FAIL min-content min item 'grid' with: grid-template-columns: 1fr min-content; and grid-template-rows: 1fr min-content; assert_in_array: gridTemplateColumns value "60px 0px" not in array ["100px 0px"]
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 0fr) min-content; and grid-template-rows: minmax(0, 0fr) min-content;
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 0fr) auto; and grid-template-rows: minmax(0, 0fr) auto;
+PASS min-content min item 'grid' with: grid-template-columns: minmax(0, 1fr) auto; and grid-template-rows: minmax(0, 1fr) auto;
+PASS min-content min item 'grid' with: grid-template-columns: minmax(25px, 0fr) auto; and grid-template-rows: minmax(25px, 0fr) auto;
+PASS min-content min item 'grid' with: grid-template-columns: minmax(25px, 1fr) auto; and grid-template-rows: minmax(25px, 1fr) auto;
+PASS 50px min item 'grid' with: grid-template-columns: 0fr; and grid-template-rows: 0fr;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr; and grid-template-rows: 1fr;
+PASS 50px min item 'grid' with: grid-template-columns: 2fr; and grid-template-rows: 2fr;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, .5fr); and grid-template-rows: minmax(0, .5fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 1fr); and grid-template-rows: minmax(0, 1fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 2fr); and grid-template-rows: minmax(0, 2fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(75px, 1fr); and grid-template-rows: minmax(75px, 1fr);
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr 0fr; and grid-template-rows: 0fr 0fr; assert_in_array: gridTemplateColumns value "0px 0px" not in array ["25px 25px"]
+PASS 50px min item 'grid' with: grid-template-columns: 0fr 1fr; and grid-template-rows: 0fr 1fr;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr 0fr; and grid-template-rows: 1fr 0fr;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr 1fr; and grid-template-rows: 1fr 1fr;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr 3fr; and grid-template-rows: 1fr 3fr;
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr 0fr 1fr; and grid-template-rows: 0fr 0fr 1fr; assert_in_array: gridTemplateColumns value "0px 0px 60px" not in array ["25px 25px 10px"]
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 0fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 0fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(0, 0fr) minmax(0, 1fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(15px, 0fr) minmax(0, 1fr); and grid-template-rows: minmax(15px, 0fr) minmax(0, 1fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(20px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(20px, 1fr) minmax(0, 1fr);
+PASS 50px min item 'grid' with: grid-template-columns: minmax(40px, 1fr) minmax(0, 1fr); and grid-template-rows: minmax(40px, 1fr) minmax(0, 1fr);
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr minmax(0, 0fr); and grid-template-rows: 0fr minmax(0, 0fr); assert_in_array: gridTemplateColumns value "0px 0px" not in array ["50px 0px"]
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr minmax(0, 1fr); and grid-template-rows: 0fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "0px 60px" not in array ["50px 10px"]
+FAIL 50px min item 'grid' with: grid-template-columns: 1fr minmax(0, 1fr); and grid-template-rows: 1fr minmax(0, 1fr); assert_in_array: gridTemplateColumns value "30px 30px" not in array ["50px 10px"]
+PASS 50px min item 'grid' with: grid-template-columns: 1fr minmax(25px, 1fr); and grid-template-rows: 1fr minmax(25px, 1fr);
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr min-content; and grid-template-rows: 0fr min-content; assert_in_array: gridTemplateColumns value "0px 0px" not in array ["50px 0px"]
+FAIL 50px min item 'grid' with: grid-template-columns: 0fr auto; and grid-template-rows: 0fr auto; assert_in_array: gridTemplateColumns value "0px 60px" not in array ["50px 10px"]
+FAIL 50px min item 'grid' with: grid-template-columns: 0.5fr auto; and grid-template-rows: 0.5fr auto; assert_in_array: gridTemplateColumns value "30px 30px" not in array ["50px 10px"]
+PASS 50px min item 'grid' with: grid-template-columns: 1fr auto; and grid-template-rows: 1fr auto;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr max-content; and grid-template-rows: 1fr max-content;
+PASS 50px min item 'grid' with: grid-template-columns: 1fr min-content; and grid-template-rows: 1fr min-content;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 0fr) min-content; and grid-template-rows: minmax(0, 0fr) min-content;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 0fr) auto; and grid-template-rows: minmax(0, 0fr) auto;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(0, 1fr) auto; and grid-template-rows: minmax(0, 1fr) auto;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(25px, 0fr) auto; and grid-template-rows: minmax(25px, 0fr) auto;
+PASS 50px min item 'grid' with: grid-template-columns: minmax(25px, 1fr) auto; and grid-template-rows: minmax(25px, 1fr) auto;
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-computed-expected.txt
new file mode 100644
index 0000000..7572574
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-computed-expected.txt
@@ -0,0 +1,32 @@
+This is a testharness.js-based test.
+PASS Property grid-area value 'auto / auto / auto / auto'
+PASS Property grid-row value 'auto / auto'
+PASS Property grid-column-end value 'auto'
+PASS Property grid-row value '-zπ'
+PASS Property grid-row-start value 'AZ'
+PASS Property grid-column-start value '-_π'
+PASS Property grid-row-end value '_9'
+PASS Property grid-area value '1 / 90 -a- / auto / auto'
+PASS Property grid-row value '2 az / auto'
+PASS Property grid-column value '9 / -19 zA'
+PASS Property grid-row-start value '-19'
+PASS Property grid-row-start value '9 -Z_'
+PASS Property grid-column-start value '-44 Z'
+PASS Property grid-row-end value '1 -πA'
+PASS Property grid-column-end value '5 π_'
+PASS Property grid-area value 'span 2 i / auto / auto / auto'
+PASS Property grid-row value 'span 2 / auto'
+PASS Property grid-column-start value 'span 1 i'
+PASS Property grid-row-end value 'span 2 i'
+PASS Property grid-column-end value 'span 2'
+FAIL Property grid-row-start value 'span i' assert_equals: expected "span i" but got "span 1 i"
+FAIL Property grid-row value 'span i / auto' assert_equals: expected "span i / auto" but got "span 1 i / auto"
+PASS Property grid-area value 'auto / i / auto / i'
+PASS Property grid-area value 'auto / i / 2 j'
+PASS Property grid-area value 'auto / i / 2 j / span 3 k'
+PASS Property grid-row value 'auto / i'
+PASS Property grid-column value '2 j / span 3 k'
+PASS Property grid-column-end value '\31st'
+PASS Property grid-column-end value '\31 st'
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt
new file mode 100644
index 0000000..6ce291e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-valid-expected.txt
@@ -0,0 +1,60 @@
+This is a testharness.js-based test.
+Found 56 tests; 24 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL e.style['grid-area'] = "auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
+FAIL e.style['grid-area'] = "auto / auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
+FAIL e.style['grid-area'] = "auto / auto / auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
+FAIL e.style['grid-area'] = "auto / auto / auto / auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
+FAIL e.style['grid-area'] = "AuTo" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto / auto / auto"
+FAIL e.style['grid-row'] = "auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto"
+FAIL e.style['grid-row'] = "auto/auto" should set the property value assert_equals: serialization should be canonical expected "auto" but got "auto / auto"
+PASS e.style['grid-column-end'] = "AuTo" should set the property value
+FAIL e.style['grid-area'] = "--a" should set the property value assert_equals: serialization should be canonical expected "--a" but got "--a / --a / --a / --a"
+FAIL e.style['grid-row'] = "-zπ" should set the property value assert_equals: serialization should be canonical expected "-zπ" but got "-zπ / -zπ"
+FAIL e.style['grid-row'] = "-zπ/-zπ" should set the property value assert_equals: serialization should be canonical expected "-zπ" but got "-zπ / -zπ"
+FAIL e.style['grid-row'] = "i / i" should set the property value assert_equals: serialization should be canonical expected "i" but got "i / i"
+PASS e.style['grid-row-start'] = "AZ" should set the property value
+PASS e.style['grid-column-start'] = "-_π" should set the property value
+PASS e.style['grid-row-end'] = "_9" should set the property value
+FAIL e.style['grid-area'] = "1" should set the property value assert_equals: serialization should be canonical expected "1" but got "1 / auto / auto / auto"
+FAIL e.style['grid-area'] = "+90 -a-" should set the property value assert_equals: serialization should be canonical expected "90 -a-" but got "90 -a- / auto / auto / auto"
+FAIL e.style['grid-row'] = "az 2" should set the property value assert_equals: serialization should be canonical expected "2 az" but got "2 az / auto"
+FAIL e.style['grid-column'] = "9" should set the property value assert_equals: serialization should be canonical expected "9" but got "9 / auto"
+FAIL e.style['grid-column'] = "-19 zA" should set the property value assert_equals: serialization should be canonical expected "-19 zA" but got "-19 zA / auto"
+FAIL e.style['grid-column'] = "-A0 33" should set the property value assert_equals: serialization should be canonical expected "33 -A0" but got "33 -A0 / auto"
+PASS e.style['grid-row-start'] = "-19" should set the property value
+PASS e.style['grid-row-start'] = "9 -Z_" should set the property value
+PASS e.style['grid-column-start'] = "+90" should set the property value
+PASS e.style['grid-column-start'] = "Z -44" should set the property value
+PASS e.style['grid-row-end'] = "1 -πA" should set the property value
+PASS e.style['grid-column-end'] = "π_ +5" should set the property value
+FAIL e.style['grid-area'] = "span 2 i" should set the property value assert_equals: serialization should be canonical expected "span 2 i" but got "span 2 i / auto / auto / auto"
+FAIL e.style['grid-area'] = "i 2 SpAn" should set the property value assert_equals: serialization should be canonical expected "span 2 i" but got "span 2 i / auto / auto / auto"
+FAIL e.style['grid-row'] = "span 2" should set the property value assert_equals: serialization should be canonical expected "span 2" but got "span 2 / auto"
+FAIL e.style['grid-column'] = "i SpAn" should set the property value assert_equals: serialization should be canonical expected "span i" but got "span i / auto"
+PASS e.style['grid-row-start'] = "span i" should set the property value
+PASS e.style['grid-column-start'] = "SpAn i 2" should set the property value
+PASS e.style['grid-row-end'] = "2 i span" should set the property value
+PASS e.style['grid-column-end'] = "2 SpAn" should set the property value
+FAIL e.style['grid-area'] = "auto / i" should set the property value assert_equals: serialization should be canonical expected "auto / i" but got "auto / i / auto / i"
+FAIL e.style['grid-area'] = "auto / i / auto / i" should set the property value assert_equals: serialization should be canonical expected "auto / i" but got "auto / i / auto / i"
+PASS e.style['grid-area'] = "auto / i / auto / 2 i" should set the property value
+FAIL e.style['grid-area'] = "1 / i  / auto / i" should set the property value assert_equals: serialization should be canonical expected "1 / i" but got "1 / i / auto / i"
+FAIL e.style['grid-area'] = "1 / auto / auto / auto" should set the property value assert_equals: serialization should be canonical expected "1" but got "1 / auto / auto / auto"
+FAIL e.style['grid-area'] = "1 / auto / i / auto" should set the property value assert_equals: serialization should be canonical expected "1 / auto / i" but got "1 / auto / i / auto"
+PASS e.style['grid-area'] = "1 / j / i / k" should set the property value
+FAIL e.style['grid-area'] = "1 / auto / 2 / auto" should set the property value assert_equals: serialization should be canonical expected "1 / auto / 2" but got "1 / auto / 2 / auto"
+PASS e.style['grid-area'] = "1 / i / 2 / auto" should set the property value
+PASS e.style['grid-area'] = "i / i / auto / auto" should set the property value
+FAIL e.style['grid-area'] = "i / auto / i / auto" should set the property value assert_equals: serialization should be canonical expected "i / auto" but got "i / auto / i / auto"
+FAIL e.style['grid-area'] = "auto / i / 2 j" should set the property value assert_equals: serialization should be canonical expected "auto / i / 2 j" but got "auto / i / 2 j / i"
+PASS e.style['grid-area'] = "auto / i / 2 j / span 3 k" should set the property value
+PASS e.style['grid-row'] = "auto / i" should set the property value
+PASS e.style['grid-row'] = "i / auto" should set the property value
+FAIL e.style['grid-row'] = "2 i / auto" should set the property value assert_equals: serialization should be canonical expected "2 i" but got "2 i / auto"
+FAIL e.style['grid-row'] = "1 / auto" should set the property value assert_equals: serialization should be canonical expected "1" but got "1 / auto"
+PASS e.style['grid-column'] = "2 j / span 3 k" should set the property value
+PASS e.style['grid-column-end'] = "\\31st" should set the property value
+PASS e.style['grid-column-end'] = "\\31 st" should set the property value
+FAIL e.style['grid-column'] = "\\31st / \\31 st" should set the property value assert_in_array: serialization should be sound value "\\31 st / \\31 st" not in array ["\\31 st", "\\31st"]
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-computed-expected.txt
new file mode 100644
index 0000000..4d03b54
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-computed-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS Property grid-auto-flow value 'row'
+PASS Property grid-auto-flow value 'column'
+FAIL Property grid-auto-flow value 'row dense' assert_equals: expected "dense" but got "row dense"
+PASS Property grid-auto-flow value 'column dense'
+FAIL Property grid-auto-flow value 'dense row' assert_equals: expected "dense" but got "row dense"
+PASS Property grid-auto-flow value 'dense column'
+FAIL Property grid-auto-flow value 'dense' assert_equals: expected "dense" but got "row dense"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-valid-expected.txt
new file mode 100644
index 0000000..d2139ff
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-flow-valid-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS e.style['grid-auto-flow'] = "row" should set the property value
+PASS e.style['grid-auto-flow'] = "column" should set the property value
+FAIL e.style['grid-auto-flow'] = "row dense" should set the property value assert_equals: serialization should be canonical expected "dense" but got "row dense"
+FAIL e.style['grid-auto-flow'] = "dense row" should set the property value assert_equals: serialization should be canonical expected "dense" but got "row dense"
+PASS e.style['grid-auto-flow'] = "dense" should set the property value
+PASS e.style['grid-auto-flow'] = "column dense" should set the property value
+PASS e.style['grid-auto-flow'] = "dense column" should set the property value
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-columns-rows-get-set-multiple-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-columns-rows-get-set-multiple-expected.txt
new file mode 100644
index 0000000..512bd0d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-columns-rows-get-set-multiple-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithFixedElement' : grid-template-columns = '7px 11px', grid-template-rows = '17px 2px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithPercentElement' : grid-template-columns = '400px 800px', grid-template-rows = '150px 450px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithPercentWithoutSize' : grid-template-columns = '3.5px 7px', grid-template-rows = '4px 12px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithAutoElement' : grid-template-columns = '0px 17px', grid-template-rows = '0px 3px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithEMElement' : grid-template-columns = '100px 120px', grid-template-rows = '150px 170px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithThreeItems' : grid-template-columns = '15px 0px 100px', grid-template-rows = '120px 18px 0px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithFitContentAndFitAvailable' : grid-template-columns = 'none', grid-template-rows = 'none'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithMinMaxContent' : grid-template-columns = '0px 0px', grid-template-rows = '0px 0px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithMinMaxContentWithChildrenElement' : grid-template-columns = '7px 17px', grid-template-rows = '16px 3px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithMinMaxAndFixed' : grid-template-columns = '240px 15px', grid-template-rows = '120px 210px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithMinMaxAndMinMaxContent' : grid-template-columns = '240px 15px', grid-template-rows = '120px 210px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithFractionFraction' : grid-template-columns = '320px 480px', grid-template-rows = '225px 375px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithFractionMinMax' : grid-template-columns = '45px 755px', grid-template-rows = '586px 14px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithCalcCalc' : grid-template-columns = '200px 100px', grid-template-rows = '150px 75px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithCalcAndFixed' : grid-template-columns = '400px 80px', grid-template-rows = '88px 150px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithCalcAndMinMax' : grid-template-columns = '190px 80px', grid-template-rows = '150px 53px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithCalcInsideMinMax' : grid-template-columns = '400px 120px', grid-template-rows = '150px 175px'
+PASS Test getting grid-template-columns and grid-template-rows set through CSS for element 'gridWithAutoInsideMinMax' : grid-template-columns = '0px 30px', grid-template-rows = '132px 60px'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '18px 22px', element.style.gridTemplateColumns = '18px 22px', grid-template-rows = '66px 70px', element.style.gridTemplateRows = '66px 70px'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '440px 640px', element.style.gridTemplateColumns = '55% 80%', grid-template-rows = '240px 378px', element.style.gridTemplateRows = '40% 63%'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '0px 0px', element.style.gridTemplateColumns = 'auto auto', grid-template-rows = '0px 0px', element.style.gridTemplateRows = 'auto auto'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '0px 160px 22px', element.style.gridTemplateColumns = 'auto 16em 22px', grid-template-rows = '336px 100px 0px', element.style.gridTemplateRows = '56% 10em auto'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '160px 20px', element.style.gridTemplateColumns = '16em minmax(16px, 20px)', grid-template-rows = '90px 0px', element.style.gridTemplateRows = 'minmax(10%, 15%) auto'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '160px 640px', element.style.gridTemplateColumns = '16em 2fr', grid-template-rows = '600px 0px', element.style.gridTemplateRows = '14fr auto'
+PASS Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '25px 20px', element.style.gridTemplateColumns = 'calc(25px) calc(2em)', grid-template-rows = '0px 60px', element.style.gridTemplateRows = 'auto calc(10%)'
+FAIL Test getting and setting grid-template-rows and grid-template-columns through JS: grid-template-columns = '345px 92px', element.style.gridTemplateColumns = 'calc(25px + 40%) minmax(min-content, calc(10% + 12px))', grid-template-rows = '100px 0px', element.style.gridTemplateRows = 'minmax(calc(75% - 350px), max-content) auto' assert_equals: expected "calc(40% + 25px) minmax(min-content, calc(10% + 12px))" but got "calc(25px + 40%) minmax(min-content, calc(10% + 12px))"
+PASS Test setting wrong/invalid values through CSS
+PASS Test setting bad JS values: grid-template-columns = 'none auto', grid-template-rows = 'none auto'
+PASS Test setting bad JS values: grid-template-columns = 'none 16em', grid-template-rows = 'none 56%'
+PASS Test setting bad JS values: grid-template-columns = 'none none', grid-template-rows = 'none none'
+PASS Test setting bad JS values: grid-template-columns = 'auto none', grid-template-rows = 'auto none'
+PASS Test setting bad JS values: grid-template-columns = 'auto none 16em', grid-template-rows = 'auto 18em none'
+PASS Test setting bad JS values: grid-template-columns = '-webkit-fit-content -webkit-fit-content', grid-template-rows = '-webkit-fit-available -webkit-fit-available'
+PASS Test setting bad JS values: grid-template-columns = '-10px minmax(16px, 32px)', grid-template-rows = 'minmax(10%, 15%) -10vw'
+PASS Test setting bad JS values: grid-template-columns = '10px minmax(16px, -1vw)', grid-template-rows = 'minmax(-1%, 15%) 10vw'
+PASS Test setting bad JS values: grid-template-columns = '10px calc(16px 30px)', grid-template-rows = 'calc(25px + auto) 2em'
+PASS Test setting bad JS values: grid-template-columns = 'minmax(min-content, calc() 250px', grid-template-rows = 'calc(2em('
+PASS Test setting grid-template-columns and grid-template-rows to 'inherit' through JS
+PASS Test the default value
+PASS Test setting grid-template-columns and grid-template-rows to 'initial' through JS
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-expected.txt
new file mode 100644
index 0000000..d2c4b0fd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-expected.txt
@@ -0,0 +1,60 @@
+This is a testharness.js-based test.
+Found 56 tests; 31 PASS, 25 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL e.style['grid'] = "none" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "none" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = "none" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = "none" should set grid-template-areas
+PASS e.style['grid'] = "none" should set grid-template-columns
+PASS e.style['grid'] = "none" should set grid-template-rows
+PASS e.style['grid'] = "none" should not set unrelated longhands
+FAIL e.style['grid'] = "10px / 20%" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "10px / 20%" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = "10px / 20%" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = "10px / 20%" should set grid-template-areas
+PASS e.style['grid'] = "10px / 20%" should set grid-template-columns
+PASS e.style['grid'] = "10px / 20%" should set grid-template-rows
+PASS e.style['grid'] = "10px / 20%" should not set unrelated longhands
+FAIL e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-template-areas
+PASS e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-template-columns
+PASS e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-template-rows
+PASS e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should not set unrelated longhands
+FAIL e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-template-areas
+PASS e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-template-columns
+PASS e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should set grid-template-rows
+PASS e.style['grid'] = "[header-top] \"a a a\"     [header-bottom]  [main-top] \"b b b\" 1fr [main-bottom]           / auto 1fr auto" should not set unrelated longhands
+FAIL e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-template-areas
+PASS e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-template-columns
+PASS e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should set grid-template-rows
+PASS e.style['grid'] = "  \"a a a\"  \"b b b\" 1fr/ auto 1fr auto" should not set unrelated longhands
+FAIL e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "row" but got "initial"
+FAIL e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+PASS e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-template-areas
+PASS e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-template-columns
+PASS e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should set grid-template-rows
+PASS e.style['grid'] = " [] \"a a a\"     [] [] \"b b b\" 1fr []  / [] auto 1fr [] auto []" should not set unrelated longhands
+PASS e.style['grid'] = "10px / auto-flow dense 20px" should set grid-auto-columns
+PASS e.style['grid'] = "10px / auto-flow dense 20px" should set grid-auto-flow
+FAIL e.style['grid'] = "10px / auto-flow dense 20px" should set grid-auto-rows assert_equals: grid-auto-rows should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "10px / auto-flow dense 20px" should set grid-template-areas assert_equals: grid-template-areas should be canonical expected "none" but got "initial"
+FAIL e.style['grid'] = "10px / auto-flow dense 20px" should set grid-template-columns assert_equals: grid-template-columns should be canonical expected "none" but got "initial"
+PASS e.style['grid'] = "10px / auto-flow dense 20px" should set grid-template-rows
+PASS e.style['grid'] = "10px / auto-flow dense 20px" should not set unrelated longhands
+FAIL e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-auto-columns assert_equals: grid-auto-columns should be canonical expected "auto" but got "initial"
+FAIL e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-auto-flow assert_equals: grid-auto-flow should be canonical expected "dense" but got "row dense"
+PASS e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-auto-rows
+FAIL e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-template-areas assert_equals: grid-template-areas should be canonical expected "none" but got "initial"
+PASS e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-template-columns
+FAIL e.style['grid'] = "auto-flow dense 30px / 40px" should set grid-template-rows assert_equals: grid-template-rows should be canonical expected "none" but got "initial"
+PASS e.style['grid'] = "auto-flow dense 30px / 40px" should not set unrelated longhands
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-valid-expected.txt
new file mode 100644
index 0000000..f6180f7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand-valid-expected.txt
@@ -0,0 +1,40 @@
+This is a testharness.js-based test.
+FAIL e.style['grid'] = "none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "none / none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "auto / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "none / [a] 0px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "none / [] 0px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] 10px / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] 10px / none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[] 10px [] / [] auto []" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\" 10px []" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[] \"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\" 10px [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" / 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" / 20%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" / 5fr" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[] \"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [] [] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] [b] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" / 0" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" 10px / 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] \"b\" 10px [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] [a] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] [] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" 10px [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "[a] \"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" \"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" [a] \"b\" [a] / 0" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid'] = "\"a\" \"a\" [a] [a] \"b\" / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-nogrid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-nogrid-expected.txt
new file mode 100644
index 0000000..e53ace5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-computed-nogrid-expected.txt
@@ -0,0 +1,27 @@
+This is a testharness.js-based test.
+PASS Property grid-template-columns value 'none'
+PASS Property grid-template-columns value '1px'
+PASS Property grid-template-columns value '1px [a]'
+PASS Property grid-template-columns value '1px [a] 2px'
+PASS Property grid-template-columns value '[a] 1px'
+PASS Property grid-template-columns value '[a] 1px [b]'
+FAIL Property grid-template-columns value '1px repeat(1, 2px) 3px' assert_equals: expected "1px repeat(1, 2px) 3px" but got "1px 2px 3px"
+PASS Property grid-template-columns value '1px repeat(auto-fill, 2px) 3px'
+PASS Property grid-template-columns value '1px repeat(auto-fit, 2px) 3px'
+FAIL Property grid-template-columns value '1px [a] repeat(1, 2px 3px) [b] 4px' assert_equals: expected "1px [a] repeat(1, 2px 3px) [b] 4px" but got "1px [a] 2px 3px [b] 4px"
+PASS Property grid-template-columns value '1px [a] repeat(auto-fill, 2px 3px) [b] 4px'
+PASS Property grid-template-columns value '1px [a] repeat(auto-fit, 2px 3px) [b] 4px'
+FAIL Property grid-template-columns value '1px [a] repeat(1, [b] 2px [c]) [d] 3px' assert_equals: expected "1px [a] repeat(1, [b] 2px [c]) [d] 3px" but got "1px [a b] 2px [c d] 3px"
+PASS Property grid-template-columns value '1px [a] repeat(auto-fill, [b] 2px [c]) [d] 3px'
+PASS Property grid-template-columns value '1px [a] repeat(auto-fit, [b] 2px [c]) [d] 3px'
+FAIL Property grid-template-columns value '[a] 1px repeat(1, 2px [b] 3px) 4px [d]' assert_equals: expected "[a] 1px repeat(1, 2px [b] 3px) 4px [d]" but got "[a] 1px 2px [b] 3px 4px [d]"
+PASS Property grid-template-columns value '[a] 1px repeat(auto-fill, 2px [b] 3px) 4px [d]'
+PASS Property grid-template-columns value '[a] 1px repeat(auto-fit, 2px [b] 3px) 4px [d]'
+FAIL Property grid-template-rows value '100% [a] repeat(1, [b] 200% [c]) [d] 300%' assert_equals: expected "100% [a] repeat(1, [b] 200% [c]) [d] 300%" but got "100% [a b] 200% [c d] 300%"
+PASS Property grid-template-rows value '100% [a] repeat(auto-fill, [b] 200% [c]) [d] 300%'
+PASS Property grid-template-rows value '100% [a] repeat(auto-fit, [b] 200% [c]) [d] 300%'
+FAIL Property grid-template-columns value '[a] 1em repeat(1, 2em [b] 3em) 4em [d]' assert_equals: expected "[a] 1px repeat(1, 2px [b] 3px) 4px [d]" but got "[a] 1px 2px [b] 3px 4px [d]"
+PASS Property grid-template-columns value '[a] 1em repeat(auto-fill, 2em [b] 3em) 4em [d]'
+PASS Property grid-template-columns value '[a] 1em repeat(auto-fit, 2em [b] 3em) 4em [d]'
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-nogrid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-nogrid-expected.txt
new file mode 100644
index 0000000..6731882b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-computed-nogrid-expected.txt
@@ -0,0 +1,27 @@
+This is a testharness.js-based test.
+PASS Property grid-template-rows value 'none'
+PASS Property grid-template-rows value '1px'
+PASS Property grid-template-rows value '1px [a]'
+PASS Property grid-template-rows value '1px [a] 2px'
+PASS Property grid-template-rows value '[a] 1px'
+PASS Property grid-template-rows value '[a] 1px [b]'
+FAIL Property grid-template-rows value '1px repeat(1, 2px) 3px' assert_equals: expected "1px repeat(1, 2px) 3px" but got "1px 2px 3px"
+PASS Property grid-template-rows value '1px repeat(auto-fill, 2px) 3px'
+PASS Property grid-template-rows value '1px repeat(auto-fit, 2px) 3px'
+FAIL Property grid-template-rows value '1px [a] repeat(1, 2px 3px) [b] 4px' assert_equals: expected "1px [a] repeat(1, 2px 3px) [b] 4px" but got "1px [a] 2px 3px [b] 4px"
+PASS Property grid-template-rows value '1px [a] repeat(auto-fill, 2px 3px) [b] 4px'
+PASS Property grid-template-rows value '1px [a] repeat(auto-fit, 2px 3px) [b] 4px'
+FAIL Property grid-template-rows value '1px [a] repeat(1, [b] 2px [c]) [d] 3px' assert_equals: expected "1px [a] repeat(1, [b] 2px [c]) [d] 3px" but got "1px [a b] 2px [c d] 3px"
+PASS Property grid-template-rows value '1px [a] repeat(auto-fill, [b] 2px [c]) [d] 3px'
+PASS Property grid-template-rows value '1px [a] repeat(auto-fit, [b] 2px [c]) [d] 3px'
+FAIL Property grid-template-rows value '[a] 1px repeat(1, 2px [b] 3px) 4px [d]' assert_equals: expected "[a] 1px repeat(1, 2px [b] 3px) 4px [d]" but got "[a] 1px 2px [b] 3px 4px [d]"
+PASS Property grid-template-rows value '[a] 1px repeat(auto-fill, 2px [b] 3px) 4px [d]'
+PASS Property grid-template-rows value '[a] 1px repeat(auto-fit, 2px [b] 3px) 4px [d]'
+FAIL Property grid-template-rows value '100% [a] repeat(1, [b] 200% [c]) [d] 300%' assert_equals: expected "100% [a] repeat(1, [b] 200% [c]) [d] 300%" but got "100% [a b] 200% [c d] 300%"
+PASS Property grid-template-rows value '100% [a] repeat(auto-fill, [b] 200% [c]) [d] 300%'
+PASS Property grid-template-rows value '100% [a] repeat(auto-fit, [b] 200% [c]) [d] 300%'
+FAIL Property grid-template-rows value '[a] 1em repeat(1, 2em [b] 3em) 4em [d]' assert_equals: expected "[a] 1px repeat(1, 2px [b] 3px) 4px [d]" but got "[a] 1px 2px [b] 3px 4px [d]"
+PASS Property grid-template-rows value '[a] 1em repeat(auto-fill, 2em [b] 3em) 4em [d]'
+PASS Property grid-template-rows value '[a] 1em repeat(auto-fit, 2em [b] 3em) 4em [d]'
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand-valid-expected.txt
new file mode 100644
index 0000000..ae7aee7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand-valid-expected.txt
@@ -0,0 +1,40 @@
+This is a testharness.js-based test.
+FAIL e.style['grid-template'] = "none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "none / none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "auto / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "none / [a] 0px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "none / [] 0px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] 10px / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] 10px / none" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[] 10px [] / [] auto []" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\" 10px []" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[] \"a\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\" 10px [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" / 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" / 20%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" / 5fr" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[] \"a\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [] [] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] [b] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] \"b\"" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" / 0" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" 10px / 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] \"b\" 10px [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] [a] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] [] \"b\" 10px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" 10px [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "[a] \"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" \"a\" [a] \"b\" [a]" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" [a] \"b\" [a] / 0" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['grid-template'] = "\"a\" \"a\" [a] [a] \"b\" / auto" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-rotate-attr-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-rotate-attr-expected.png
new file mode 100644
index 0000000..cb2f450d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-rotate-attr-expected.png
Binary files differ
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index 6b911e1..80c2b64 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -534,37 +534,52 @@
     c = Code()
     underlying_type = self._type_helper.FollowRef(property.type_)
     underlying_property_type = underlying_type.property_type
+    underlying_item_type = (
+      self._type_helper.FollowRef(underlying_type.item_type)
+      if underlying_property_type is PropertyType.ARRAY
+      else None)
+
     assert (underlying_property_type in supported_property_types), (
       'Property type not implemented for %s, type: %s, namespace: %s' %
       (underlying_property_type, underlying_type.name,
       underlying_type.namespace.name))
 
-    assert (underlying_property_type != PropertyType.ARRAY or
-      underlying_type.item_type.property_type != PropertyType.ENUM), (
-      'Enum types in arrays are not currently supported. Type: %s.' %
-      underlying_type.name)
-
     property_constant = cpp_util.UnixNameToConstantName(property.unix_name)
     out_expression = '&out->%s' % property.unix_name
 
-    if underlying_property_type == PropertyType.ENUM:
+    def get_enum_params(enum_type, include_optional_param):
+      # type: (Type, bool) -> List[str]
       enum_name = cpp_util.Classname(
-        schema_util.StripNamespace(underlying_type.name))
-      cpp_type_namespace = '' if underlying_type.namespace == self._namespace \
-          else '%s::' % underlying_type.namespace.unix_name
+        schema_util.StripNamespace(enum_type.name))
+      cpp_type_namespace = (''
+        if enum_type.namespace == self._namespace
+        else '%s::' % enum_type.namespace.unix_name)
 
       params = [
         'dict',
         '%s' % property_constant,
-        '&%sParse%s' % (cpp_type_namespace, enum_name),
-        'true' if property.optional else 'false',
+        '&%sParse%s' % (cpp_type_namespace, enum_name)
+      ]
+      if include_optional_param:
+        params.append('true' if property.optional else 'false')
+      params += [
         '%s%s' % (cpp_type_namespace,
-                  self._type_helper.GetEnumNoneValue(underlying_type)),
+                  self._type_helper.GetEnumNoneValue(enum_type)),
         '%s' % out_expression,
         'error',
         'error_path_reversed'
       ]
+      return params
+
+    if underlying_property_type == PropertyType.ENUM:
+      params = get_enum_params(underlying_type, include_optional_param=True)
       func_name = 'ParseEnumFromDictionary'
+    elif underlying_item_type and \
+      underlying_item_type.property_type == PropertyType.ENUM:
+      # Array of enums.
+      params = get_enum_params(underlying_item_type,
+                               include_optional_param=False)
+      func_name = 'ParseEnumArrayFromDictionary'
     else:
       params = [
         'dict',
diff --git a/tools/json_schema_compiler/manifest_parse_util.cc b/tools/json_schema_compiler/manifest_parse_util.cc
index fbf47fad..0e9a0b37 100644
--- a/tools/json_schema_compiler/manifest_parse_util.cc
+++ b/tools/json_schema_compiler/manifest_parse_util.cc
@@ -55,6 +55,13 @@
       base::StringPrintf("Specified value '%s' is invalid.", value.c_str()));
 }
 
+std::u16string GetArrayParseError(size_t error_index,
+                                  const std::u16string& item_error) {
+  return base::ASCIIToUTF16(
+      base::StringPrintf("Parsing array failed at index %" PRIuS ": %s",
+                         error_index, base::UTF16ToASCII(item_error).c_str()));
+}
+
 void PopulateFinalError(std::u16string* error,
                         std::vector<base::StringPiece>* error_path_reversed) {
   DCHECK(error);
diff --git a/tools/json_schema_compiler/manifest_parse_util.h b/tools/json_schema_compiler/manifest_parse_util.h
index 7674e1c..427739a 100644
--- a/tools/json_schema_compiler/manifest_parse_util.h
+++ b/tools/json_schema_compiler/manifest_parse_util.h
@@ -26,6 +26,10 @@
     std::u16string* error,
     std::vector<base::StringPiece>* error_path_reversed);
 
+// Returns array parse error for `item_error` at index `error_index`
+std::u16string GetArrayParseError(size_t error_index,
+                                  const std::u16string& item_error);
+
 // Populates manifest parse |error| for the given path in |error_path_reversed|.
 void PopulateFinalError(std::u16string* error,
                         std::vector<base::StringPiece>* error_path_reversed);
@@ -174,6 +178,71 @@
   return true;
 }
 
+// Parses non-optional enum array `out` from `dict` at the given `key`. On
+// failure, returns false and populates `error` and `error_path_reversed`.
+template <typename T>
+bool ParseEnumArrayFromDictionary(
+    const base::DictionaryValue& dict,
+    base::StringPiece key,
+    StringToEnumConverter<T> converter,
+    T none_value,
+    std::vector<T>* out,
+    std::u16string* error,
+    std::vector<base::StringPiece>* error_path_reversed) {
+  DCHECK(out);
+  DCHECK(out->empty());
+
+  std::vector<std::string> str_array;
+  if (!ParseFromDictionary(dict, key, &str_array, error, error_path_reversed))
+    return false;
+
+  std::vector<T> result;
+  result.reserve(str_array.size());
+  for (size_t i = 0; i < str_array.size(); ++i) {
+    T enum_value = converter(str_array[i]);
+    if (enum_value == none_value) {
+      std::u16string item_error;
+      PopulateInvalidEnumValueError(key, str_array[i], &item_error,
+                                    error_path_reversed);
+      *error = GetArrayParseError(i, item_error);
+      return false;
+    }
+
+    result.push_back(enum_value);
+  }
+
+  *out = std::move(result);
+  return true;
+}
+
+// Overload for optional enum arrays.
+template <typename T>
+bool ParseEnumArrayFromDictionary(
+    const base::DictionaryValue& dict,
+    base::StringPiece key,
+    StringToEnumConverter<T> converter,
+    T none_value,
+    std::unique_ptr<std::vector<T>>* out,
+    std::u16string* error,
+    std::vector<base::StringPiece>* error_path_reversed) {
+  DCHECK(out);
+
+  // Ignore optional keys if they are not present without raising an error.
+  if (!dict.FindKey(key))
+    return true;
+
+  // Parse errors for optional keys which are specified should still cause a
+  // failure.
+  auto result = std::make_unique<std::vector<T>>();
+  if (!ParseEnumArrayFromDictionary(dict, key, converter, none_value,
+                                    result.get(), error, error_path_reversed)) {
+    return false;
+  }
+
+  *out = std::move(result);
+  return true;
+}
+
 }  // namespace manifest_parse_util
 }  // namespace json_schema_compiler
 
diff --git a/tools/json_schema_compiler/test/simple_api.json b/tools/json_schema_compiler/test/simple_api.json
index de2c8b3..57bea6b 100644
--- a/tools/json_schema_compiler/test/simple_api.json
+++ b/tools/json_schema_compiler/test/simple_api.json
@@ -69,11 +69,24 @@
           },
           "obj_bool": {
             "type": "boolean"
+          },
+          "obj_optional_enum_array": {
+            "optional": true,
+            "type": "array",
+            "items": {
+              "$ref": "enums.Enumeration"
+            }
           }
         }
       },
       "key_enum": {
         "$ref": "TestEnum"
+      },
+      "key_enum_array": {
+        "type": "array",
+        "items": {
+          "$ref": "TestEnum"
+        }
       }
     },
     "functions": [
diff --git a/tools/json_schema_compiler/test/simple_api_unittest.cc b/tools/json_schema_compiler/test/simple_api_unittest.cc
index 6b61030..ea68b17 100644
--- a/tools/json_schema_compiler/test/simple_api_unittest.cc
+++ b/tools/json_schema_compiler/test/simple_api_unittest.cc
@@ -32,7 +32,7 @@
 void GetManifestParseError(base::StringPiece manifest_json,
                            std::string* error) {
   base::Optional<base::Value> manifest = base::JSONReader::Read(manifest_json);
-  ASSERT_TRUE(manifest);
+  ASSERT_TRUE(manifest) << "Invalid json \n" << manifest_json;
 
   simple_api::ManifestKeys manifest_keys;
   std::u16string error_16;
@@ -248,7 +248,8 @@
       "object": {
         "foo": "bar"
       },
-      "key_enum": "one"
+      "key_enum": "one",
+      "key_enum_array": ["two"]
     }
   })";
 
@@ -270,7 +271,8 @@
       "integer": 32,
       "array": ["one", "two", 3]
     },
-    "key_enum": "one"
+    "key_enum": "one",
+    "key_enum_array": ["two"]
   })";
 
   std::string error;
@@ -281,6 +283,89 @@
       error);
 }
 
+TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_EnumArrayParseError) {
+  {
+    const char kPartialManifestJson[] = R"({
+      "key_string": "abc",
+      "key_ref": {
+        "string": "ref_string",
+        "boolean": true,
+        "number": 25.4,
+        "integer": 32,
+        "array": ["one", "two"]
+      },
+      "key_enum": "one",
+      "key_enum_array": ["two", false]
+    })";
+
+    std::string error;
+    ASSERT_NO_FATAL_FAILURE(
+        GetManifestParseError(kPartialManifestJson, &error));
+    EXPECT_EQ(
+        "Error at key 'key_enum_array'. Parsing array failed at index 1: "
+        "expected string, got boolean",
+        error);
+  }
+  {
+    const char kPartialManifestJson[] = R"({
+      "key_string": "abc",
+      "key_ref": {
+        "string": "ref_string",
+        "boolean": true,
+        "number": 25.4,
+        "integer": 32,
+        "array": ["one", "two"]
+      },
+      "key_enum": "one",
+      "key_enum_array": [],
+      "key_obj": {
+        "obj_string": "foo",
+        "obj_bool": true,
+        "obj_optional_enum_array": ["one", "invalid_value"]
+      }
+    })";
+
+    std::string error;
+    ASSERT_NO_FATAL_FAILURE(
+        GetManifestParseError(kPartialManifestJson, &error));
+    EXPECT_EQ(
+        "Error at key 'key_obj.obj_optional_enum_array'. Parsing array failed "
+        "at index 1: "
+        "Specified value 'invalid_value' is invalid.",
+        error);
+  }
+  {
+    const char kPartialManifestJson[] = R"({
+      "key_string": "abc",
+      "key_ref": {
+        "string": "ref_string",
+        "boolean": true,
+        "number": 25.4,
+        "integer": 32,
+        "array": ["one", "two"]
+      },
+      "key_enum": "one",
+      "key_enum_array": [],
+      "key_obj": {
+        "obj_string": "foo",
+        "obj_bool": true,
+        "obj_optional_enum_array": false
+      }
+    })";
+
+    std::string error;
+    ASSERT_NO_FATAL_FAILURE(
+        GetManifestParseError(kPartialManifestJson, &error));
+    EXPECT_EQ(
+        "Error at key 'key_obj.obj_optional_enum_array'. Type is invalid. "
+        "Expected list, found boolean.",
+        error);
+  }
+}
+
+TEST(JsonSchemaCompilerSimpleTest,
+     ManifestKeyParsing_OptionalEnumArrayParseError) {}
+
 TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_InvalidEnumValue) {
   const char kPartialManifestJson[] = R"({
     "key_string": "abc",
@@ -291,7 +376,8 @@
       "integer": 32,
       "opt_external_enum": "four"
     },
-    "key_enum": "one"
+    "key_enum": "one",
+    "key_enum_array": ["two"]
   })";
 
   std::string error;
@@ -318,9 +404,11 @@
     },
     "key_obj": {
       "obj_string": "foo",
-      "obj_bool": true
+      "obj_bool": true,
+      "obj_optional_enum_array": ["three"]
     },
-    "key_enum": "one"
+    "key_enum": "one",
+    "key_enum_array": ["two", "one"]
   })";
 
   simple_api::ManifestKeys manifest_keys;
@@ -332,6 +420,9 @@
   ASSERT_TRUE(manifest_keys.key_obj);
   EXPECT_EQ("foo", manifest_keys.key_obj->obj_string);
   EXPECT_TRUE(manifest_keys.key_obj->obj_bool);
+  ASSERT_TRUE(manifest_keys.key_obj->obj_optional_enum_array);
+  EXPECT_THAT(*manifest_keys.key_obj->obj_optional_enum_array,
+              ::testing::ElementsAre(enums::ENUMERATION_THREE));
 
   EXPECT_EQ(simple_api::TEST_ENUM_ONE, manifest_keys.key_enum);
 
@@ -345,6 +436,9 @@
   EXPECT_THAT(*manifest_keys.key_ref.array,
               ::testing::ElementsAre("one", "two"));
   EXPECT_EQ(enums::ENUMERATION_TWO, manifest_keys.key_ref.opt_external_enum);
+  EXPECT_THAT(manifest_keys.key_enum_array,
+              ::testing::ElementsAre(simple_api::TEST_ENUM_TWO,
+                                     simple_api::TEST_ENUM_ONE));
 }
 
 // Ensure leaving out optional keys is not a manifest parse error.
@@ -358,7 +452,8 @@
       "number": 25.4,
       "integer": 32
     },
-    "key_enum": "two"
+    "key_enum": "two",
+    "key_enum_array": ["one"]
   })";
 
   simple_api::ManifestKeys manifest_keys;
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index b653bbe..96f5fd9 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -121,12 +121,14 @@
 
       'android-marshmallow-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_resource_allowlisting_webview_google',
       'android-marshmallow-x86-rel-non-cq': 'android_release_bot_minimal_symbols_x86_fastbuild_resource_allowlisting_webview_google',
+      'android-marshmallow-x86-rel-rts': 'android_release_bot_minimal_symbols_x86_fastbuild_resource_allowlisting_webview_google',
       'android-nougat-arm64-rel': 'android_release_bot_minimal_symbols_arm64_fastbuild_webview_google',
       # TODO(crbug/1182468) Remove android coverage bots after coverage is
       # running on CQ.
       'android-pie-arm64-coverage-experimental-rel': 'android_release_bot_arm64_webview_google_expectations',
       'android-pie-arm64-rel': 'android_release_bot_minimal_symbols_arm64_webview_google',
       'android-pie-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google',
+      'android-weblayer-with-aosp-webview-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_resource_allowlisting_disable_proguard_chrome_google',
       'android-weblayer-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_disable_proguard_webview_google',
       'android-10-arm64-rel': 'android_release_bot_minimal_symbols_arm64_fastbuild_webview_google',
     },
@@ -170,6 +172,7 @@
       'chromeos-amd64-generic-dbg': 'chromeos_amd64-generic_dbg',
       'chromeos-amd64-generic-lacros-dbg': 'chromeos_amd64-generic_lacros_dbg',
       'chromeos-amd64-generic-rel': 'chromeos_amd64-generic_use_fake_dbus_clients',
+      'chromeos-amd64-generic-rel-rts': 'chromeos_amd64-generic_use_fake_dbus_clients',
       'chromeos-arm-generic-dbg': 'chromeos_arm-generic_dbg',
       'chromeos-arm-generic-rel': 'chromeos_arm-generic',
       'chromeos-kevin-rel': 'chromeos_kevin',
@@ -340,6 +343,7 @@
       'ios-simulator-cr-recipe': 'ios_simulator_debug_static_bot_xctest',
       'ios-simulator-cronet': 'ios_cronet_xctest',
       'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_xctest',
+      'ios-simulator-rts': 'ios_error',
       'ios-webkit-tot': 'ios_simulator_debug_static_bot_xctest',
       'linux-annotator-rel': 'release_bot',
       'linux-blink-animation-use-time-delta': 'debug_bot_enable_blink_animation_use_time_delta',
@@ -353,6 +357,7 @@
       'linux-example-builder': 'release_bot',
       'linux-fieldtrial-rel': 'release_bot_minimal_symbols',
       'linux-backuprefptr-x64-fyi-rel': 'release_trybot_backuprefptr_x64',
+      'linux-lacros-code-coverage': 'lacros_on_linux_clang_code_coverage',
       'linux-perfetto-rel': 'perfetto_release_bot',
       'linux-upload-perfetto': 'release_bot',
       'linux-wpt-fyi-rel': 'release_bot_minimal_symbols',
@@ -426,6 +431,9 @@
       'Chromium Win Goma RBE ToT': 'release_bot_x86_minimal_symbols',
       'Chromium Win Goma RBE Staging': 'release_bot_x86_minimal_symbols',
       'Chromium Win Goma RBE Staging (clobber)': 'release_bot_x86_minimal_symbols',
+      'Chromium Win Goma RBE ATS ToT': 'release_bot_x86_minimal_symbols',
+      'Chromium Win Goma RBE ATS Staging': 'release_bot_x86_minimal_symbols',
+      'Chromium Win Goma RBE ATS Staging (clobber)': 'release_bot_x86_minimal_symbols',
 
       'Chromium Android ARM 32-bit Goma RBE ToT': 'android_release_bot_minimal_symbols',
       # TODO(b/167942918): re-enable java goma?
@@ -980,6 +988,7 @@
       'fuchsia-fyi-x64-dbg': 'debug_bot_fuchsia',
       'fuchsia-fyi-x64-rel': 'release_trybot_fuchsia',
       'fuchsia_x64': 'release_trybot_fuchsia',
+      'fuchsia_x64_rts': 'release_trybot_fuchsia',
       'fuchsia-x64-cast': 'release_trybot_fuchsia_cast',
       'gpu-fyi-try-lacros-amd-rel': 'gpu_tests_ozone_linux_non_x11_release_trybot',
       'gpu-fyi-try-lacros-intel-rel': 'gpu_tests_ozone_linux_non_x11_release_trybot',
@@ -1116,6 +1125,7 @@
       'mac_upload_clang_arm': 'release_bot',
       'mac-inverse-fieldtrials-fyi-rel': 'gpu_tests_release_trybot_deterministic_mac_invert_fieldtrials',
       'mac-rel': 'gpu_tests_release_trybot_deterministic_mac',
+      'mac-rel-rts': 'gpu_tests_release_trybot_deterministic_mac',
       'mac-arm64-rel': 'mac_arm64_release_trybot',
     },
 
@@ -1171,6 +1181,7 @@
       'win10_chromium_x64_dbg_ng': 'gpu_tests_debug_bot',
       'win10_chromium_x64_rel_ng': 'gpu_tests_release_trybot_resource_allowlisting_code_coverage',
       'win10_chromium_x64_rel_ng_exp': 'release_trybot',
+      'win10_chromium_x64_rel_ng_rts': 'gpu_tests_release_trybot_resource_allowlisting_code_coverage',
       'win-annotator-rel': 'release_trybot',
       'win-asan': 'asan_clang_fuzzer_static_v8_heap_minimal_symbols_release',
       'win-celab-try-rel': 'release_bot_minimal_symbols',
@@ -2313,6 +2324,10 @@
         'ios', 'ios_simulator', 'ios_cpu_x64', 'release_bot', 'asan', 'xctest', 'ios_disable_xcode_project_generation',
     ],
 
+    'lacros_on_linux_clang_code_coverage': [
+      'lacros_on_linux', 'release_bot', 'also_build_ash_chrome', 'clang', 'use_clang_coverage', 'no_symbols',
+    ],
+
     'lacros_on_linux_release_bot': [
       'lacros_on_linux', 'release_bot', 'also_build_ash_chrome',
     ],
diff --git a/tools/mb/mb_config_expectations/chromium.android.json b/tools/mb/mb_config_expectations/chromium.android.json
index 3c7b3f8..38813ec8 100644
--- a/tools/mb/mb_config_expectations/chromium.android.json
+++ b/tools/mb/mb_config_expectations/chromium.android.json
@@ -471,6 +471,22 @@
       "use_goma": true
     }
   },
+  "android-marshmallow-x86-rel-rts": {
+    "gn_args": {
+      "disable_android_lint": true,
+      "enable_resource_allowlist_generation": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "system_webview_package_name": "com.google.android.webview",
+      "target_cpu": "x86",
+      "target_os": "android",
+      "use_errorprone_java_compiler": false,
+      "use_goma": true
+    }
+  },
   "android-nougat-arm64-rel": {
     "gn_args": {
       "disable_android_lint": true,
@@ -531,6 +547,23 @@
       "use_goma": true
     }
   },
+  "android-weblayer-with-aosp-webview-x86-rel": {
+    "gn_args": {
+      "chrome_public_manifest_package": "com.android.chrome",
+      "disable_android_lint": true,
+      "enable_proguard_obfuscation": false,
+      "enable_resource_allowlist_generation": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "target_os": "android",
+      "use_errorprone_java_compiler": false,
+      "use_goma": true
+    }
+  },
   "android-weblayer-x86-rel": {
     "gn_args": {
       "disable_android_lint": true,
diff --git a/tools/mb/mb_config_expectations/chromium.chromiumos.json b/tools/mb/mb_config_expectations/chromium.chromiumos.json
index 5d034864..e60340d 100644
--- a/tools/mb/mb_config_expectations/chromium.chromiumos.json
+++ b/tools/mb/mb_config_expectations/chromium.chromiumos.json
@@ -76,6 +76,15 @@
       "use_real_dbus_clients": false
     }
   },
+  "chromeos-amd64-generic-rel-rts": {
+    "args_file": "//build/args/chromeos/amd64-generic.gni",
+    "gn_args": {
+      "is_chromeos_device": true,
+      "ozone_platform_headless": true,
+      "use_goma": true,
+      "use_real_dbus_clients": false
+    }
+  },
   "chromeos-arm-generic-dbg": {
     "args_file": "//build/args/chromeos/arm-generic.gni",
     "gn_args": {
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index 4442eb0c..6961c2f4 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -776,6 +776,23 @@
       "use_ozone": true
     }
   },
+  "linux-lacros-code-coverage": {
+    "gn_args": {
+      "also_build_ash_chrome": true,
+      "chromeos_is_browser_only": true,
+      "is_clang": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "ozone_platform": "wayland",
+      "ozone_platform_wayland": true,
+      "symbol_level": 0,
+      "target_os": "chromeos",
+      "use_clang_coverage": true,
+      "use_goma": true,
+      "use_gtk": false,
+      "use_ozone": true
+    }
+  },
   "linux-lacros-tester-fyi-rel": {
     "gn_args": {
       "also_build_ash_chrome": true,
diff --git a/tools/mb/mb_config_expectations/chromium.goma.json b/tools/mb/mb_config_expectations/chromium.goma.json
index e469b258..8b18d0ef 100644
--- a/tools/mb/mb_config_expectations/chromium.goma.json
+++ b/tools/mb/mb_config_expectations/chromium.goma.json
@@ -108,6 +108,33 @@
       "use_goma": true
     }
   },
+  "Chromium Win Goma RBE ATS Staging": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "use_goma": true
+    }
+  },
+  "Chromium Win Goma RBE ATS Staging (clobber)": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "use_goma": true
+    }
+  },
+  "Chromium Win Goma RBE ATS ToT": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_cpu": "x86",
+      "use_goma": true
+    }
+  },
   "Chromium Win Goma RBE Staging": {
     "gn_args": {
       "is_component_build": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
index 89dd51b..40190dbf 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -140,6 +140,16 @@
       "use_goma": true
     }
   },
+  "fuchsia_x64_rts": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "symbol_level": 1,
+      "target_os": "fuchsia",
+      "use_goma": true
+    }
+  },
   "gpu-fyi-try-lacros-amd-rel": {
     "gn_args": {
       "dcheck_always_on": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
index 3cd2b0fd..f2d4df6 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -436,6 +436,18 @@
       "use_goma": true
     }
   },
+  "mac-rel-rts": {
+    "gn_args": {
+      "dcheck_always_on": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "mac_deterministic_build": true,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "use_goma": true
+    }
+  },
   "mac_chromium_10.11_rel_ng": {
     "gn_args": {
       "dcheck_always_on": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.win.json b/tools/mb/mb_config_expectations/tryserver.chromium.win.json
index 2388382..81f204e 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.win.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.win.json
@@ -286,6 +286,20 @@
       "use_goma": true
     }
   },
+  "win10_chromium_x64_rel_ng_rts": {
+    "gn_args": {
+      "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
+      "dcheck_always_on": true,
+      "enable_resource_allowlist_generation": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "use_clang_coverage": true,
+      "use_goma": true
+    }
+  },
   "win7-rel": {
     "gn_args": {
       "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ed95d010..1782dfc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3483,7 +3483,7 @@
   <int value="2" label="No hash code for multiple accounts"/>
   <int value="3" label="Hash code set but no account"/>
   <int value="4" label="Hash code set but does not match single account"/>
-  <int value="5" label="Hash code set but does not any account"/>
+  <int value="5" label="Hash code set but does not match any account"/>
   <int value="6" label="Hash code set and matches single account"/>
   <int value="7" label="Hash code set and matches one of multiple accounts"/>
   <int value="8" label="Hash code collides with multiple accounts"/>
@@ -13397,6 +13397,9 @@
   <int value="71" label="Font Access"/>
   <int value="74" label="Display Capture"/>
   <int value="75" label="File Handling"/>
+  <int value="76" label="File system access chooser data"/>
+  <int value="77" label="Federated identity sharing"/>
+  <int value="78" label="Federated identity request"/>
 </enum>
 
 <enum name="ContentTypeParseableResult">
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml
index b00e10c56..e6e9838 100644
--- a/tools/metrics/histograms/histograms_xml/media/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -407,6 +407,50 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.Capture.Win.VolumeRangeAvailable"
+    enum="BooleanAvailable" expires_after="2021-09-30">
+  <owner>alessiob@chromium.org</owner>
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    Availability of volume range information on the audio capture stream on
+    Windows. Only uploaded when analog AGC is enabled - i.e., for WebRTC-based
+    audio input streams.
+  </summary>
+</histogram>
+
+<histogram name="Media.Audio.Capture.Win.VolumeRangeMax" units="dB"
+    expires_after="2021-09-30">
+  <owner>alessiob@chromium.org</owner>
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    Volume range maximum for the audio capture stream on Windows. Only uploaded
+    when volume range information is available and when analog AGC is enabled -
+    i.e., for WebRTC-based audio input streams.
+  </summary>
+</histogram>
+
+<histogram name="Media.Audio.Capture.Win.VolumeRangeMin" units="dB"
+    expires_after="2021-09-30">
+  <owner>alessiob@chromium.org</owner>
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    Volume range minimum for the audio capture stream on Windows. Only uploaded
+    when volume range information is available and when analog AGC is enabled -
+    i.e., for WebRTC-based audio input streams.
+  </summary>
+</histogram>
+
+<histogram name="Media.Audio.Capture.Win.VolumeRangeNumSteps" units="units"
+    expires_after="2021-09-30">
+  <owner>alessiob@chromium.org</owner>
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    Number of volume range steps for the audio capture stream on Windows. Only
+    uploaded when volume range information is available and when analog AGC is
+    enabled - i.e., for WebRTC-based audio input streams.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.Capture.Win.{AudioProcessingMode}EffectType"
     enum="AudioEffectType" expires_after="2021-10-22">
   <owner>henrika@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index e97f3b4..9e78092 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": "01c343f9df8a5ef5ec58b96c1793a9301b83f55d",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/a6c4cea7f7ff399ed4f69ec8ca30153ff60264fa/trace_processor_shell.exe"
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/395145ab5dbd4c4c1f6ae01c8a63bde2a5612db6/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "fd71c24d8e85705c4a5abf1ac3c6e6405e9874c8",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/a6c4cea7f7ff399ed4f69ec8ca30153ff60264fa/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c9641c91104af34e2f562fdce1514b4912ae1c10/trace_processor_shell"
         },
         "linux": {
             "hash": "69e538301b42ba89cbe14e061ce227422140a206",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/a6c4cea7f7ff399ed4f69ec8ca30153ff60264fa/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/52fefceb29bb88140996879a9a8970d7ea6dce83/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/core/results_processor/processor.py b/tools/perf/core/results_processor/processor.py
index 4a26edd..4db8f43 100644
--- a/tools/perf/core/results_processor/processor.py
+++ b/tools/perf/core/results_processor/processor.py
@@ -99,7 +99,6 @@
   if should_compute_metrics:
     histogram_dicts = ExtractHistograms(test_results)
 
-  util.TryUploadingResultToResultSink(test_results)
   for output_format in options.output_formats:
     logging.info('Processing format: %s', output_format)
     formatter = formatters.FORMATTERS[output_format]
@@ -107,7 +106,6 @@
       output_file = formatter.ProcessHistogramDicts(histogram_dicts, options)
     else:
       output_file = formatter.ProcessIntermediateResults(test_results, options)
-
     print('View results at file://', output_file, sep='')
 
   return GenerateExitCode(test_results)
diff --git a/tools/perf/core/results_processor/util.py b/tools/perf/core/results_processor/util.py
index 13c2c29e..f670e5f 100644
--- a/tools/perf/core/results_processor/util.py
+++ b/tools/perf/core/results_processor/util.py
@@ -4,11 +4,7 @@
 
 import calendar
 import datetime
-import json
 import logging
-import os
-
-import requests  # pylint: disable=import-error
 
 import multiprocessing
 from multiprocessing.dummy import Pool as ThreadPool
@@ -101,58 +97,3 @@
   test_result['status'] = 'FAIL'
   test_result['expected'] = False
   logging.error('Processing failed for test %s', test_result['testPath'])
-
-
-def TryUploadingResultToResultSink(results):
-  def buildSummaryHtml(artifacts):
-    summaryHtml = ''
-    for artifact_id, _ in artifacts.items():
-      summaryHtml += '<p><text-artifact artifact-id=' + artifact_id + '></p>'
-    return summaryHtml
-
-  def buildArtifacts(artifacts):
-    artifacts_result = {}
-    for artifact_id, artifact in artifacts.items():
-      artifacts_result[artifact_id] = {'filePath': artifact['filePath']}
-    return artifacts_result
-
-  def parse(results):
-    test_results = []
-    for test_case in results:
-      test_result = {
-          'testId': test_case['testPath'],
-          'expected': test_case['expected'],
-          'status': test_case['status']
-      }
-      # TODO: go/result-sink#test-result-json-object listed that specifying
-      # testMetadata with location info can helped with breaking down flaky
-      # tests. We don't have the file location currently in test results.
-      if 'runDuration' in test_case:
-        test_result['duration'] = '%.9fs' % float(
-            test_case['runDuration'].rstrip('s'))
-      if 'tags' in test_case:
-        test_result['tags'] = test_case['tags']
-      if 'outputArtifacts' in test_case:
-        test_result['summaryHtml'] = buildSummaryHtml(
-            test_case['outputArtifacts'])
-        test_result['artifacts'] = buildArtifacts(test_case['outputArtifacts'])
-      test_results.append(test_result)
-    return test_results
-
-  try:
-    with open(os.environ['LUCI_CONTEXT']) as f:
-      sink = json.load(f)['result_sink']
-  except KeyError:
-    return
-
-  test_results = parse(results)
-  res = requests.post(
-      url='http://%s/prpc/luci.resultsink.v1.Sink/ReportTestResults' %
-      sink['address'],
-      headers={
-          'Content-Type': 'application/json',
-          'Accept': 'application/json',
-          'Authorization': 'ResultSink %s' % sink['auth_token'],
-      },
-      data=json.dumps({'testResults': test_results}))
-  res.raise_for_status()
diff --git a/tools/resultdb/DIR_METADATA b/tools/resultdb/DIR_METADATA
index cbad6f6..0172575 100644
--- a/tools/resultdb/DIR_METADATA
+++ b/tools/resultdb/DIR_METADATA
@@ -1,10 +1,10 @@
 # Metadata information for this directory.
 #
 # For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
 #
 # For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
 
 monorail {
   component: "Infra>Test>Results"
diff --git a/ui/accelerated_widget_mac/accelerated_widget_mac.h b/ui/accelerated_widget_mac/accelerated_widget_mac.h
index 44b1dfc..317173d 100644
--- a/ui/accelerated_widget_mac/accelerated_widget_mac.h
+++ b/ui/accelerated_widget_mac/accelerated_widget_mac.h
@@ -5,7 +5,6 @@
 #ifndef UI_ACCELERATED_WIDGET_MAC_ACCELERATED_WIDGET_MAC_H_
 #define UI_ACCELERATED_WIDGET_MAC_ACCELERATED_WIDGET_MAC_H_
 
-#include <vector>
 
 #include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
 #include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
diff --git a/ui/accelerated_widget_mac/io_surface_context.h b/ui/accelerated_widget_mac/io_surface_context.h
index 504a52b..a468782 100644
--- a/ui/accelerated_widget_mac/io_surface_context.h
+++ b/ui/accelerated_widget_mac/io_surface_context.h
@@ -7,8 +7,6 @@
 
 #include <OpenGL/OpenGL.h>
 
-#include <map>
-#include <memory>
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
diff --git a/ui/accessibility/platform/ax_android_constants.h b/ui/accessibility/platform/ax_android_constants.h
index fe83123..837aab8 100644
--- a/ui/accessibility/platform/ax_android_constants.h
+++ b/ui/accessibility/platform/ax_android_constants.h
@@ -5,7 +5,6 @@
 #ifndef UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_
 #define UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_
 
-#include <string>
 
 #include "ui/accessibility/ax_export.h"
 
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.h b/ui/accessibility/platform/ax_platform_node_textprovider_win.h
index 74984eb..b8c2c61 100644
--- a/ui/accessibility/platform/ax_platform_node_textprovider_win.h
+++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.h
@@ -7,7 +7,6 @@
 
 #include <wrl/client.h>
 
-#include <string>
 
 #include "ui/accessibility/platform/ax_platform_node_win.h"
 
diff --git a/ui/android/edge_effect.h b/ui/android/edge_effect.h
index 2e0039e..21fa3291 100644
--- a/ui/android/edge_effect.h
+++ b/ui/android/edge_effect.h
@@ -5,7 +5,6 @@
 #ifndef UI_ANDROID_EDGE_EFFECT_H_
 #define UI_ANDROID_EDGE_EFFECT_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/ui/android/resources/resource_manager.h b/ui/android/resources/resource_manager.h
index 27b2e28..0506161 100644
--- a/ui/android/resources/resource_manager.h
+++ b/ui/android/resources/resource_manager.h
@@ -5,10 +5,6 @@
 #ifndef UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
 #define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
 
-#include <memory>
-#include <unordered_map>
-#include <unordered_set>
-
 #include "base/android/jni_android.h"
 #include "cc/resources/scoped_ui_resource.h"
 #include "third_party/skia/include/core/SkColor.h"
diff --git a/ui/android/resources/resource_manager_impl.h b/ui/android/resources/resource_manager_impl.h
index a737d56..c0d266f 100644
--- a/ui/android/resources/resource_manager_impl.h
+++ b/ui/android/resources/resource_manager_impl.h
@@ -6,6 +6,8 @@
 #define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_IMPL_H_
 
 #include <memory>
+#include <unordered_map>
+#include <unordered_set>
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
diff --git a/ui/aura/client/cursor_client.h b/ui/aura/client/cursor_client.h
index a39aeff..4d7c636 100644
--- a/ui/aura/client/cursor_client.h
+++ b/ui/aura/client/cursor_client.h
@@ -5,7 +5,6 @@
 #ifndef UI_AURA_CLIENT_CURSOR_CLIENT_H_
 #define UI_AURA_CLIENT_CURSOR_CLIENT_H_
 
-#include <string>
 
 #include "ui/aura/aura_export.h"
 #include "ui/base/cursor/cursor.h"
diff --git a/ui/aura/client/window_stacking_client.h b/ui/aura/client/window_stacking_client.h
index 657e599..151efdd9 100644
--- a/ui/aura/client/window_stacking_client.h
+++ b/ui/aura/client/window_stacking_client.h
@@ -5,7 +5,6 @@
 #ifndef UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
 #define UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_
 
-#include <memory>
 
 #include "ui/aura/aura_export.h"
 #include "ui/aura/window.h"
diff --git a/ui/aura/window_observer.h b/ui/aura/window_observer.h
index c2ce7a6d..d893c934 100644
--- a/ui/aura/window_observer.h
+++ b/ui/aura/window_observer.h
@@ -5,7 +5,6 @@
 #ifndef UI_AURA_WINDOW_OBSERVER_H_
 #define UI_AURA_WINDOW_OBSERVER_H_
 
-#include <string>
 
 #include "base/observer_list_types.h"
 #include "ui/aura/aura_export.h"
diff --git a/ui/base/clipboard/clipboard_constants.h b/ui/base/clipboard/clipboard_constants.h
index d0eea22..fe9e5fe 100644
--- a/ui/base/clipboard/clipboard_constants.h
+++ b/ui/base/clipboard/clipboard_constants.h
@@ -5,7 +5,6 @@
 #ifndef UI_BASE_CLIPBOARD_CLIPBOARD_CONSTANTS_H_
 #define UI_BASE_CLIPBOARD_CLIPBOARD_CONSTANTS_H_
 
-#include <string>
 
 #include "base/component_export.h"
 #include "build/build_config.h"
diff --git a/ui/base/cocoa/menu_controller.h b/ui/base/cocoa/menu_controller.h
index ace28e03..5a42c79c 100644
--- a/ui/base/cocoa/menu_controller.h
+++ b/ui/base/cocoa/menu_controller.h
@@ -7,7 +7,6 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include <string>
 
 #include "base/component_export.h"
 #include "base/mac/scoped_nsobject.h"
diff --git a/ui/base/ime/fuchsia/input_method_fuchsia.cc b/ui/base/ime/fuchsia/input_method_fuchsia.cc
index aaa5a1e..4d88241 100644
--- a/ui/base/ime/fuchsia/input_method_fuchsia.cc
+++ b/ui/base/ime/fuchsia/input_method_fuchsia.cc
@@ -49,9 +49,19 @@
   return dispatch_details;
 }
 
-void InputMethodFuchsia::OnCaretBoundsChanged(const TextInputClient* client) {}
+void InputMethodFuchsia::CancelComposition(const TextInputClient* client) {
+  // FIDL asynchronicity makes it impossible to know whether a recent
+  // visibility update might be in flight, so always call Dismiss.
+  virtual_keyboard_controller_.DismissVirtualKeyboard();
+}
 
-void InputMethodFuchsia::CancelComposition(const TextInputClient* client) {}
+void InputMethodFuchsia::OnTextInputTypeChanged(const TextInputClient* client) {
+  InputMethodBase::OnTextInputTypeChanged(client);
+
+  virtual_keyboard_controller_.UpdateTextType();
+}
+
+void InputMethodFuchsia::OnCaretBoundsChanged(const TextInputClient* client) {}
 
 bool InputMethodFuchsia::IsCandidatePopupOpen() const {
   return false;
diff --git a/ui/base/ime/fuchsia/input_method_fuchsia.h b/ui/base/ime/fuchsia/input_method_fuchsia.h
index 511f2c9..52b2b6b 100644
--- a/ui/base/ime/fuchsia/input_method_fuchsia.h
+++ b/ui/base/ime/fuchsia/input_method_fuchsia.h
@@ -8,7 +8,6 @@
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/ui/scenic/cpp/view_ref_pair.h>
-#include <memory>
 
 #include "base/component_export.h"
 #include "base/macros.h"
@@ -35,8 +34,9 @@
   // InputMethodBase interface implementation.
   VirtualKeyboardController* GetVirtualKeyboardController() final;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) final;
-  void OnCaretBoundsChanged(const TextInputClient* client) final;
   void CancelComposition(const TextInputClient* client) final;
+  void OnTextInputTypeChanged(const TextInputClient* client) final;
+  void OnCaretBoundsChanged(const TextInputClient* client) final;
   bool IsCandidatePopupOpen() const final;
 
  private:
diff --git a/ui/base/ime/fuchsia/keyboard_client.h b/ui/base/ime/fuchsia/keyboard_client.h
index d74aeb0..3c213077 100644
--- a/ui/base/ime/fuchsia/keyboard_client.h
+++ b/ui/base/ime/fuchsia/keyboard_client.h
@@ -7,7 +7,6 @@
 
 #include <fuchsia/ui/input3/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
-#include <memory>
 
 #include "base/component_export.h"
 #include "ui/events/event.h"
diff --git a/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc b/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
index 7003199..ccf0f9f 100644
--- a/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
+++ b/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc
@@ -15,27 +15,6 @@
 namespace ui {
 namespace {
 
-// Returns the FIDL enum representation of the current InputMode.
-fuchsia::input::virtualkeyboard::TextType ConvertTextInputMode(
-    ui::TextInputMode mode) {
-  switch (mode) {
-    case TEXT_INPUT_MODE_NUMERIC:
-    case TEXT_INPUT_MODE_DECIMAL:
-      return fuchsia::input::virtualkeyboard::TextType::NUMERIC;
-
-    case TEXT_INPUT_MODE_TEL:
-      return fuchsia::input::virtualkeyboard::TextType::PHONE;
-
-    case TEXT_INPUT_MODE_DEFAULT:
-    case TEXT_INPUT_MODE_NONE:
-    case TEXT_INPUT_MODE_TEXT:
-    case TEXT_INPUT_MODE_URL:
-    case TEXT_INPUT_MODE_EMAIL:
-    case TEXT_INPUT_MODE_SEARCH:
-      return fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
-  }
-}
-
 }  // namespace
 
 VirtualKeyboardControllerFuchsia::VirtualKeyboardControllerFuchsia(
@@ -47,13 +26,11 @@
   base::ComponentContextForProcess()
       ->svc()
       ->Connect<fuchsia::input::virtualkeyboard::ControllerCreator>()
-      ->Create(std::move(view_ref),
-               ConvertTextInputMode(input_method_->GetTextInputMode()),
+      ->Create(std::move(view_ref), requested_type_,
                controller_service_.NewRequest());
 
-  controller_service_.set_error_handler([this](zx_status_t status) {
+  controller_service_.set_error_handler([](zx_status_t status) {
     ZX_LOG(ERROR, status) << "virtualkeyboard::Controller disconnected";
-    keyboard_visible_ = false;
   });
 
   WatchVisibility();
@@ -62,22 +39,29 @@
 VirtualKeyboardControllerFuchsia::~VirtualKeyboardControllerFuchsia() = default;
 
 bool VirtualKeyboardControllerFuchsia::DisplayVirtualKeyboard() {
+  DVLOG(1) << "DisplayVirtualKeyboard (visible= " << keyboard_visible_ << ")";
+
   if (!controller_service_)
     return false;
 
-  controller_service_->SetTextType(
-      ConvertTextInputMode(input_method_->GetTextInputMode()));
+  UpdateTextType();
 
-  if (!keyboard_visible_)
-    controller_service_->RequestShow();
+  requested_visible_ = true;
+  controller_service_->RequestShow();
 
   return true;
 }
 
 void VirtualKeyboardControllerFuchsia::DismissVirtualKeyboard() {
+  DVLOG(1) << "DismissVirtualKeyboard (visible= " << keyboard_visible_ << ")";
+
   if (!controller_service_)
     return;
 
+  if (!requested_visible_ && !keyboard_visible_)
+    return;
+
+  requested_visible_ = false;
   controller_service_->RequestHide();
 }
 
@@ -104,4 +88,34 @@
   WatchVisibility();
 }
 
+// Returns the FIDL enum representation of the current InputMode.
+fuchsia::input::virtualkeyboard::TextType
+VirtualKeyboardControllerFuchsia::GetFocusedTextType() const {
+  switch (input_method_->GetTextInputMode()) {
+    case TEXT_INPUT_MODE_NUMERIC:
+    case TEXT_INPUT_MODE_DECIMAL:
+      return fuchsia::input::virtualkeyboard::TextType::NUMERIC;
+
+    case TEXT_INPUT_MODE_TEL:
+      return fuchsia::input::virtualkeyboard::TextType::PHONE;
+
+    case TEXT_INPUT_MODE_DEFAULT:
+    case TEXT_INPUT_MODE_NONE:
+    case TEXT_INPUT_MODE_TEXT:
+    case TEXT_INPUT_MODE_URL:
+    case TEXT_INPUT_MODE_EMAIL:
+    case TEXT_INPUT_MODE_SEARCH:
+      return fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
+  }
+}
+
+void VirtualKeyboardControllerFuchsia::UpdateTextType() {
+  // Only send updates if the type has changed.
+  auto new_type = GetFocusedTextType();
+  if (new_type != requested_type_) {
+    controller_service_->SetTextType(new_type);
+    requested_type_ = new_type;
+  }
+}
+
 }  // namespace ui
diff --git a/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h b/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
index 1adc5692..4f96003 100644
--- a/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
+++ b/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h
@@ -29,6 +29,8 @@
   VirtualKeyboardControllerFuchsia operator=(
       VirtualKeyboardControllerFuchsia&) = delete;
 
+  void UpdateTextType();
+
   // VirtualKeyboardController implementation.
   bool DisplayVirtualKeyboard() override;
   void DismissVirtualKeyboard() override;
@@ -43,9 +45,15 @@
   // Handles the visibility change response from the service.
   void OnVisibilityChange(bool is_visible);
 
+  // Gets the Fuchsia TextType corresponding to the currently focused field.
+  fuchsia::input::virtualkeyboard::TextType GetFocusedTextType() const;
+
   ui::InputMethodBase* const input_method_;
+  fuchsia::input::virtualkeyboard::TextType requested_type_ =
+      fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC;
   fuchsia::input::virtualkeyboard::ControllerPtr controller_service_;
   bool keyboard_visible_ = false;
+  bool requested_visible_ = false;
 };
 
 }  // namespace ui
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h
index a93dc25..6e411aa 100644
--- a/ui/base/ime/input_method.h
+++ b/ui/base/ime/input_method.h
@@ -7,9 +7,6 @@
 
 #include <stdint.h>
 
-#include <memory>
-#include <string>
-#include <vector>
 
 #include "build/build_config.h"
 #include "ui/base/ime/text_input_mode.h"
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h
index 6fdd630..0ed0143 100644
--- a/ui/base/ime/mock_input_method.h
+++ b/ui/base/ime/mock_input_method.h
@@ -5,7 +5,6 @@
 #ifndef UI_BASE_IME_MOCK_INPUT_METHOD_H_
 #define UI_BASE_IME_MOCK_INPUT_METHOD_H_
 
-#include <string>
 
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
diff --git a/ui/base/ime/win/input_method_win_imm32.h b/ui/base/ime/win/input_method_win_imm32.h
index b9ec2f5..cd233475 100644
--- a/ui/base/ime/win/input_method_win_imm32.h
+++ b/ui/base/ime/win/input_method_win_imm32.h
@@ -7,7 +7,6 @@
 
 #include <windows.h>
 
-#include <string>
 
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
diff --git a/ui/base/ime/win/tsf_event_router.h b/ui/base/ime/win/tsf_event_router.h
index 6107c599..7b82289 100644
--- a/ui/base/ime/win/tsf_event_router.h
+++ b/ui/base/ime/win/tsf_event_router.h
@@ -8,7 +8,6 @@
 #include <msctf.h>
 #include <wrl/client.h>
 
-#include <set>
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
diff --git a/ui/base/scoped_visibility_tracker.h b/ui/base/scoped_visibility_tracker.h
index 2f53bc55..7082ee3 100644
--- a/ui/base/scoped_visibility_tracker.h
+++ b/ui/base/scoped_visibility_tracker.h
@@ -5,7 +5,6 @@
 #ifndef UI_BASE_SCOPED_VISIBILITY_TRACKER_H_
 #define UI_BASE_SCOPED_VISIBILITY_TRACKER_H_
 
-#include <memory>
 
 #include "base/component_export.h"
 #include "base/time/time.h"
diff --git a/ui/compositor/paint_context.h b/ui/compositor/paint_context.h
index c2d3dca..f8b4565 100644
--- a/ui/compositor/paint_context.h
+++ b/ui/compositor/paint_context.h
@@ -5,7 +5,6 @@
 #ifndef UI_COMPOSITOR_PAINT_CONTEXT_H_
 #define UI_COMPOSITOR_PAINT_CONTEXT_H_
 
-#include <memory>
 
 #include "base/check.h"
 #include "base/macros.h"
diff --git a/ui/compositor/paint_recorder.h b/ui/compositor/paint_recorder.h
index 609d6f0..5aebaa5 100644
--- a/ui/compositor/paint_recorder.h
+++ b/ui/compositor/paint_recorder.h
@@ -5,7 +5,6 @@
 #ifndef UI_COMPOSITOR_PAINT_RECORDER_H_
 #define UI_COMPOSITOR_PAINT_RECORDER_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "cc/paint/display_item_list.h"
diff --git a/ui/compositor/test/throughput_report_checker.h b/ui/compositor/test/throughput_report_checker.h
index c7837a7..71b5954 100644
--- a/ui/compositor/test/throughput_report_checker.h
+++ b/ui/compositor/test/throughput_report_checker.h
@@ -5,7 +5,6 @@
 #ifndef UI_COMPOSITOR_TEST_THROUGHPUT_REPORT_CHECKER_H_
 #define UI_COMPOSITOR_TEST_THROUGHPUT_REPORT_CHECKER_H_
 
-#include <memory>
 
 #include "base/bind.h"
 #include "cc/metrics/frame_sequence_metrics.h"
diff --git a/ui/compositor/total_animation_throughput_reporter.h b/ui/compositor/total_animation_throughput_reporter.h
index 6edc347..a87e6a9 100644
--- a/ui/compositor/total_animation_throughput_reporter.h
+++ b/ui/compositor/total_animation_throughput_reporter.h
@@ -5,7 +5,6 @@
 #ifndef UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
 #define UI_COMPOSITOR_TOTAL_ANIMATION_THROUGHPUT_REPORTER_H_
 
-#include <memory>
 
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
diff --git a/ui/display/mac/display_link_mac.h b/ui/display/mac/display_link_mac.h
index 3db8d3cb..42a601dde 100644
--- a/ui/display/mac/display_link_mac.h
+++ b/ui/display/mac/display_link_mac.h
@@ -7,7 +7,6 @@
 
 #include <QuartzCore/CVDisplayLink.h>
 
-#include <map>
 
 #include "base/mac/scoped_typeref.h"
 #include "base/memory/ref_counted.h"
diff --git a/ui/display/manager/display_change_observer.h b/ui/display/manager/display_change_observer.h
index 33909247..7d5795c 100644
--- a/ui/display/manager/display_change_observer.h
+++ b/ui/display/manager/display_change_observer.h
@@ -7,8 +7,6 @@
 
 #include <stdint.h>
 
-#include <memory>
-#include <vector>
 
 #include "base/macros.h"
 #include "ui/display/manager/display_configurator.h"
diff --git a/ui/display/manager/test/touch_transform_controller_test_api.h b/ui/display/manager/test/touch_transform_controller_test_api.h
index 7e49aa2f..fed93c3 100644
--- a/ui/display/manager/test/touch_transform_controller_test_api.h
+++ b/ui/display/manager/test/touch_transform_controller_test_api.h
@@ -5,7 +5,6 @@
 #ifndef UI_DISPLAY_MANAGER_TEST_TOUCH_TRANSFORM_CONTROLLER_TEST_API_H_
 #define UI_DISPLAY_MANAGER_TEST_TOUCH_TRANSFORM_CONTROLLER_TEST_API_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "ui/display/manager/touch_transform_controller.h"
diff --git a/ui/display/test/test_screen.h b/ui/display/test/test_screen.h
index 37b618b..cab20404 100644
--- a/ui/display/test/test_screen.h
+++ b/ui/display/test/test_screen.h
@@ -5,7 +5,6 @@
 #ifndef UI_DISPLAY_TEST_TEST_SCREEN_H_
 #define UI_DISPLAY_TEST_TEST_SCREEN_H_
 
-#include <vector>
 
 #include "base/macros.h"
 #include "ui/display/display.h"
diff --git a/ui/events/base_event_utils.h b/ui/events/base_event_utils.h
index 2c5743c1..401ae76 100644
--- a/ui/events/base_event_utils.h
+++ b/ui/events/base_event_utils.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_BASE_EVENT_UTILS_H_
 #define UI_EVENTS_BASE_EVENT_UTILS_H_
 
-#include <memory>
 #include <stdint.h>
 
 #include "base/time/tick_clock.h"
diff --git a/ui/events/gestures/motion_event_aura.h b/ui/events/gestures/motion_event_aura.h
index cccab0b..1c7ad51 100644
--- a/ui/events/gestures/motion_event_aura.h
+++ b/ui/events/gestures/motion_event_aura.h
@@ -7,8 +7,6 @@
 
 #include <stddef.h>
 
-#include <map>
-#include <memory>
 
 #include "base/macros.h"
 #include "base/time/time.h"
diff --git a/ui/events/keyboard_hook_base.h b/ui/events/keyboard_hook_base.h
index c5a7f2d..4626d19 100644
--- a/ui/events/keyboard_hook_base.h
+++ b/ui/events/keyboard_hook_base.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_KEYBOARD_HOOK_BASE_H_
 #define UI_EVENTS_KEYBOARD_HOOK_BASE_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "ui/events/keyboard_hook.h"
diff --git a/ui/events/keycodes/keyboard_code_conversion.h b/ui/events/keycodes/keyboard_code_conversion.h
index 2341a64..7efa5bfe 100644
--- a/ui/events/keycodes/keyboard_code_conversion.h
+++ b/ui/events/keycodes/keyboard_code_conversion.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_
 #define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_
 
-#include <string>
 
 #include "base/compiler_specific.h"
 #include "ui/events/events_base_export.h"
diff --git a/ui/events/keycodes/keyboard_code_conversion_x.h b/ui/events/keycodes/keyboard_code_conversion_x.h
index ae3742c..118895c 100644
--- a/ui/events/keycodes/keyboard_code_conversion_x.h
+++ b/ui/events/keycodes/keyboard_code_conversion_x.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <string>
 
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
diff --git a/ui/events/keycodes/keyboard_code_conversion_xkb.h b/ui/events/keycodes/keyboard_code_conversion_xkb.h
index 8f56878..e1fefa4c 100644
--- a/ui/events/keycodes/keyboard_code_conversion_xkb.h
+++ b/ui/events/keycodes/keyboard_code_conversion_xkb.h
@@ -7,7 +7,6 @@
 
 // These functions are used by X11 targets and by Ozone/XKBcommon targets.
 
-#include <string>
 
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/xkb_keysym.h"
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
index 94dc5cb9..1e35ff9 100644
--- a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
+++ b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
@@ -5,9 +5,6 @@
 #ifndef UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_EVDEV_PROXY_H_
 #define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_FACTORY_EVDEV_PROXY_H_
 
-#include <memory>
-#include <set>
-#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
diff --git a/ui/events/ozone/layout/keyboard_layout_engine_manager.h b/ui/events/ozone/layout/keyboard_layout_engine_manager.h
index 96459d8b..f60864a 100644
--- a/ui/events/ozone/layout/keyboard_layout_engine_manager.h
+++ b/ui/events/ozone/layout/keyboard_layout_engine_manager.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
 #define UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_MANAGER_H_
 
-#include <memory>
 
 #include "base/check.h"
 #include "base/component_export.h"
diff --git a/ui/events/test/x11_event_waiter.h b/ui/events/test/x11_event_waiter.h
index b50d5fa..e323028 100644
--- a/ui/events/test/x11_event_waiter.h
+++ b/ui/events/test/x11_event_waiter.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_TEST_X11_EVENT_WAITER_H_
 #define UI_EVENTS_TEST_X11_EVENT_WAITER_H_
 
-#include <memory>
 
 #include "base/callback.h"
 #include "ui/gfx/x/connection.h"
diff --git a/ui/events/win/events_win_utils.h b/ui/events/win/events_win_utils.h
index a1dfada5..8aaa07f 100644
--- a/ui/events/win/events_win_utils.h
+++ b/ui/events/win/events_win_utils.h
@@ -8,8 +8,6 @@
 #include <stdint.h>
 #include <windows.h>
 
-#include <memory>
-#include <string>
 
 #include "build/build_config.h"
 #include "ui/display/display.h"
diff --git a/ui/events/x/events_x_utils.h b/ui/events/x/events_x_utils.h
index 2a6e48d..9888a89 100644
--- a/ui/events/x/events_x_utils.h
+++ b/ui/events/x/events_x_utils.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <memory>
 
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
diff --git a/ui/events/x/keyboard_hook_x11.h b/ui/events/x/keyboard_hook_x11.h
index 74cb13a..c19774d 100644
--- a/ui/events/x/keyboard_hook_x11.h
+++ b/ui/events/x/keyboard_hook_x11.h
@@ -5,7 +5,6 @@
 #ifndef UI_EVENTS_X_KEYBOARD_HOOK_X11_H_
 #define UI_EVENTS_X_KEYBOARD_HOOK_X11_H_
 
-#include <vector>
 
 #include "base/optional.h"
 #include "base/threading/thread_checker.h"
diff --git a/ui/gfx/gdi_util.h b/ui/gfx/gdi_util.h
index e8e8f0e..5b9af51b 100644
--- a/ui/gfx/gdi_util.h
+++ b/ui/gfx/gdi_util.h
@@ -6,7 +6,6 @@
 #define UI_GFX_GDI_UTIL_H_
 
 #include <windows.h>
-#include <vector>
 
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/gfx_export.h"
diff --git a/ui/gfx/image/image_skia_source.h b/ui/gfx/image/image_skia_source.h
index 9c50760e..9ffc135 100644
--- a/ui/gfx/image/image_skia_source.h
+++ b/ui/gfx/image/image_skia_source.h
@@ -5,7 +5,6 @@
 #ifndef UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
 #define UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
 
-#include <vector>
 
 #include "ui/gfx/gfx_export.h"
 
diff --git a/ui/gfx/mojom/buffer_types_mojom_traits.h b/ui/gfx/mojom/buffer_types_mojom_traits.h
index 8f068d8c..5ed27e0 100644
--- a/ui/gfx/mojom/buffer_types_mojom_traits.h
+++ b/ui/gfx/mojom/buffer_types_mojom_traits.h
@@ -5,7 +5,6 @@
 #ifndef UI_GFX_MOJOM_BUFFER_TYPES_MOJOM_TRAITS_H_
 #define UI_GFX_MOJOM_BUFFER_TYPES_MOJOM_TRAITS_H_
 
-#include <vector>
 
 #include "base/component_export.h"
 #include "build/build_config.h"
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h
index b73ff46..33bab22d 100644
--- a/ui/gfx/skia_util.h
+++ b/ui/gfx/skia_util.h
@@ -5,8 +5,6 @@
 #ifndef UI_GFX_SKIA_UTIL_H_
 #define UI_GFX_SKIA_UTIL_H_
 
-#include <string>
-#include <vector>
 
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkRect.h"
diff --git a/ui/gfx/test/gfx_util.h b/ui/gfx/test/gfx_util.h
index 3b01c73..1c9015d 100644
--- a/ui/gfx/test/gfx_util.h
+++ b/ui/gfx/test/gfx_util.h
@@ -5,9 +5,6 @@
 #ifndef UI_GFX_TEST_GFX_UTIL_H_
 #define UI_GFX_TEST_GFX_UTIL_H_
 
-#include <iosfwd>
-#include <string>
-
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColor.h"
 
diff --git a/ui/gfx/win/singleton_hwnd.h b/ui/gfx/win/singleton_hwnd.h
index 11ac73c..d987f31 100644
--- a/ui/gfx/win/singleton_hwnd.h
+++ b/ui/gfx/win/singleton_hwnd.h
@@ -6,7 +6,6 @@
 #define UI_GFX_WIN_SINGLETON_HWND_H_
 
 #include <windows.h>
-#include <vector>
 
 #include "base/macros.h"
 #include "base/observer_list.h"
diff --git a/ui/gfx/x/generated_protos/bigreq.h b/ui/gfx/x/generated_protos/bigreq.h
index 4f32d9d..19f4323 100644
--- a/ui/gfx/x/generated_protos/bigreq.h
+++ b/ui/gfx/x/generated_protos/bigreq.h
@@ -41,11 +41,9 @@
 #ifndef UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_
 #define UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_
 
-#include <array>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
-#include <vector>
 
 #include "base/component_export.h"
 #include "base/files/scoped_file.h"
diff --git a/ui/gfx/x/generated_protos/ge.h b/ui/gfx/x/generated_protos/ge.h
index 1a690c9..4aa3e10 100644
--- a/ui/gfx/x/generated_protos/ge.h
+++ b/ui/gfx/x/generated_protos/ge.h
@@ -41,11 +41,9 @@
 #ifndef UI_GFX_X_GENERATED_PROTOS_GE_H_
 #define UI_GFX_X_GENERATED_PROTOS_GE_H_
 
-#include <array>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
-#include <vector>
 
 #include "base/component_export.h"
 #include "base/files/scoped_file.h"
diff --git a/ui/gl/gl_context_glx.h b/ui/gl/gl_context_glx.h
index b8925ae..cad557a 100644
--- a/ui/gl/gl_context_glx.h
+++ b/ui/gl/gl_context_glx.h
@@ -5,7 +5,6 @@
 #ifndef UI_GL_GL_CONTEXT_GLX_H_
 #define UI_GL_GL_CONTEXT_GLX_H_
 
-#include <string>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
diff --git a/ui/gl/gl_surface_egl_x11_gles2.h b/ui/gl/gl_surface_egl_x11_gles2.h
index 55ff91f6..17c4d07 100644
--- a/ui/gl/gl_surface_egl_x11_gles2.h
+++ b/ui/gl/gl_surface_egl_x11_gles2.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/gfx/x/event.h"
diff --git a/ui/gl/gl_visual_picker_glx.h b/ui/gl/gl_visual_picker_glx.h
index d780aa2..5a48f9b 100644
--- a/ui/gl/gl_visual_picker_glx.h
+++ b/ui/gl/gl_visual_picker_glx.h
@@ -5,7 +5,6 @@
 #ifndef UI_GL_GL_VISUAL_PICKER_GLX_H_
 #define UI_GL_GL_VISUAL_PICKER_GLX_H_
 
-#include <vector>
 
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
diff --git a/ui/gl/hdr_metadata_helper_win.h b/ui/gl/hdr_metadata_helper_win.h
index d276f05..a7ab4df 100644
--- a/ui/gl/hdr_metadata_helper_win.h
+++ b/ui/gl/hdr_metadata_helper_win.h
@@ -9,9 +9,6 @@
 #include <dxgi1_6.h>
 #include <wrl/client.h>
 
-#include <memory>
-#include <utility>
-#include <vector>
 
 #include "base/macros.h"
 #include "base/optional.h"
diff --git a/ui/gtk/gtk_util.cc b/ui/gtk/gtk_util.cc
index bcc947fc..4deeabf 100644
--- a/ui/gtk/gtk_util.cc
+++ b/ui/gtk/gtk_util.cc
@@ -747,6 +747,9 @@
     case ui::kColorAvatarIconIncognito:
       return GetFgColor("GtkLabel#label");
     case ui::kColorBubbleFooterBackground:
+    case ui::kColorNotificationActionsBackground:
+    case ui::kColorNotificationBackgroundActive:
+    case ui::kColorNotificationImageBackground:
       return GetBgColor("#statusbar");
 
     // FocusableBorder
@@ -916,6 +919,7 @@
     case ui::kColorButtonForegroundChecked:
     case ui::kColorButtonBackgroundProminent:
     case ui::kColorButtonBackgroundProminentFocused:
+    case ui::kColorNotificationInputBackground:
       return GetBgColor(
           "GtkTreeView#treeview.view "
           "GtkTreeView#treeview.view.cell:selected:focus");
diff --git a/ui/native_theme/common_theme.h b/ui/native_theme/common_theme.h
index 73a84cf1..3d035852 100644
--- a/ui/native_theme/common_theme.h
+++ b/ui/native_theme/common_theme.h
@@ -5,7 +5,6 @@
 #ifndef UI_NATIVE_THEME_COMMON_THEME_H_
 #define UI_NATIVE_THEME_COMMON_THEME_H_
 
-#include <memory>
 
 #include "ui/color/color_id.h"
 #include "ui/native_theme/native_theme.h"
diff --git a/ui/native_theme/native_theme_base.h b/ui/native_theme/native_theme_base.h
index a29df63..90ab8021 100644
--- a/ui/native_theme/native_theme_base.h
+++ b/ui/native_theme/native_theme_base.h
@@ -5,7 +5,6 @@
 #ifndef UI_NATIVE_THEME_NATIVE_THEME_BASE_H_
 #define UI_NATIVE_THEME_NATIVE_THEME_BASE_H_
 
-#include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
index 34df247..9576c5dd 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
@@ -6,7 +6,6 @@
 #define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_MANAGER_LEGACY_H_
 
 #include <stdint.h>
-#include <memory>
 
 #include "base/macros.h"
 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
diff --git a/ui/ozone/platform/drm/gpu/page_flip_request.h b/ui/ozone/platform/drm/gpu/page_flip_request.h
index d24d6bbc..c7fb160 100644
--- a/ui/ozone/platform/drm/gpu/page_flip_request.h
+++ b/ui/ozone/platform/drm/gpu/page_flip_request.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
 #define UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
 
-#include <memory>
 
 #include "base/atomic_ref_count.h"
 #include "base/callback.h"
diff --git a/ui/ozone/platform/drm/host/drm_device_connector.h b/ui/ozone/platform/drm/host/drm_device_connector.h
index 0944085..e358162 100644
--- a/ui/ozone/platform/drm/host/drm_device_connector.h
+++ b/ui/ozone/platform/drm/host/drm_device_connector.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
 #define UI_OZONE_PLATFORM_DRM_HOST_DRM_DEVICE_CONNECTOR_H_
 
-#include <string>
 
 #include "base/single_thread_task_runner.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/ui/ozone/platform/headless/headless_window_manager.h b/ui/ozone/platform/headless/headless_window_manager.h
index 8768c9c..2364f021 100644
--- a/ui/ozone/platform/headless/headless_window_manager.h
+++ b/ui/ozone/platform/headless/headless_window_manager.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <memory>
 
 #include "base/containers/id_map.h"
 #include "base/files/file_path.h"
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
index a33e0e1..e7b5ceb 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_SURFACE_GPU_H_
 #define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_SURFACE_GPU_H_
 
-#include <memory>
 
 namespace gfx {
 enum class SwapResult;
diff --git a/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h b/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
index 4bb586b..c6afbcd 100644
--- a/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
+++ b/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
@@ -5,9 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
 
-#include <memory>
-#include <string>
-#include <vector>
 
 #include "base/callback.h"
 #include "base/macros.h"
diff --git a/ui/ozone/platform/wayland/host/gtk_surface1.h b/ui/ozone/platform/wayland/host/gtk_surface1.h
index 764b609..73c2329 100644
--- a/ui/ozone/platform/wayland/host/gtk_surface1.h
+++ b/ui/ozone/platform/wayland/host/gtk_surface1.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SURFACE1_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_SURFACE1_H_
 
-#include <memory>
 
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index 4b17d8d..9f98934 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -118,6 +118,11 @@
   uint32_t serial() const { return serial_.serial; }
   EventSerial event_serial() const { return serial_; }
 
+  void set_pointer_enter_serial(uint32_t serial) {
+    pointer_enter_serial_ = serial;
+  }
+  uint32_t pointer_enter_serial() const { return pointer_enter_serial_; }
+
   void SetPlatformCursor(wl_cursor* cursor_data, int buffer_scale);
 
   void SetCursorBufferListener(WaylandCursorBufferListener* listener);
@@ -298,6 +303,8 @@
   bool scheduled_flush_ = false;
 
   EventSerial serial_;
+
+  uint32_t pointer_enter_serial_ = 0;
 };
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_cursor.cc b/ui/ozone/platform/wayland/host/wayland_cursor.cc
index 981ade1..575fe2c 100644
--- a/ui/ozone/platform/wayland/host/wayland_cursor.cc
+++ b/ui/ozone/platform/wayland/host/wayland_cursor.cc
@@ -97,8 +97,8 @@
 
 void WaylandCursor::HideCursor() {
   DCHECK(pointer_);
-  wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(), nullptr,
-                        0, 0);
+  wl_pointer_set_cursor(pointer_->wl_object(),
+                        connection_->pointer_enter_serial(), nullptr, 0, 0);
 
   wl_surface_attach(pointer_surface_.get(), nullptr, 0, 0);
   wl_surface_commit(pointer_surface_.get());
@@ -142,7 +142,8 @@
                                     uint32_t hotspot_y_dip) {
   DCHECK(pointer_);
 
-  wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(),
+  wl_pointer_set_cursor(pointer_->wl_object(),
+                        connection_->pointer_enter_serial(),
                         pointer_surface_.get(), hotspot_x_dip, hotspot_y_dip);
 
   wl_surface_damage(pointer_surface_.get(), 0, 0, buffer_width, buffer_height);
diff --git a/ui/ozone/platform/wayland/host/wayland_pointer.cc b/ui/ozone/platform/wayland/host/wayland_pointer.cc
index db6bcb97..d1d8bb9 100644
--- a/ui/ozone/platform/wayland/host/wayland_pointer.cc
+++ b/ui/ozone/platform/wayland/host/wayland_pointer.cc
@@ -47,6 +47,8 @@
                            wl_fixed_t surface_y) {
   DCHECK(data);
   WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+  pointer->connection_->set_pointer_enter_serial(serial);
+
   WaylandWindow* window = wl::RootWindowFromWlSurface(surface);
   gfx::PointF location{wl_fixed_to_double(surface_x),
                        wl_fixed_to_double(surface_y)};
diff --git a/ui/ozone/platform/wayland/host/wayland_shm.h b/ui/ozone/platform/wayland/host/wayland_shm.h
index 0b484ed6..1eafd53f 100644
--- a/ui/ozone/platform/wayland/host/wayland_shm.h
+++ b/ui/ozone/platform/wayland/host/wayland_shm.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_H_
 
-#include <memory>
 
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
diff --git a/ui/ozone/platform/wayland/host/wayland_shm_buffer.h b/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
index 5dc4600..465183b1 100644
--- a/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
+++ b/ui/ozone/platform/wayland/host/wayland_shm_buffer.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_BUFFER_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SHM_BUFFER_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "base/memory/shared_memory_mapping.h"
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell.h b/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
index 9c0e8251..82a35ba 100644
--- a/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
+++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_SHELL_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_ZAURA_SHELL_H_
 
-#include <string>
 
 #include "base/containers/flat_set.h"
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
diff --git a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
index b29e63c..00990cf 100644
--- a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
+++ b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
@@ -8,7 +8,6 @@
 #include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
 
 #include <cstdint>
-#include <string>
 
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
diff --git a/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
index 4a366339..b36842d 100644
--- a/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
+++ b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
@@ -8,7 +8,6 @@
 #include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
 
 #include <cstdint>
-#include <string>
 
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
diff --git a/ui/ozone/platform/wayland/test/mock_surface.h b/ui/ozone/platform/wayland/test/mock_surface.h
index fd682b8..7246a7d 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.h
+++ b/ui/ozone/platform/wayland/test/mock_surface.h
@@ -5,8 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_SURFACE_H_
 #define UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_SURFACE_H_
 
-#include <memory>
-#include <utility>
 
 #include <wayland-server-protocol.h>
 
diff --git a/ui/ozone/platform/wayland/test/test_subcompositor.h b/ui/ozone/platform/wayland/test/test_subcompositor.h
index 45be83b9..cc8943bf 100644
--- a/ui/ozone/platform/wayland/test/test_subcompositor.h
+++ b/ui/ozone/platform/wayland/test/test_subcompositor.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SUBCOMPOSITOR_H_
 #define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SUBCOMPOSITOR_H_
 
-#include <vector>
 
 #include "base/macros.h"
 #include "ui/ozone/platform/wayland/test/global_object.h"
diff --git a/ui/ozone/platform/wayland/test/test_subsurface.h b/ui/ozone/platform/wayland/test/test_subsurface.h
index d21f398..959276ef 100644
--- a/ui/ozone/platform/wayland/test/test_subsurface.h
+++ b/ui/ozone/platform/wayland/test/test_subsurface.h
@@ -7,8 +7,6 @@
 
 #include <wayland-server-protocol.h>
 
-#include <memory>
-#include <utility>
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/ui/ozone/platform/windows/windows_window_manager.h b/ui/ozone/platform/windows/windows_window_manager.h
index a11546c8..30d9b81 100644
--- a/ui/ozone/platform/windows/windows_window_manager.h
+++ b/ui/ozone/platform/windows/windows_window_manager.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <memory>
 
 #include "base/containers/id_map.h"
 #include "base/files/file_path.h"
diff --git a/ui/ozone/platform_constructor_list.h b/ui/ozone/platform_constructor_list.h
index e103ab6..5600af0 100644
--- a/ui/ozone/platform_constructor_list.h
+++ b/ui/ozone/platform_constructor_list.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_CONSTRUCTOR_LIST_H_
 #define UI_OZONE_PLATFORM_CONSTRUCTOR_LIST_H_
 
-#include <memory>
 
 #include "ui/ozone/platform_list.h"
 
diff --git a/ui/ozone/public/platform_user_input_monitor.h b/ui/ozone/public/platform_user_input_monitor.h
index ce768411..7d71724 100644
--- a/ui/ozone/public/platform_user_input_monitor.h
+++ b/ui/ozone/public/platform_user_input_monitor.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
 #define UI_OZONE_PUBLIC_PLATFORM_USER_INPUT_MONITOR_H_
 
-#include <memory>
 
 #include "base/component_export.h"
 #include "base/memory/shared_memory_mapping.h"
diff --git a/ui/ozone/public/swap_completion_callback.h b/ui/ozone/public/swap_completion_callback.h
index 7334b1e..185bef07 100644
--- a/ui/ozone/public/swap_completion_callback.h
+++ b/ui/ozone/public/swap_completion_callback.h
@@ -5,7 +5,6 @@
 #ifndef UI_OZONE_PUBLIC_SWAP_COMPLETION_CALLBACK_H_
 #define UI_OZONE_PUBLIC_SWAP_COMPLETION_CALLBACK_H_
 
-#include <memory>
 
 #include "base/callback.h"
 #include "ui/gfx/gpu_fence_handle.h"
diff --git a/ui/snapshot/snapshot.h b/ui/snapshot/snapshot.h
index 9fbb3b6..ca6c1e6d 100644
--- a/ui/snapshot/snapshot.h
+++ b/ui/snapshot/snapshot.h
@@ -5,7 +5,6 @@
 #ifndef UI_SNAPSHOT_SNAPSHOT_H_
 #define UI_SNAPSHOT_SNAPSHOT_H_
 
-#include <vector>
 
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
diff --git a/ui/views/animation/animation_delegate_views.h b/ui/views/animation/animation_delegate_views.h
index 7edc84d..afe6a72 100644
--- a/ui/views/animation/animation_delegate_views.h
+++ b/ui/views/animation/animation_delegate_views.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_ANIMATION_DELEGATE_VIEWS_H_
 #define UI_VIEWS_ANIMATION_ANIMATION_DELEGATE_VIEWS_H_
 
-#include <memory>
 
 #include "base/scoped_observation.h"
 #include "ui/gfx/animation/animation_container_observer.h"
diff --git a/ui/views/animation/compositor_animation_runner.h b/ui/views/animation/compositor_animation_runner.h
index b2e543e..4aaec55 100644
--- a/ui/views/animation/compositor_animation_runner.h
+++ b/ui/views/animation/compositor_animation_runner.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_COMPOSITOR_ANIMATION_RUNNER_H_
 #define UI_VIEWS_ANIMATION_COMPOSITOR_ANIMATION_RUNNER_H_
 
-#include <memory>
 
 #include "base/time/time.h"
 #include "ui/compositor/compositor.h"
diff --git a/ui/views/animation/flood_fill_ink_drop_ripple.h b/ui/views/animation/flood_fill_ink_drop_ripple.h
index 3a63a8a..2343a3fb 100644
--- a/ui/views/animation/flood_fill_ink_drop_ripple.h
+++ b/ui/views/animation/flood_fill_ink_drop_ripple.h
@@ -5,8 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_RIPPLE_H_
 #define UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_RIPPLE_H_
 
-#include <memory>
-#include <string>
 
 #include "base/macros.h"
 #include "base/time/time.h"
diff --git a/ui/views/animation/ink_drop.h b/ui/views/animation/ink_drop.h
index 5260dab..3eb91c9 100644
--- a/ui/views/animation/ink_drop.h
+++ b/ui/views/animation/ink_drop.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_INK_DROP_H_
 #define UI_VIEWS_ANIMATION_INK_DROP_H_
 
-#include <memory>
 
 #include "base/time/time.h"
 #include "ui/compositor/layer_tree_owner.h"
diff --git a/ui/views/animation/ink_drop_highlight_observer.h b/ui/views/animation/ink_drop_highlight_observer.h
index eb98bd7..c463f50 100644
--- a/ui/views/animation/ink_drop_highlight_observer.h
+++ b/ui/views/animation/ink_drop_highlight_observer.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_INK_DROP_HIGHLIGHT_OBSERVER_H_
 #define UI_VIEWS_ANIMATION_INK_DROP_HIGHLIGHT_OBSERVER_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/animation/ink_drop_animation_ended_reason.h"
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 0451b76..4b0a9426d 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -79,17 +79,44 @@
 }
 
 std::unique_ptr<InkDrop> InkDropHostView::CreateInkDrop() {
+  if (create_ink_drop_callback_)
+    return create_ink_drop_callback_.Run();
   return CreateDefaultFloodFillInkDropImpl();
 }
 
+void InkDropHostView::SetCreateInkDropCallback(
+    base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback) {
+  create_ink_drop_callback_ = std::move(callback);
+}
+
+const base::RepeatingCallback<std::unique_ptr<InkDrop>()>&
+InkDropHostView::GetCreateInkDropCallback() const {
+  return create_ink_drop_callback_;
+}
+
 std::unique_ptr<InkDropRipple> InkDropHostView::CreateInkDropRipple() const {
+  if (create_ink_drop_ripple_callback_)
+    return create_ink_drop_ripple_callback_.Run();
   return std::make_unique<views::FloodFillInkDropRipple>(
       size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(),
       GetInkDropBaseColor(), GetInkDropVisibleOpacity());
 }
 
+void InkDropHostView::SetCreateInkDropRippleCallback(
+    base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback) {
+  create_ink_drop_ripple_callback_ = std::move(callback);
+}
+
+const base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>&
+InkDropHostView::GetCreateInkDropRippleCallback() const {
+  return create_ink_drop_ripple_callback_;
+}
+
 std::unique_ptr<InkDropHighlight> InkDropHostView::CreateInkDropHighlight()
     const {
+  if (create_ink_drop_highlight_callback_)
+    return create_ink_drop_highlight_callback_.Run();
+
   auto highlight = std::make_unique<views::InkDropHighlight>(
       size(), 0, gfx::RectF(GetMirroredRect(GetLocalBounds())).CenterPoint(),
       GetInkDropBaseColor());
@@ -102,16 +129,50 @@
   return highlight;
 }
 
+void InkDropHostView::SetCreateInkDropHighlightCallback(
+    base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback) {
+  create_ink_drop_highlight_callback_ = std::move(callback);
+}
+
+const base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>&
+InkDropHostView::GetCreateInkDropHighlightCallback() const {
+  return create_ink_drop_highlight_callback_;
+}
+
 std::unique_ptr<views::InkDropMask> InkDropHostView::CreateInkDropMask() const {
+  if (create_ink_drop_mask_callback_)
+    return create_ink_drop_mask_callback_.Run();
   return std::make_unique<views::PathInkDropMask>(size(),
                                                   GetHighlightPath(this));
 }
 
+void InkDropHostView::SetCreateInkDropMaskCallback(
+    base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback) {
+  create_ink_drop_mask_callback_ = std::move(callback);
+}
+
+const base::RepeatingCallback<std::unique_ptr<InkDropMask>()>&
+InkDropHostView::GetCreateInkDropMaskCallback() const {
+  return create_ink_drop_mask_callback_;
+}
+
 SkColor InkDropHostView::GetInkDropBaseColor() const {
+  if (ink_drop_base_color_callback_)
+    return ink_drop_base_color_callback_.Run();
   NOTREACHED();
   return gfx::kPlaceholderColor;
 }
 
+void InkDropHostView::SetInkDropBaseColorCallback(
+    base::RepeatingCallback<SkColor()> callback) {
+  ink_drop_base_color_callback_ = std::move(callback);
+}
+
+const base::RepeatingCallback<SkColor()>&
+InkDropHostView::GetInkDropBaseColorCallback() const {
+  return ink_drop_base_color_callback_;
+}
+
 void InkDropHostView::SetInkDropMode(InkDropMode ink_drop_mode) {
   ink_drop_mode_ = ink_drop_mode;
   ink_drop_ = nullptr;
@@ -301,6 +362,17 @@
 }
 
 BEGIN_METADATA(InkDropHostView, View)
+ADD_PROPERTY_METADATA(base::RepeatingCallback<std::unique_ptr<InkDrop>()>,
+                      CreateInkDropCallback)
+ADD_PROPERTY_METADATA(base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>,
+                      CreateInkDropRippleCallback)
+ADD_PROPERTY_METADATA(
+    base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>,
+    CreateInkDropHighlightCallback)
+ADD_PROPERTY_METADATA(base::RepeatingCallback<std::unique_ptr<InkDropMask>()>,
+                      CreateInkDropMaskCallback)
+ADD_PROPERTY_METADATA(base::RepeatingCallback<SkColor()>,
+                      InkDropBaseColorCallback)
 ADD_READONLY_PROPERTY_METADATA(bool, Highlighted)
 ADD_PROPERTY_METADATA(float, InkDropVisibleOpacity)
 ADD_PROPERTY_METADATA(base::Optional<float>, InkDropHighlightOpacity)
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h
index 71a049f..4a6664c 100644
--- a/ui/views/animation/ink_drop_host_view.h
+++ b/ui/views/animation/ink_drop_host_view.h
@@ -48,6 +48,8 @@
   };
 
   InkDropHostView();
+  InkDropHostView(const InkDropHostView&) = delete;
+  InkDropHostView& operator=(const InkDropHostView&) = delete;
   ~InkDropHostView() override;
 
   // Adds the |ink_drop_layer| in to a visible layer tree.
@@ -65,23 +67,71 @@
   // InkDropImpl instance.
   virtual std::unique_ptr<InkDrop> CreateInkDrop();
 
+  // Callback version of CreateInkDrop(). Note that this is called in the base
+  // implementation of CreateInkDrop(), so if "it's not working", check the
+  // class hierarchy for overrides.
+  void SetCreateInkDropCallback(
+      base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback);
+
+  // Only here to support metadata.
+  const base::RepeatingCallback<std::unique_ptr<InkDrop>()>&
+  GetCreateInkDropCallback() const;
+
   // Creates and returns the visual effect used for press. Used by InkDropImpl
   // instances.
   virtual std::unique_ptr<InkDropRipple> CreateInkDropRipple() const;
 
+  // Callback version of CreateInkDropRipple(). Note that this is called in the
+  // base implementation of CreateInkDropRipple(), so if "it's not working",
+  // check the class hierarchy for overrides.
+  void SetCreateInkDropRippleCallback(
+      base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback);
+
+  // Only here to support metadata.
+  const base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>&
+  GetCreateInkDropRippleCallback() const;
+
   // Creates and returns the visual effect used for hover and focus. Used by
   // InkDropImpl instances.
   virtual std::unique_ptr<InkDropHighlight> CreateInkDropHighlight() const;
 
+  // Callback version of CreateInkDropHighlight(). Note that this is called in
+  // the base implementation of CreateInkDropHighlight(), so if "it's not
+  // working", check the class hierarchy for overrides.
+  void SetCreateInkDropHighlightCallback(
+      base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback);
+
+  // Only here to support metadata.
+  const base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>&
+  GetCreateInkDropHighlightCallback() const;
+
   // Subclasses can override to return a mask for the ink drop. By default,
   // this generates a mask based on HighlightPathGenerator.
   // TODO(pbos): Replace overrides with HighlightPathGenerator usage and remove
   // this function.
   virtual std::unique_ptr<views::InkDropMask> CreateInkDropMask() const;
 
+  // Callback version of CreateInkDropMask(). Note that this is called in the
+  // base implementation of CreateInkDropMask(), so if "it's not working", check
+  // the class hierarchy for overrides.
+  void SetCreateInkDropMaskCallback(
+      base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback);
+
+  // Only here to support metadata.
+  const base::RepeatingCallback<std::unique_ptr<InkDropMask>()>&
+  GetCreateInkDropMaskCallback() const;
+
   // Returns the base color for the ink drop.
   virtual SkColor GetInkDropBaseColor() const;
 
+  // Callback version of GetInkDropBaseColor(). Note that this is called in the
+  // base implementation of GetInkDropBaseColor(), so if "it's not working",
+  // check the class hierarchy for overrides.
+  void SetInkDropBaseColorCallback(base::RepeatingCallback<SkColor()> callback);
+
+  // Only here to support metadata.
+  const base::RepeatingCallback<SkColor()>& GetInkDropBaseColorCallback() const;
+
   // Toggle to enable/disable an InkDrop on this View.  Descendants can override
   // CreateInkDropHighlight() and CreateInkDropRipple() to change the look/feel
   // of the InkDrop.
@@ -241,7 +291,15 @@
 
   std::unique_ptr<views::InkDropMask> ink_drop_mask_;
 
-  DISALLOW_COPY_AND_ASSIGN(InkDropHostView);
+  base::RepeatingCallback<std::unique_ptr<InkDrop>()> create_ink_drop_callback_;
+  base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>
+      create_ink_drop_ripple_callback_;
+  base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>
+      create_ink_drop_highlight_callback_;
+
+  base::RepeatingCallback<std::unique_ptr<InkDropMask>()>
+      create_ink_drop_mask_callback_;
+  base::RepeatingCallback<SkColor()> ink_drop_base_color_callback_;
 };
 
 BEGIN_VIEW_BUILDER(VIEWS_EXPORT, InkDropHostView, View)
diff --git a/ui/views/animation/ink_drop_impl.cc b/ui/views/animation/ink_drop_impl.cc
index 635e1dd..c665d06 100644
--- a/ui/views/animation/ink_drop_impl.cc
+++ b/ui/views/animation/ink_drop_impl.cc
@@ -565,14 +565,7 @@
 InkDropImpl::InkDropImpl(InkDropHostView* ink_drop_host,
                          const gfx::Size& host_size)
     : ink_drop_host_(ink_drop_host),
-      root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
-      root_layer_added_to_host_(false),
-      show_highlight_on_hover_(true),
-      show_highlight_on_focus_(false),
-      is_hovered_(false),
-      is_focused_(false),
-      exiting_highlight_state_(false),
-      destroying_(false) {
+      root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)) {
   root_layer_->SetBounds(gfx::Rect(host_size));
   SetAutoHighlightMode(AutoHighlightMode::NONE);
   root_layer_->SetName("InkDropImpl:RootLayer");
diff --git a/ui/views/animation/ink_drop_impl.h b/ui/views/animation/ink_drop_impl.h
index 971f354..7bc842d 100644
--- a/ui/views/animation/ink_drop_impl.h
+++ b/ui/views/animation/ink_drop_impl.h
@@ -267,7 +267,7 @@
 
   // The host of the ink drop. Used to create the ripples and highlights, and to
   // add/remove the root layer to/from it.
-  InkDropHostView* ink_drop_host_;
+  InkDropHostView* const ink_drop_host_;
 
   // The root Layer that parents the InkDropRipple layers and the
   // InkDropHighlight layers. The |root_layer_| is the one that is added and
@@ -275,25 +275,25 @@
   std::unique_ptr<ui::Layer> root_layer_;
 
   // True when the |root_layer_| has been added to the |ink_drop_host_|.
-  bool root_layer_added_to_host_;
+  bool root_layer_added_to_host_ = false;
 
   // The current InkDropHighlight. Lazily created using
   // CreateInkDropHighlight();
   std::unique_ptr<InkDropHighlight> highlight_;
 
   // True denotes the highlight should be shown when |this| is hovered.
-  bool show_highlight_on_hover_;
+  bool show_highlight_on_hover_ = true;
 
   // True denotes the highlight should be shown when |this| is focused.
-  bool show_highlight_on_focus_;
+  bool show_highlight_on_focus_ = false;
 
   // Tracks the logical hovered state of |this| as manipulated by the public
   // SetHovered() function.
-  bool is_hovered_;
+  bool is_hovered_ = false;
 
   // Tracks the logical focused state of |this| as manipulated by the public
   // SetFocused() function.
-  bool is_focused_;
+  bool is_focused_ = false;
 
   // The current InkDropRipple. Created on demand using CreateInkDropRipple().
   std::unique_ptr<InkDropRipple> ink_drop_ripple_;
@@ -311,10 +311,10 @@
 
   // Used to ensure highlight state transitions are not triggered when exiting
   // the current state.
-  bool exiting_highlight_state_;
+  bool exiting_highlight_state_ = false;
 
   // Used to fail DCHECKS to catch unexpected behavior during tear down.
-  bool destroying_;
+  bool destroying_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(InkDropImpl);
 };
diff --git a/ui/views/animation/ink_drop_observer.h b/ui/views/animation/ink_drop_observer.h
index 5eb51cf..b91833d 100644
--- a/ui/views/animation/ink_drop_observer.h
+++ b/ui/views/animation/ink_drop_observer.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_INK_DROP_OBSERVER_H_
 #define UI_VIEWS_ANIMATION_INK_DROP_OBSERVER_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/animation/ink_drop_state.h"
diff --git a/ui/views/animation/ink_drop_ripple_observer.h b/ui/views/animation/ink_drop_ripple_observer.h
index b294b3a..fc534e5 100644
--- a/ui/views/animation/ink_drop_ripple_observer.h
+++ b/ui/views/animation/ink_drop_ripple_observer.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_ANIMATION_INK_DROP_RIPPLE_OBSERVER_H_
 #define UI_VIEWS_ANIMATION_INK_DROP_RIPPLE_OBSERVER_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/animation/ink_drop_animation_ended_reason.h"
diff --git a/ui/views/bubble/bubble_border.h b/ui/views/bubble/bubble_border.h
index f521961..3f4f818 100644
--- a/ui/views/bubble/bubble_border.h
+++ b/ui/views/bubble/bubble_border.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
 #define UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
 
-#include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index 67ce94c..44973b5d 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -874,14 +874,22 @@
 void NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged(
     bool is_first_responder) {
   accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
+
+  FocusManager* focus_manager = root_view_->GetWidget()->GetFocusManager();
+  if (focus_manager->IsSettingFocusedView()) {
+    // This first responder change is not initiated by the os,
+    // but by the focus change within the browser (e.g. tab switch),
+    // so skip setting the focus.
+    return;
+  }
+
   if (is_first_responder) {
-    root_view_->GetWidget()->GetFocusManager()->RestoreFocusedView();
+    focus_manager->RestoreFocusedView();
   } else {
     // Do not call ClearNativeFocus because that will re-make the
     // BridgedNativeWidget first responder (and this is called to indicate that
     // it is no longer first responder).
-    root_view_->GetWidget()->GetFocusManager()->StoreFocusedView(
-        false /* clear_native_focus */);
+    focus_manager->StoreFocusedView(false /* clear_native_focus */);
   }
 }
 
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index 77e53ac..7e1a339 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -573,14 +573,8 @@
     SchedulePaint();
 }
 
-std::unique_ptr<InkDrop> Button::CreateInkDrop() {
-  std::unique_ptr<InkDrop> ink_drop = InkDropHostView::CreateInkDrop();
-  ink_drop->SetShowHighlightOnFocus(!focus_ring_);
-  return ink_drop;
-}
-
 SkColor Button::GetInkDropBaseColor() const {
-  return ink_drop_base_color_;
+  return InkDropHostView::GetInkDropBaseColor();
 }
 
 void Button::AnimationProgressed(const gfx::Animation* animation) {
@@ -597,6 +591,16 @@
   SetInstallFocusRingOnFocus(true);
   button_controller_ = std::make_unique<ButtonController>(
       this, std::make_unique<DefaultButtonControllerDelegate>(this));
+  SetCreateInkDropCallback(base::BindRepeating(
+      [](Button* button) {
+        std::unique_ptr<InkDrop> ink_drop =
+            button->CreateDefaultFloodFillInkDropImpl();
+        ink_drop->SetShowHighlightOnFocus(!button->focus_ring());
+        return ink_drop;
+      },
+      base::Unretained(this)));
+  SetInkDropBaseColorCallback(base::BindRepeating(
+      [](Button* button) { return button->ink_drop_base_color_; }, this));
 }
 
 void Button::RequestFocusFromEvent() {
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h
index 1ca1a75..96df742 100644
--- a/ui/views/controls/button/button.h
+++ b/ui/views/controls/button/button.h
@@ -213,7 +213,8 @@
   void OnBlur() override;
 
   // Overridden from InkDropHostView:
-  std::unique_ptr<InkDrop> CreateInkDrop() override;
+  // This just returns InkDropHostView::GetInkDropBaseColor(). It's overridden
+  // so that ADD_PROPERTY_METADATA can retrieve the InkDropBaseColor property.
   SkColor GetInkDropBaseColor() const override;
 
   // Overridden from views::AnimationDelegateViews:
diff --git a/ui/views/controls/resize_area.h b/ui/views/controls/resize_area.h
index 77567910..fd95151 100644
--- a/ui/views/controls/resize_area.h
+++ b/ui/views/controls/resize_area.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_CONTROLS_RESIZE_AREA_H_
 #define UI_VIEWS_CONTROLS_RESIZE_AREA_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/view.h"
diff --git a/ui/views/controls/separator.h b/ui/views/controls/separator.h
index 6e1a20c..2e62bc8 100644
--- a/ui/views/controls/separator.h
+++ b/ui/views/controls/separator.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_CONTROLS_SEPARATOR_H_
 #define UI_VIEWS_CONTROLS_SEPARATOR_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "base/optional.h"
diff --git a/ui/views/controls/views_text_services_context_menu_base.cc b/ui/views/controls/views_text_services_context_menu_base.cc
index ba7f725a..62fac34 100644
--- a/ui/views/controls/views_text_services_context_menu_base.cc
+++ b/ui/views/controls/views_text_services_context_menu_base.cc
@@ -54,8 +54,11 @@
     *accelerator = ui::Accelerator(ui::VKEY_SPACE,
                                    ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
     return true;
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
+    *accelerator = ui::Accelerator(ui::VKEY_SPACE,
+                                   ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN);
+    return true;
 #else
-    // TODO(crbug.com/887660): Add accelerator key for Chrome OS.
     return false;
 #endif
   }
diff --git a/ui/views/examples/create_examples.h b/ui/views/examples/create_examples.h
index 39f1d02..1c035bec 100644
--- a/ui/views/examples/create_examples.h
+++ b/ui/views/examples/create_examples.h
@@ -5,8 +5,6 @@
 #ifndef UI_VIEWS_EXAMPLES_CREATE_EXAMPLES_H_
 #define UI_VIEWS_EXAMPLES_CREATE_EXAMPLES_H_
 
-#include <memory>
-#include <vector>
 
 #include "ui/views/examples/example_base.h"
 #include "ui/views/examples/views_examples_export.h"
diff --git a/ui/views/examples/message_box_example.h b/ui/views/examples/message_box_example.h
index d8648c5..0319ac2dc 100644
--- a/ui/views/examples/message_box_example.h
+++ b/ui/views/examples/message_box_example.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_EXAMPLES_MESSAGE_BOX_EXAMPLE_H_
 #define UI_VIEWS_EXAMPLES_MESSAGE_BOX_EXAMPLE_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/examples/example_base.h"
diff --git a/ui/views/examples/scroll_view_example.h b/ui/views/examples/scroll_view_example.h
index 9283b14..89fec4333 100644
--- a/ui/views/examples/scroll_view_example.h
+++ b/ui/views/examples/scroll_view_example.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_EXAMPLES_SCROLL_VIEW_EXAMPLE_H_
 #define UI_VIEWS_EXAMPLES_SCROLL_VIEW_EXAMPLE_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/controls/scroll_view.h"
diff --git a/ui/views/examples/text_example.h b/ui/views/examples/text_example.h
index eb76a150..27ee0d11 100644
--- a/ui/views/examples/text_example.h
+++ b/ui/views/examples/text_example.h
@@ -5,8 +5,6 @@
 #ifndef UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
 #define UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
 
-#include <memory>
-#include <vector>
 
 #include "base/macros.h"
 #include "ui/views/examples/example_base.h"
diff --git a/ui/views/examples/textfield_example.h b/ui/views/examples/textfield_example.h
index 90a4371..f6d35bb7 100644
--- a/ui/views/examples/textfield_example.h
+++ b/ui/views/examples/textfield_example.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_EXAMPLES_TEXTFIELD_EXAMPLE_H_
 #define UI_VIEWS_EXAMPLES_TEXTFIELD_EXAMPLE_H_
 
-#include <string>
 
 #include "base/macros.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 9618d65d..128a3bf 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -334,6 +334,10 @@
   AdvanceFocusIfNecessary();
 }
 
+bool FocusManager::IsSettingFocusedView() const {
+  return setting_focused_view_entrance_count > 0;
+}
+
 void FocusManager::SetFocusedViewWithReason(View* view,
                                             FocusChangeReason reason) {
   if (focused_view_ == view)
@@ -366,6 +370,10 @@
 
   View* old_focused_view = focused_view_;
   focused_view_ = view;
+  base::AutoReset<int> entrance_count_resetter(
+      &setting_focused_view_entrance_count,
+      setting_focused_view_entrance_count + 1);
+
   if (old_focused_view) {
     old_focused_view->RemoveObserver(this);
     old_focused_view->Blur();
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index 6175b8e..eb9939b7 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -302,6 +302,9 @@
   // necessary.
   void SetKeyboardAccessible(bool keyboard_accessible);
 
+  // Checks if a focused view is being set.
+  bool IsSettingFocusedView() const;
+
  private:
   // Returns the focusable view found in the FocusTraversable specified starting
   // at the specified view. This traverses down along the FocusTraversable
@@ -369,6 +372,11 @@
 
   // Whether FocusManager is currently trying to restore a focused view.
   bool in_restoring_focused_view_ = false;
+
+  // Count of SetFocusedViewWithReason() in the current stack.
+  // This value is ideally 0 or 1, i.e. no nested focus change.
+  // See crbug.com/1203960.
+  int setting_focused_view_entrance_count = 0;
 };
 
 }  // namespace views
diff --git a/ui/views/touchui/touch_selection_menu_runner_views.h b/ui/views/touchui/touch_selection_menu_runner_views.h
index a78e6042..fac09e47 100644
--- a/ui/views/touchui/touch_selection_menu_runner_views.h
+++ b/ui/views/touchui/touch_selection_menu_runner_views.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_TOUCHUI_TOUCH_SELECTION_MENU_RUNNER_VIEWS_H_
 #define UI_VIEWS_TOUCHUI_TOUCH_SELECTION_MENU_RUNNER_VIEWS_H_
 
-#include <memory>
 
 #include "base/macros.h"
 #include "ui/touch_selection/touch_selection_menu_runner.h"
diff --git a/ui/views/widget/desktop_aura/window_shape_updater.h b/ui/views/widget/desktop_aura/window_shape_updater.h
index ec77362..da2a6cae 100644
--- a/ui/views/widget/desktop_aura/window_shape_updater.h
+++ b/ui/views/widget/desktop_aura/window_shape_updater.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_WINDOW_SHAPE_UPDATER_H_
 #define UI_VIEWS_WIDGET_DESKTOP_AURA_WINDOW_SHAPE_UPDATER_H_
 
-#include <memory>
 
 #include "ui/aura/window_observer.h"
 #include "ui/compositor/layer.h"
diff --git a/ui/views/widget/drop_helper.h b/ui/views/widget/drop_helper.h
index c643bd6..f361de1 100644
--- a/ui/views/widget/drop_helper.h
+++ b/ui/views/widget/drop_helper.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_WIDGET_DROP_HELPER_H_
 #define UI_VIEWS_WIDGET_DROP_HELPER_H_
 
-#include <utility>
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
diff --git a/ui/views/widget/tooltip_manager.h b/ui/views/widget/tooltip_manager.h
index 3bbdb772..7bda767 100644
--- a/ui/views/widget/tooltip_manager.h
+++ b/ui/views/widget/tooltip_manager.h
@@ -5,7 +5,6 @@
 #ifndef UI_VIEWS_WIDGET_TOOLTIP_MANAGER_H_
 #define UI_VIEWS_WIDGET_TOOLTIP_MANAGER_H_
 
-#include <string>
 
 #include "ui/views/views_export.h"
 
diff --git a/ui/views/win/fullscreen_handler.h b/ui/views/win/fullscreen_handler.h
index c76ef18..29231e2a 100644
--- a/ui/views/win/fullscreen_handler.h
+++ b/ui/views/win/fullscreen_handler.h
@@ -8,7 +8,6 @@
 #include <shobjidl.h>
 #include <wrl/client.h>
 
-#include <map>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
diff --git a/ui/web_dialogs/web_dialog_ui.h b/ui/web_dialogs/web_dialog_ui.h
index 97b467c..6ec68384 100644
--- a/ui/web_dialogs/web_dialog_ui.h
+++ b/ui/web_dialogs/web_dialog_ui.h
@@ -5,8 +5,6 @@
 #ifndef UI_WEB_DIALOGS_WEB_DIALOG_UI_H_
 #define UI_WEB_DIALOGS_WEB_DIALOG_UI_H_
 
-#include <string>
-#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
index 4f5613ae..15d3178f 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.js
@@ -42,6 +42,19 @@
   }
 
   /**
+   * @return {!Promise<number>}
+   */
+  /* #export */ function getNumESimProfiles() {
+    return getEuicc()
+        .then(euicc => {
+          return euicc.getProfileList();
+        })
+        .then(response => {
+          return response.profiles.length;
+        });
+  }
+
+  /**
    * Returns the Euicc that should be used for eSim operations or null
    * if there is none available.
    * @return {!Promise<?chromeos.cellularSetup.mojom.EuiccRemote>}
@@ -94,5 +107,6 @@
     getEuicc,
     getESimProfile,
     getPendingESimProfiles,
+    getNumESimProfiles,
   };
 });
diff --git a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
index cad4531d..83c66ff 100644
--- a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
+++ b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
@@ -22,7 +22,9 @@
       }
     </style>
     <!-- Enter PIN dialog -->
-    <cr-dialog id="enterPinDialog" close-text="[[i18n('close')]]">
+    <cr-dialog id="enterPinDialog"
+        on-cancel="onCancel_"
+        close-text="[[i18n('close')]]">
       <div slot="title">[[i18n('networkSimEnterPinTitle')]]</div>
       <div slot="body">
         <network-password-input id="enterPin"
@@ -36,7 +38,7 @@
         </div>
       </div>
       <div slot="button-container">
-        <cr-button class="cancel-button" on-click="onCancelClick_">
+        <cr-button class="cancel-button" on-click="onCancel_">
           [[i18n('cancel')]]
         </cr-button>
         <cr-button class="action-button"
@@ -48,7 +50,9 @@
     </cr-dialog>
 
     <!-- Change PIN dialog -->
-    <cr-dialog id="changePinDialog" close-text="[[i18n('close')]]">
+    <cr-dialog id="changePinDialog"
+        on-cancel="onCancel_"
+        close-text="[[i18n('close')]]">
       <div slot="title">[[i18n('networkSimChangePinTitle')]]</div>
       <div slot="body">
         <network-password-input id="changePinOld"
@@ -72,7 +76,7 @@
         </div>
       </div>
       <div slot="button-container">
-        <cr-button class="cancel-button" on-click="onCancelClick_">
+        <cr-button class="cancel-button" on-click="onCancel_">
           [[i18n('cancel')]]
         </cr-button>
         <cr-button class="action-button"
@@ -84,7 +88,9 @@
     </cr-dialog>
 
     <!-- Unlock PIN dialog -->
-    <cr-dialog id="unlockPinDialog" close-text="[[i18n('close')]]">
+    <cr-dialog id="unlockPinDialog"
+        on-cancel="onCancel_"
+        close-text="[[i18n('close')]]">
       <div slot="title">[[i18n('networkSimLockedTitle')]]</div>
       <div slot="body">
         <network-password-input id="unlockPin"
@@ -98,7 +104,7 @@
         </div>
       </div>
       <div slot="button-container">
-        <cr-button class="cancel-button" on-click="onCancelClick_">
+        <cr-button class="cancel-button" on-click="onCancel_">
           [[i18n('cancel')]]
         </cr-button>
         <cr-button class="action-button"
@@ -110,7 +116,9 @@
     </cr-dialog>
 
     <!-- Unlock PUK dialog -->
-    <cr-dialog id="unlockPukDialog" close-text="[[i18n('close')]]">
+    <cr-dialog id="unlockPukDialog"
+        on-cancel="onCancel_"
+        close-text="[[i18n('close')]]">
       <div slot="title">[[i18n('networkSimLockedTitle')]]</div>
       <div slot="body">
         <div>
@@ -140,7 +148,7 @@
         </div>
       </div>
       <div slot="button-container">
-        <cr-button class="cancel-button" on-click="onCancelClick_">
+        <cr-button class="cancel-button" on-click="onCancel_">
           [[i18n('cancel')]]
         </cr-button>
         <cr-button class="action-button"
diff --git a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
index 9c844be..1973abe 100644
--- a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
+++ b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
@@ -394,7 +394,7 @@
    * @param {!Event} event
    * @private
    */
-  onCancelClick_(event) {
+  onCancel_(event) {
     event.stopPropagation();
     this.closeDialogs_();
   },
diff --git a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
index 4b0c328..b1d19df0 100644
--- a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
+++ b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -21,6 +21,7 @@
   "cellular_setup.setESimManagerRemoteForTesting|setESimManagerRemoteForTesting",
   "cellular_setup.observeESimManager|observeESimManager",
   "cellular_setup.getPendingESimProfiles|getPendingESimProfiles",
+  "cellular_setup.getNumESimProfiles|getNumESimProfiles",
   "cellular_setup.getEuicc|getEuicc",
   "cellular_setup.getESimProfile|getESimProfile",
   "cellular_setup.CellularSetupDelegate|CellularSetupDelegate",
@@ -44,7 +45,7 @@
   "ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_delegate.html|CellularSetupDelegate",
   "ui/webui/resources/cr_components/chromeos/cellular_setup/subflow_behavior.html|SubflowBehavior",
   "ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.html|setCellularSetupRemoteForTesting,getCellularSetupRemote,setESimManagerRemoteForTesting,getESimManagerRemote,observeESimManager",
-  "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html|getPendingESimProfiles,getEuicc,getESimProfile",
+  "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html|getPendingESimProfiles,getNumESimProfiles,getEuicc,getESimProfile",
   "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.html|ESimManagerListenerBehavior",
   "ui/webui/resources/cr_components/chromeos/cellular_setup/setup_loading_page.html|LoadingPageState",
   "ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html|BrowserProxy,BrowserProxyImpl",
diff --git a/ui/wm/core/native_cursor_manager.h b/ui/wm/core/native_cursor_manager.h
index 1df3489..165f0f6 100644
--- a/ui/wm/core/native_cursor_manager.h
+++ b/ui/wm/core/native_cursor_manager.h
@@ -5,7 +5,6 @@
 #ifndef UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
 #define UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
 
-#include <string>
 
 #include "ui/base/cursor/cursor.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
diff --git a/ui/wm/core/window_animations.h b/ui/wm/core/window_animations.h
index 4f425ca..066de998 100644
--- a/ui/wm/core/window_animations.h
+++ b/ui/wm/core/window_animations.h
@@ -5,7 +5,6 @@
 #ifndef UI_WM_CORE_WINDOW_ANIMATIONS_H_
 #define UI_WM_CORE_WINDOW_ANIMATIONS_H_
 
-#include <vector>
 
 #include "base/macros.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
diff --git a/url/gurl.cc b/url/gurl.cc
index 675217d5..82ae837 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -413,11 +413,11 @@
 }
 
 std::string GURL::PathForRequest() const {
-  return PathForRequestPiece().as_string();
+  return std::string(PathForRequestPiece());
 }
 
 std::string GURL::HostNoBrackets() const {
-  return HostNoBracketsPiece().as_string();
+  return std::string(HostNoBracketsPiece());
 }
 
 base::StringPiece GURL::HostNoBracketsPiece() const {
@@ -502,7 +502,7 @@
 
   if ((actual_path.size() == allowed_path.size() + 1) &&
       actual_path.back() == '/') {
-    DCHECK_EQ(actual_path, allowed_path.as_string() + '/');
+    DCHECK_EQ(actual_path, std::string(allowed_path) + '/');
     return true;
   }
 
diff --git a/url/origin.cc b/url/origin.cc
index 12a85a7..e470d064 100644
--- a/url/origin.cc
+++ b/url/origin.cc
@@ -16,6 +16,7 @@
 #include "base/pickle.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
 #include "url/gurl.h"
@@ -77,7 +78,7 @@
     base::StringPiece scheme,
     base::StringPiece host,
     uint16_t port) {
-  SchemeHostPort tuple(scheme.as_string(), host.as_string(), port,
+  SchemeHostPort tuple(std::string(scheme), std::string(host), port,
                        SchemeHostPort::CHECK_CANONICALIZATION);
   if (!tuple.IsValid())
     return base::nullopt;
@@ -90,8 +91,8 @@
     base::StringPiece precursor_host,
     uint16_t precursor_port,
     const Origin::Nonce& nonce) {
-  SchemeHostPort precursor(precursor_scheme.as_string(),
-                           precursor_host.as_string(), precursor_port,
+  SchemeHostPort precursor(std::string(precursor_scheme),
+                           std::string(precursor_host), precursor_port,
                            SchemeHostPort::CHECK_CANONICALIZATION);
   // For opaque origins, it is okay for the SchemeHostPort to be invalid;
   // however, this should only arise when the arguments indicate the
diff --git a/url/scheme_host_port.cc b/url/scheme_host_port.cc
index 61239b1..490f17b 100644
--- a/url/scheme_host_port.cc
+++ b/url/scheme_host_port.cc
@@ -14,6 +14,7 @@
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "url/gurl.h"
 #include "url/third_party/mozilla/url_parse.h"
 #include "url/url_canon.h"
@@ -159,8 +160,8 @@
 SchemeHostPort::SchemeHostPort(base::StringPiece scheme,
                                base::StringPiece host,
                                uint16_t port)
-    : SchemeHostPort(scheme.as_string(),
-                     host.as_string(),
+    : SchemeHostPort(std::string(scheme),
+                     std::string(host),
                      port,
                      ConstructPolicy::CHECK_CANONICALIZATION) {}