diff --git a/DEPS b/DEPS
index 5c264987..3231285e 100644
--- a/DEPS
+++ b/DEPS
@@ -133,11 +133,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': 'e6a83e16086095ffcc14a2b9a37a1b6392100a55',
+  'skia_revision': '6c8f5b31ac49be07ce68efb176a803a38810cb44',
   # 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': '8733ff5449b43d9eaf4a6dcaf2344032cd61a149',
+  'v8_revision': 'c77ce38099096de1347aa59f9d5b93191bf4b4f4',
   # 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.
@@ -145,15 +145,15 @@
   # 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': '3fb957a00ba37257efd6b635ce58e57127253557',
+  'angle_revision': '0f861bd8c46f7ae179c425a3be861b1bb8414dd2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '2e2385837e9b46547d8fb944882f93ac9088c40b',
+  'swiftshader_revision': 'd354695df3cbfebe261ee554f6db7c768f57e41b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '0eaf1902e2845134ed8e765f0421d2621a44e856',
+  'pdfium_revision': '8f64f4a25dc8311f798947cf073ab152827f5328',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -200,7 +200,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'c86b091be0e05ddefb1fbf321985cc31f453f2b3',
+  'catapult_revision': '178118d233d98876cdf0cb472e7c91614cc1988f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -272,11 +272,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '11b703904ab61b08f08aae8e36cdb726826e6487',
+  'dawn_revision': 'cc141797dfc8fd0d10eafb96c9bfab7b341b8bd4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': 'c703612c85f2b72c2c4e91956f48a27eb7f4833f',
+  'quiche_revision': '6cf4d2ab35b79479428d43a65b5211c2814d8747',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -1184,7 +1184,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '23f7a5a007a077ccb4a20fb2cf316b3a6aaaee4c',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '7f17b0b76444d19ff5c39bede231acc23fafb348',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1396,7 +1396,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@831c8b54505e241951b29542732d287326faa4cb',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c6d9391d98ae5bf66405852d2ab823f4de51d1b0',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index cd765da5..733ab4e 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1362,8 +1362,6 @@
     "//chromeos/services/multidevice_setup/public/mojom",
     "//chromeos/services/network_config/public/cpp",
     "//chromeos/services/network_config/public/mojom",
-    "//chromeos/services/power/public/cpp:controller",
-    "//chromeos/services/power/public/mojom",
     "//chromeos/settings",
     "//chromeos/strings",
     "//chromeos/system",
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc
index 6cc514ff..f113ad3b 100644
--- a/ash/mojo_interface_factory.cc
+++ b/ash/mojo_interface_factory.cc
@@ -54,7 +54,6 @@
 #include "base/lazy_instance.h"
 #include "base/single_thread_task_runner.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_controller.h"
 #include "ui/keyboard/keyboard_controller.h"
 
 namespace ash {
@@ -273,12 +272,6 @@
   Shell::Get()->split_view_controller()->BindRequest(std::move(request));
 }
 
-void BindPowerManagerControllerRequestOnMainThread(
-    chromeos::power::mojom::PowerManagerControllerRequest request) {
-  Shell::Get()->power_manager_mojo_controller()->BindRequest(
-      std::move(request));
-}
-
 }  // namespace
 
 void RegisterInterfaces(
@@ -410,9 +403,6 @@
                          main_thread_task_runner);
   registry->AddInterface(base::BindRepeating(&BindSplitViewRequestOnMainThread),
                          main_thread_task_runner);
-  registry->AddInterface(
-      base::BindRepeating(&BindPowerManagerControllerRequestOnMainThread),
-      main_thread_task_runner);
 
   // Inject additional optional interfaces.
   if (g_register_interfaces_callback.Get()) {
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index f67cce4..1aa4102 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -179,7 +179,6 @@
     "//base",
     "//chromeos/services/multidevice_setup/public/mojom",
     "//chromeos/services/network_config/public/mojom",
-    "//chromeos/services/power/public/mojom",
     "//services/content/public/mojom",
     "//services/data_decoder/public/mojom",
     "//services/device/public/mojom",
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc
index 6dca609..902003e 100644
--- a/ash/public/cpp/manifest.cc
+++ b/ash/public/cpp/manifest.cc
@@ -45,7 +45,6 @@
 #include "base/no_destructor.h"
 #include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
 #include "chromeos/services/network_config/public/mojom/constants.mojom.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom.h"
 #include "services/content/public/mojom/constants.mojom.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -77,7 +76,6 @@
           .ExposeCapability(
               "system_ui",
               service_manager::Manifest::InterfaceList<
-                  chromeos::power::mojom::PowerManagerController,
                   mojom::AcceleratorController, mojom::AccessibilityController,
                   mojom::AccessibilityFocusRingController,
                   mojom::AppListController, mojom::ArcCustomTabController,
diff --git a/ash/shell.cc b/ash/shell.cc
index b80e81a..6414b376 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -178,7 +178,6 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/dbus/initialize_dbus_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_controller.h"
 #include "chromeos/system/devicemode.h"
 #include "components/exo/file_helper.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -676,11 +675,6 @@
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
 
-  if (base::FeatureList::IsEnabled(chromeos::features::kMojoDBusRelay)) {
-    power_manager_mojo_controller_ =
-        std::make_unique<chromeos::PowerManagerMojoController>();
-  }
-
   login_screen_controller_ =
       std::make_unique<LoginScreenController>(system_tray_notifier_.get());
   display_manager_.reset(ScreenAsh::CreateDisplayManager());
@@ -955,8 +949,6 @@
   // before it.
   detachable_base_handler_.reset();
 
-  power_manager_mojo_controller_.reset();
-
   // MediaNotificationController depends on MessageCenter and must be destructed
   // before it.
   media_notification_controller_.reset();
diff --git a/ash/shell.h b/ash/shell.h
index 28a2ea7..b90ce0c2 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -35,10 +35,6 @@
 class Window;
 }  // namespace aura
 
-namespace chromeos {
-class PowerManagerMojoController;
-}
-
 namespace dbus {
 class Bus;
 }
@@ -472,9 +468,6 @@
   NewWindowController* new_window_controller() {
     return new_window_controller_.get();
   }
-  chromeos::PowerManagerMojoController* power_manager_mojo_controller() {
-    return power_manager_mojo_controller_.get();
-  }
   NightLightController* night_light_controller();
   NoteTakingController* note_taking_controller() {
     return note_taking_controller_.get();
@@ -767,8 +760,6 @@
   std::unique_ptr<MultiDeviceNotificationPresenter>
       multidevice_notification_presenter_;
   std::unique_ptr<NewWindowController> new_window_controller_;
-  std::unique_ptr<chromeos::PowerManagerMojoController>
-      power_manager_mojo_controller_;
   std::unique_ptr<ResizeShadowController> resize_shadow_controller_;
   std::unique_ptr<SessionController> session_controller_;
   std::unique_ptr<NightLightController> night_light_controller_;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 8e9076ba..535677d 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -825,34 +825,16 @@
     "task/thread_pool/environment_config.h",
     "task/thread_pool/initialization_util.cc",
     "task/thread_pool/initialization_util.h",
-    "task/thread_pool/platform_native_worker_pool.cc",
-    "task/thread_pool/platform_native_worker_pool.h",
-    "task/thread_pool/platform_native_worker_pool_mac.h",
-    "task/thread_pool/platform_native_worker_pool_mac.mm",
-    "task/thread_pool/platform_native_worker_pool_win.cc",
-    "task/thread_pool/platform_native_worker_pool_win.h",
+    "task/thread_pool/pooled_parallel_task_runner.cc",
+    "task/thread_pool/pooled_parallel_task_runner.h",
+    "task/thread_pool/pooled_sequenced_task_runner.cc",
+    "task/thread_pool/pooled_sequenced_task_runner.h",
+    "task/thread_pool/pooled_single_thread_task_runner_manager.cc",
+    "task/thread_pool/pooled_single_thread_task_runner_manager.h",
+    "task/thread_pool/pooled_task_runner_delegate.cc",
+    "task/thread_pool/pooled_task_runner_delegate.h",
     "task/thread_pool/priority_queue.cc",
     "task/thread_pool/priority_queue.h",
-    "task/thread_pool/scheduler_parallel_task_runner.cc",
-    "task/thread_pool/scheduler_parallel_task_runner.h",
-    "task/thread_pool/scheduler_sequenced_task_runner.cc",
-    "task/thread_pool/scheduler_sequenced_task_runner.h",
-    "task/thread_pool/scheduler_single_thread_task_runner_manager.cc",
-    "task/thread_pool/scheduler_single_thread_task_runner_manager.h",
-    "task/thread_pool/scheduler_task_runner_delegate.cc",
-    "task/thread_pool/scheduler_task_runner_delegate.h",
-    "task/thread_pool/scheduler_worker.cc",
-    "task/thread_pool/scheduler_worker.h",
-    "task/thread_pool/scheduler_worker_observer.h",
-    "task/thread_pool/scheduler_worker_params.h",
-    "task/thread_pool/scheduler_worker_pool.cc",
-    "task/thread_pool/scheduler_worker_pool.h",
-    "task/thread_pool/scheduler_worker_pool_impl.cc",
-    "task/thread_pool/scheduler_worker_pool_impl.h",
-    "task/thread_pool/scheduler_worker_pool_params.cc",
-    "task/thread_pool/scheduler_worker_pool_params.h",
-    "task/thread_pool/scheduler_worker_stack.cc",
-    "task/thread_pool/scheduler_worker_stack.h",
     "task/thread_pool/sequence.cc",
     "task/thread_pool/sequence.h",
     "task/thread_pool/sequence_sort_key.cc",
@@ -865,11 +847,29 @@
     "task/thread_pool/task_source.h",
     "task/thread_pool/task_tracker.cc",
     "task/thread_pool/task_tracker.h",
+    "task/thread_pool/thread_group.cc",
+    "task/thread_pool/thread_group.h",
+    "task/thread_pool/thread_group_impl.cc",
+    "task/thread_pool/thread_group_impl.h",
+    "task/thread_pool/thread_group_native.cc",
+    "task/thread_pool/thread_group_native.h",
+    "task/thread_pool/thread_group_native_mac.h",
+    "task/thread_pool/thread_group_native_mac.mm",
+    "task/thread_pool/thread_group_native_win.cc",
+    "task/thread_pool/thread_group_native_win.h",
+    "task/thread_pool/thread_group_params.cc",
+    "task/thread_pool/thread_group_params.h",
     "task/thread_pool/thread_pool.cc",
     "task/thread_pool/thread_pool.h",
     "task/thread_pool/thread_pool_impl.cc",
     "task/thread_pool/thread_pool_impl.h",
     "task/thread_pool/tracked_ref.h",
+    "task/thread_pool/worker_thread.cc",
+    "task/thread_pool/worker_thread.h",
+    "task/thread_pool/worker_thread_observer.h",
+    "task/thread_pool/worker_thread_params.h",
+    "task/thread_pool/worker_thread_stack.cc",
+    "task/thread_pool/worker_thread_stack.h",
     "task_runner.cc",
     "task_runner.h",
     "task_runner_util.h",
@@ -1889,8 +1889,8 @@
       "strings/sys_string_conversions_mac.mm",
       "synchronization/waitable_event_mac.cc",
       "system/sys_info_ios.mm",
-      "task/thread_pool/platform_native_worker_pool_mac.h",
-      "task/thread_pool/platform_native_worker_pool_mac.mm",
+      "task/thread_pool/thread_group_native_mac.h",
+      "task/thread_pool/thread_group_native_mac.mm",
       "threading/platform_thread_mac.mm",
       "time/time_conversion_posix.cc",
       "time/time_mac.cc",
@@ -2603,12 +2603,8 @@
     "task/task_traits_unittest.cc",
     "task/thread_pool/can_run_policy_test.h",
     "task/thread_pool/delayed_task_manager_unittest.cc",
+    "task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc",
     "task/thread_pool/priority_queue_unittest.cc",
-    "task/thread_pool/scheduler_single_thread_task_runner_manager_unittest.cc",
-    "task/thread_pool/scheduler_worker_pool_impl_unittest.cc",
-    "task/thread_pool/scheduler_worker_pool_unittest.cc",
-    "task/thread_pool/scheduler_worker_stack_unittest.cc",
-    "task/thread_pool/scheduler_worker_unittest.cc",
     "task/thread_pool/sequence_sort_key_unittest.cc",
     "task/thread_pool/sequence_unittest.cc",
     "task/thread_pool/service_thread_unittest.cc",
@@ -2618,8 +2614,12 @@
     "task/thread_pool/test_task_factory.h",
     "task/thread_pool/test_utils.cc",
     "task/thread_pool/test_utils.h",
+    "task/thread_pool/thread_group_impl_unittest.cc",
+    "task/thread_pool/thread_group_unittest.cc",
     "task/thread_pool/thread_pool_impl_unittest.cc",
     "task/thread_pool/tracked_ref_unittest.cc",
+    "task/thread_pool/worker_thread_stack_unittest.cc",
+    "task/thread_pool/worker_thread_unittest.cc",
     "task_runner_util_unittest.cc",
     "template_util_unittest.cc",
     "test/launcher/test_results_tracker_unittest.cc",
@@ -3299,6 +3299,7 @@
       "test/android/javatests/src/org/chromium/base/test/util/Feature.java",
       "test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java",
       "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java",
+      "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferencesContext.java",
       "test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java",
       "test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java",
       "test/android/javatests/src/org/chromium/base/test/util/JniMocker.java",
diff --git a/base/android/java/src/org/chromium/base/process_launcher/BindService.java b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
index ac304e70..fef84ec 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/BindService.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
@@ -25,26 +25,31 @@
  */
 final class BindService {
     private static final Method sDoBindServiceQMethod;
+    private static final Method sUpdateServiceGroupQMethod;
     static {
-        Method method = null;
+        Method bindMethod = null;
+        Method updateServiceGroupMethod = null;
         try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
             if (BuildInfo.isAtLeastQ()) {
                 Class<?> clazz =
                         Class.forName("org.chromium.base.process_launcher.BindServiceInternal");
-                method = clazz.getDeclaredMethod("doBindServiceQ", Context.class, Intent.class,
+                bindMethod = clazz.getDeclaredMethod("doBindServiceQ", Context.class, Intent.class,
                         ServiceConnection.class, int.class, Executor.class, String.class);
+                updateServiceGroupMethod = clazz.getDeclaredMethod("updateServiceGroupQ",
+                        Context.class, ServiceConnection.class, int.class, int.class);
             }
         } catch (Exception e) {
             // Ignore exceptions.
         } finally {
-            sDoBindServiceQMethod = method;
+            sDoBindServiceQMethod = bindMethod;
+            sUpdateServiceGroupQMethod = updateServiceGroupMethod;
         }
     }
 
     private static Method sBindServiceAsUserMethod;
 
     static boolean supportVariableConnections() {
-        return sDoBindServiceQMethod != null;
+        return sDoBindServiceQMethod != null && sUpdateServiceGroupQMethod != null;
     }
 
     // Note that handler is not guaranteed to be used, and client still need to correctly handle
@@ -71,6 +76,15 @@
         }
     }
 
+    static void updateServiceGroup(
+            Context context, ServiceConnection connection, int group, int importance) {
+        try {
+            sUpdateServiceGroupQMethod.invoke(null, context, connection, group, importance);
+        } catch (ReflectiveOperationException e) {
+            // Ignore reflection errors.
+        }
+    }
+
     private static boolean bindServiceByCall(
             Context context, Intent intent, ServiceConnection connection, int flags) {
         return context.bindService(intent, connection, flags);
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
index f5937966..d6485a4 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -103,6 +103,7 @@
         boolean bind();
         void unbind();
         boolean isBound();
+        void updateGroupImportance(int group, int importanceInGroup);
     }
 
     /** Implementation of ChildServiceConnection that does connect to a service. */
@@ -157,6 +158,16 @@
         }
 
         @Override
+        public void updateGroupImportance(int group, int importanceInGroup) {
+            assert isBound();
+            if (BindService.supportVariableConnections()) {
+                BindService.updateServiceGroup(mContext, this, group, importanceInGroup);
+                BindService.doBindService(mContext, mBindIntent, this, mBindFlags, mHandler,
+                        mExecutor, mInstanceName);
+            }
+        }
+
+        @Override
         public void onServiceConnected(ComponentName className, final IBinder service) {
             mDelegate.onServiceConnected(service);
         }
@@ -251,6 +262,9 @@
     private int mStrongBindingCount;
     private int mModerateBindingCount;
 
+    private int mGroup;
+    private int mImportanceInGroup;
+
     // Set to true once unbind() was called.
     private boolean mUnbound;
 
@@ -642,6 +656,17 @@
         }
     }
 
+    public void updateGroupImportance(int group, int importanceInGroup) {
+        assert isRunningOnLauncherThread();
+        assert !mUnbound;
+        assert mWaivedBinding.isBound();
+        if (mGroup != group || mImportanceInGroup != importanceInGroup) {
+            mGroup = group;
+            mImportanceInGroup = importanceInGroup;
+            mWaivedBinding.updateGroupImportance(group, importanceInGroup);
+        }
+    }
+
     public boolean isStrongBindingBound() {
         assert isRunningOnLauncherThread();
         return mStrongBinding.isBound();
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
index f5cf7df..605dd7d 100644
--- a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
+++ b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
@@ -42,6 +42,8 @@
 import org.chromium.base.ChildBindingState;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
+import java.util.ArrayList;
+
 /** Unit tests for ChildProcessConnection. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
@@ -51,6 +53,8 @@
         private final Intent mBindIntent;
         private final ChildProcessConnection.ChildServiceConnectionDelegate mDelegate;
         private boolean mBound;
+        private int mGroup;
+        private int mImportanceInGroup;
 
         public ChildServiceConnectionMock(
                 Intent bindIntent, ChildProcessConnection.ChildServiceConnectionDelegate delegate) {
@@ -74,6 +78,12 @@
             return mBound;
         }
 
+        @Override
+        public void updateGroupImportance(int group, int importanceInGroup) {
+            mGroup = group;
+            mImportanceInGroup = importanceInGroup;
+        }
+
         public void notifyServiceConnected(IBinder service) {
             mDelegate.onServiceConnected(service);
         }
@@ -85,6 +95,14 @@
         public Intent getBindIntent() {
             return mBindIntent;
         }
+
+        public int getGroup() {
+            return mGroup;
+        }
+
+        public int getImportanceInGroup() {
+            return mImportanceInGroup;
+        }
     };
 
     private final ChildProcessConnection.ChildServiceConnectionFactory mServiceConnectionFactory =
@@ -99,6 +117,7 @@
                     if (mFirstServiceConnection == null) {
                         mFirstServiceConnection = connection;
                     }
+                    mMockConnections.add(connection);
                     return connection;
                 }
             };
@@ -114,6 +133,7 @@
     private Binder mChildProcessServiceBinder;
 
     private ChildServiceConnectionMock mFirstServiceConnection;
+    private final ArrayList<ChildServiceConnectionMock> mMockConnections = new ArrayList<>();
 
     // Parameters captured from the IChildProcessService.setupConnection() call
     private Bundle mConnectionBundle;
@@ -441,4 +461,17 @@
         assertArrayEquals(
                 connection1.remainingBindingStateCountsCurrentOrWhenDied(), new int[] {0, 1, 0, 0});
     }
+
+    @Test
+    public void testUpdateGroupImportanceSmoke() {
+        ChildProcessConnection connection = createDefaultTestConnection();
+        connection.start(false /* useStrongBinding */, null /* serviceCallback */);
+        connection.updateGroupImportance(1, 2);
+        // Expect a important, moderate and waived bindings.
+        assertEquals(3, mMockConnections.size());
+        // Group should be set on the wavied (last) binding.
+        ChildServiceConnectionMock mock = mMockConnections.get(mMockConnections.size() - 1);
+        assertEquals(1, mock.getGroup());
+        assertEquals(2, mock.getImportanceInGroup());
+    }
 }
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
index e219ee15..afef04ae 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -444,6 +444,16 @@
   ~RefCountedData() = default;
 };
 
+template <typename T>
+bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
+  return lhs.data == rhs.data;
+}
+
+template <typename T>
+bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
+  return !(lhs == rhs);
+}
+
 }  // namespace base
 
 #endif  // BASE_MEMORY_REF_COUNTED_H_
diff --git a/base/task/scoped_set_task_priority_for_current_thread_unittest.cc b/base/task/scoped_set_task_priority_for_current_thread_unittest.cc
index 838fad9e..b1dbd96 100644
--- a/base/task/scoped_set_task_priority_for_current_thread_unittest.cc
+++ b/base/task/scoped_set_task_priority_for_current_thread_unittest.cc
@@ -10,7 +10,7 @@
 namespace base {
 namespace internal {
 
-TEST(ThreadPoolScopedSetTaskPriorityForCurrentThreadTest,
+TEST(ScopedSetTaskPriorityForCurrentThreadTest,
      ScopedSetTaskPriorityForCurrentThread) {
   EXPECT_EQ(TaskPriority::USER_VISIBLE, GetTaskPriorityForCurrentThread());
   {
diff --git a/base/task/sequence_manager/sequence_manager_perftest.cc b/base/task/sequence_manager/sequence_manager_perftest.cc
index 818c54a3..9d76444 100644
--- a/base/task/sequence_manager/sequence_manager_perftest.cc
+++ b/base/task/sequence_manager/sequence_manager_perftest.cc
@@ -86,8 +86,8 @@
   kUseUIMessageLoop,
   kUseIOMessageLoop,
 
-  // A SingleThreadTaskRunner in the worker pool.
-  kUseSingleThreadInWorkerPool,
+  // A SingleThreadTaskRunner in the thread pool.
+  kUseSingleThreadInThreadPool,
 };
 
 // Customization point for SequenceManagerPerfTest which allows us to test
@@ -240,21 +240,21 @@
   std::unique_ptr<RunLoop> run_loop_;
 };
 
-class SingleThreadInWorkerPoolPerfTestDelegate : public PerfTestDelegate {
+class SingleThreadInThreadPoolPerfTestDelegate : public PerfTestDelegate {
  public:
-  SingleThreadInWorkerPoolPerfTestDelegate() : done_cond_(&done_lock_) {
+  SingleThreadInThreadPoolPerfTestDelegate() : done_cond_(&done_lock_) {
     ThreadPool::SetInstance(
         std::make_unique<::base::internal::ThreadPoolImpl>("Test"));
     ThreadPool::GetInstance()->StartWithDefaultParams();
   }
 
-  ~SingleThreadInWorkerPoolPerfTestDelegate() override {
+  ~SingleThreadInThreadPoolPerfTestDelegate() override {
     ThreadPool::GetInstance()->JoinForTesting();
     ThreadPool::SetInstance(nullptr);
   }
 
   const char* GetName() const override {
-    return " single thread in WorkerPool ";
+    return " single thread in ThreadPool ";
   }
 
   bool VirtualTimeIsSupported() const override { return false; }
@@ -639,8 +639,8 @@
         return std::make_unique<MessageLoopPerfTestDelegate>(
             " MessageLoopForIO ", std::make_unique<MessageLoopForIO>());
 
-      case PerfTestType::kUseSingleThreadInWorkerPool:
-        return std::make_unique<SingleThreadInWorkerPoolPerfTestDelegate>();
+      case PerfTestType::kUseSingleThreadInThreadPool:
+        return std::make_unique<SingleThreadInThreadPoolPerfTestDelegate>();
 
       default:
         NOTREACHED();
@@ -696,7 +696,7 @@
         PerfTestType::kUseMessageLoop,
         PerfTestType::kUseUIMessageLoop,
         PerfTestType::kUseIOMessageLoop,
-        PerfTestType::kUseSingleThreadInWorkerPool,
+        PerfTestType::kUseSingleThreadInThreadPool,
         PerfTestType::kUseSequenceManagerWithMessagePumpAndRandomSampling));
 TEST_P(SequenceManagerPerfTest, PostDelayedTasks_OneQueue) {
   if (!delegate_->VirtualTimeIsSupported()) {
diff --git a/base/task/task_features.h b/base/task/task_features.h
index 21d8719..cc24bd69 100644
--- a/base/task/task_features.h
+++ b/base/task/task_features.h
@@ -16,7 +16,7 @@
 extern const BASE_EXPORT Feature kAllTasksUserBlocking;
 extern const BASE_EXPORT Feature kMergeBlockingNonBlockingPools;
 
-// Under this feature, unused threads in SchedulerWorkerPool are only detached
+// Under this feature, unused threads in ThreadGroup are only detached
 // if the total number of threads in the pool is above the initial capacity.
 extern const BASE_EXPORT Feature kNoDetachBelowInitialCapacity;
 
@@ -25,7 +25,7 @@
 extern const BASE_EXPORT Feature kMayBlockWithoutDelay;
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
-// Under this feature, ThreadPool will use a SchedulerWorkerPool backed by a
+// Under this feature, ThreadPool will use a ThreadGroup backed by a
 // native thread pool implementation. The Windows Thread Pool API and
 // libdispatch are used on Windows and macOS/iOS respectively.
 extern const BASE_EXPORT Feature kUseNativeThreadPool;
diff --git a/base/task/thread_pool/environment_config.cc b/base/task/thread_pool/environment_config.cc
index eeb4df9..b69f4f9 100644
--- a/base/task/thread_pool/environment_config.cc
+++ b/base/task/thread_pool/environment_config.cc
@@ -19,9 +19,9 @@
   return is_background ? BACKGROUND : FOREGROUND;
 }
 
-bool CanUseBackgroundPriorityForSchedulerWorker() {
+bool CanUseBackgroundPriorityForWorkerThread() {
   // When Lock doesn't handle multiple thread priorities, run all
-  // SchedulerWorker with a normal priority to avoid priority inversion when a
+  // WorkerThread with a normal priority to avoid priority inversion when a
   // thread running with a normal priority tries to acquire a lock held by a
   // thread running with a background priority.
   if (!Lock::HandlesMultipleThreadPriorities())
diff --git a/base/task/thread_pool/environment_config.h b/base/task/thread_pool/environment_config.h
index 23432ead..0bda159 100644
--- a/base/task/thread_pool/environment_config.h
+++ b/base/task/thread_pool/environment_config.h
@@ -15,7 +15,7 @@
 namespace internal {
 
 // TODO(etiennep): This is now specific to
-// SchedulerSingleThreadTaskRunnerManager, move it there.
+// PooledSingleThreadTaskRunnerManager, move it there.
 enum EnvironmentType {
   FOREGROUND = 0,
   FOREGROUND_BLOCKING,
@@ -44,9 +44,9 @@
 
 size_t BASE_EXPORT GetEnvironmentIndexForTraits(const TaskTraits& traits);
 
-// Returns true if this platform supports having SchedulerWorkers running with a
+// Returns true if this platform supports having WorkerThreads running with a
 // background priority.
-bool BASE_EXPORT CanUseBackgroundPriorityForSchedulerWorker();
+bool BASE_EXPORT CanUseBackgroundPriorityForWorkerThread();
 
 }  // namespace internal
 }  // namespace base
diff --git a/base/task/thread_pool/platform_native_worker_pool_mac.h b/base/task/thread_pool/platform_native_worker_pool_mac.h
deleted file mode 100644
index 01f080b5..0000000
--- a/base/task/thread_pool/platform_native_worker_pool_mac.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_MAC_H_
-#define BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_MAC_H_
-
-#include <dispatch/dispatch.h>
-
-#include "base/base_export.h"
-#include "base/mac/scoped_dispatch_object.h"
-#include "base/task/thread_pool/platform_native_worker_pool.h"
-
-namespace base {
-namespace internal {
-
-// A SchedulerWorkerPool implementation backed by libdispatch.
-//
-// libdispatch official documentation:
-// https://developer.apple.com/documentation/dispatch
-//
-// Guides:
-// https://apple.github.io/swift-corelibs-libdispatch/tutorial/
-// https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
-class BASE_EXPORT PlatformNativeWorkerPoolMac
-    : public PlatformNativeWorkerPool {
- public:
-  PlatformNativeWorkerPoolMac(TrackedRef<TaskTracker> task_tracker,
-                              TrackedRef<Delegate> delegate,
-                              SchedulerWorkerPool* predecessor_pool = nullptr);
-
-  ~PlatformNativeWorkerPoolMac() override;
-
- private:
-  // PlatformNativeWorkerPool:
-  void JoinImpl() override;
-  void StartImpl() override;
-  void SubmitWork() override;
-
-  // Dispatch queue on which work is scheduled. Backed by a shared thread pool
-  // managed by libdispatch.
-  ScopedDispatchObject<dispatch_queue_t> queue_;
-
-  // Dispatch group to enable synchronization.
-  ScopedDispatchObject<dispatch_group_t> group_;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformNativeWorkerPoolMac);
-};
-
-using PlatformNativeWorkerPoolImpl = PlatformNativeWorkerPoolMac;
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_MAC_H_
diff --git a/base/task/thread_pool/platform_native_worker_pool_mac.mm b/base/task/thread_pool/platform_native_worker_pool_mac.mm
deleted file mode 100644
index ec21eb2..0000000
--- a/base/task/thread_pool/platform_native_worker_pool_mac.mm
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/task/thread_pool/platform_native_worker_pool_mac.h"
-
-#include "base/task/thread_pool/task_tracker.h"
-
-namespace base {
-namespace internal {
-
-PlatformNativeWorkerPoolMac::PlatformNativeWorkerPoolMac(
-    TrackedRef<TaskTracker> task_tracker,
-    TrackedRef<Delegate> delegate,
-    SchedulerWorkerPool* predecessor_pool)
-    : PlatformNativeWorkerPool(std::move(task_tracker),
-                               std::move(delegate),
-                               predecessor_pool) {}
-
-PlatformNativeWorkerPoolMac::~PlatformNativeWorkerPoolMac() {}
-
-void PlatformNativeWorkerPoolMac::StartImpl() {
-  queue_.reset(dispatch_queue_create("org.chromium.base.ThreadPool.WorkerPool",
-                                     DISPATCH_QUEUE_CONCURRENT));
-  group_.reset(dispatch_group_create());
-}
-
-void PlatformNativeWorkerPoolMac::JoinImpl() {
-  dispatch_group_wait(group_, DISPATCH_TIME_FOREVER);
-}
-
-void PlatformNativeWorkerPoolMac::SubmitWork() {
-  // TODO(adityakeerthi): Handle priorities by having multiple dispatch queues
-  // with different qualities-of-service.
-  dispatch_group_async(group_, queue_, ^{
-    RunNextTaskSourceImpl();
-  });
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/task/thread_pool/platform_native_worker_pool_win.h b/base/task/thread_pool/platform_native_worker_pool_win.h
deleted file mode 100644
index cabd33f..0000000
--- a/base/task/thread_pool/platform_native_worker_pool_win.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_WIN_H_
-#define BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_WIN_H_
-
-#include <windows.h>
-
-#include "base/base_export.h"
-#include "base/task/thread_pool/platform_native_worker_pool.h"
-
-namespace base {
-namespace internal {
-
-// A SchedulerWorkerPool implementation backed by the Windows Thread Pool API.
-//
-// Windows Thread Pool API official documentation:
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686766(v=vs.85).aspx
-//
-// Blog posts on the Windows Thread Pool API:
-// https://msdn.microsoft.com/magazine/hh335066.aspx
-// https://msdn.microsoft.com/magazine/hh394144.aspx
-// https://msdn.microsoft.com/magazine/hh456398.aspx
-// https://msdn.microsoft.com/magazine/hh547107.aspx
-// https://msdn.microsoft.com/magazine/hh580731.aspx
-class BASE_EXPORT PlatformNativeWorkerPoolWin
-    : public PlatformNativeWorkerPool {
- public:
-  PlatformNativeWorkerPoolWin(TrackedRef<TaskTracker> task_tracker,
-                              TrackedRef<Delegate> delegate,
-                              SchedulerWorkerPool* predecessor_pool = nullptr);
-
-  ~PlatformNativeWorkerPoolWin() override;
-
- private:
-  class ScopedCallbackMayRunLongObserver;
-
-  // Callback that gets run by |pool_|.
-  static void CALLBACK
-  RunNextTaskSource(PTP_CALLBACK_INSTANCE callback_instance,
-                    void* scheduler_worker_pool_windows_impl,
-                    PTP_WORK);
-
-  // PlatformNativeWorkerPool:
-  void JoinImpl() override;
-  void StartImpl() override;
-  void SubmitWork() override;
-
-  // Thread pool object that |work_| gets executed on.
-  PTP_POOL pool_ = nullptr;
-
-  // Callback environment. |pool_| is associated with |environment_| so that
-  // work objects using this environment run on |pool_|.
-  TP_CALLBACK_ENVIRON environment_ = {};
-
-  // Work object that executes RunNextTaskSource. It has a pointer to the
-  // current |PlatformNativeWorkerPoolWin| and a pointer to |environment_| bound
-  // to it.
-  PTP_WORK work_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(PlatformNativeWorkerPoolWin);
-};
-
-using PlatformNativeWorkerPoolImpl = PlatformNativeWorkerPoolWin;
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_WIN_H_
diff --git a/base/task/thread_pool/pooled_parallel_task_runner.cc b/base/task/thread_pool/pooled_parallel_task_runner.cc
new file mode 100644
index 0000000..8eed8660
--- /dev/null
+++ b/base/task/thread_pool/pooled_parallel_task_runner.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 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/task/thread_pool/pooled_parallel_task_runner.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
+
+#include "base/task/thread_pool/sequence.h"
+
+namespace base {
+namespace internal {
+
+PooledParallelTaskRunner::PooledParallelTaskRunner(
+    const TaskTraits& traits,
+    PooledTaskRunnerDelegate* pooled_task_runner_delegate)
+    : traits_(traits),
+      pooled_task_runner_delegate_(pooled_task_runner_delegate) {}
+
+PooledParallelTaskRunner::~PooledParallelTaskRunner() = default;
+
+bool PooledParallelTaskRunner::PostDelayedTask(const Location& from_here,
+                                               OnceClosure closure,
+                                               TimeDelta delay) {
+  if (!PooledTaskRunnerDelegate::Exists())
+    return false;
+
+  // Post the task as part of a one-off single-task Sequence.
+  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
+      traits_, this, TaskSourceExecutionMode::kParallel);
+
+  {
+    CheckedAutoLock auto_lock(lock_);
+    sequences_.insert(sequence.get());
+  }
+
+  return pooled_task_runner_delegate_->PostTaskWithSequence(
+      Task(from_here, std::move(closure), delay), std::move(sequence));
+}
+
+bool PooledParallelTaskRunner::RunsTasksInCurrentSequence() const {
+  return pooled_task_runner_delegate_->IsRunningPoolWithTraits(traits_);
+}
+
+void PooledParallelTaskRunner::UnregisterSequence(Sequence* sequence) {
+  DCHECK(sequence);
+
+  CheckedAutoLock auto_lock(lock_);
+  sequences_.erase(sequence);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/thread_pool/scheduler_parallel_task_runner.h b/base/task/thread_pool/pooled_parallel_task_runner.h
similarity index 62%
rename from base/task/thread_pool/scheduler_parallel_task_runner.h
rename to base/task/thread_pool/pooled_parallel_task_runner.h
index ede136e..672499a 100644
--- a/base/task/thread_pool/scheduler_parallel_task_runner.h
+++ b/base/task/thread_pool/pooled_parallel_task_runner.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 BASE_TASK_THREAD_POOL_SCHEDULER_PARALLEL_TASK_RUNNER_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_PARALLEL_TASK_RUNNER_H_
+#ifndef BASE_TASK_THREAD_POOL_POOLED_PARALLEL_TASK_RUNNER_H_
+#define BASE_TASK_THREAD_POOL_POOLED_PARALLEL_TASK_RUNNER_H_
 
 #include "base/base_export.h"
 #include "base/callback_forward.h"
@@ -19,15 +19,15 @@
 namespace internal {
 
 class Sequence;
-class SchedulerTaskRunnerDelegate;
+class PooledTaskRunnerDelegate;
 
 // A task runner that runs tasks in parallel.
-class BASE_EXPORT SchedulerParallelTaskRunner : public TaskRunner {
+class BASE_EXPORT PooledParallelTaskRunner : public TaskRunner {
  public:
-  // Constructs a SchedulerParallelTaskRunner which can be used to post tasks.
-  SchedulerParallelTaskRunner(
+  // Constructs a PooledParallelTaskRunner which can be used to post tasks.
+  PooledParallelTaskRunner(
       const TaskTraits& traits,
-      SchedulerTaskRunnerDelegate* scheduler_task_runner_delegate);
+      PooledTaskRunnerDelegate* pooled_task_runner_delegate);
 
   // TaskRunner:
   bool PostDelayedTask(const Location& from_here,
@@ -40,22 +40,22 @@
   void UnregisterSequence(Sequence* sequence);
 
  private:
-  ~SchedulerParallelTaskRunner() override;
+  ~PooledParallelTaskRunner() override;
 
   const TaskTraits traits_;
-  SchedulerTaskRunnerDelegate* const scheduler_task_runner_delegate_;
+  PooledTaskRunnerDelegate* const pooled_task_runner_delegate_;
 
   CheckedLock lock_;
 
-  // List of alive Sequences instantiated by this SchedulerParallelTaskRunner.
+  // List of alive Sequences instantiated by this PooledParallelTaskRunner.
   // Sequences are added when they are instantiated, and removed when they are
   // destroyed.
   base::flat_set<Sequence*> sequences_ GUARDED_BY(lock_);
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerParallelTaskRunner);
+  DISALLOW_COPY_AND_ASSIGN(PooledParallelTaskRunner);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_PARALLEL_TASK_RUNNER_H_
+#endif  // BASE_TASK_THREAD_POOL_POOLED_PARALLEL_TASK_RUNNER_H_
diff --git a/base/task/thread_pool/pooled_sequenced_task_runner.cc b/base/task/thread_pool/pooled_sequenced_task_runner.cc
new file mode 100644
index 0000000..6f363fa
--- /dev/null
+++ b/base/task/thread_pool/pooled_sequenced_task_runner.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 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/task/thread_pool/pooled_sequenced_task_runner.h"
+
+#include "base/sequence_token.h"
+
+namespace base {
+namespace internal {
+
+PooledSequencedTaskRunner::PooledSequencedTaskRunner(
+    const TaskTraits& traits,
+    PooledTaskRunnerDelegate* pooled_task_runner_delegate)
+    : pooled_task_runner_delegate_(pooled_task_runner_delegate),
+      sequence_(MakeRefCounted<Sequence>(traits,
+                                         this,
+                                         TaskSourceExecutionMode::kSequenced)) {
+}
+
+PooledSequencedTaskRunner::~PooledSequencedTaskRunner() = default;
+
+bool PooledSequencedTaskRunner::PostDelayedTask(const Location& from_here,
+                                                OnceClosure closure,
+                                                TimeDelta delay) {
+  if (!PooledTaskRunnerDelegate::Exists())
+    return false;
+
+  Task task(from_here, std::move(closure), delay);
+
+  // Post the task as part of |sequence_|.
+  return pooled_task_runner_delegate_->PostTaskWithSequence(std::move(task),
+                                                            sequence_);
+}
+
+bool PooledSequencedTaskRunner::PostNonNestableDelayedTask(
+    const Location& from_here,
+    OnceClosure closure,
+    TimeDelta delay) {
+  // Tasks are never nested within the thread pool.
+  return PostDelayedTask(from_here, std::move(closure), delay);
+}
+
+bool PooledSequencedTaskRunner::RunsTasksInCurrentSequence() const {
+  return sequence_->token() == SequenceToken::GetForCurrentThread();
+}
+
+void PooledSequencedTaskRunner::UpdatePriority(TaskPriority priority) {
+  pooled_task_runner_delegate_->UpdatePriority(sequence_, priority);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/thread_pool/scheduler_sequenced_task_runner.h b/base/task/thread_pool/pooled_sequenced_task_runner.h
similarity index 65%
rename from base/task/thread_pool/scheduler_sequenced_task_runner.h
rename to base/task/thread_pool/pooled_sequenced_task_runner.h
index 749b7f2..37a1716 100644
--- a/base/task/thread_pool/scheduler_sequenced_task_runner.h
+++ b/base/task/thread_pool/pooled_sequenced_task_runner.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_TASK_THREAD_POOL_SCHEDULER_SEQUENCED_TASK_RUNNER_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_SEQUENCED_TASK_RUNNER_H_
+#ifndef BASE_TASK_THREAD_POOL_POOLED_SEQUENCED_TASK_RUNNER_H_
+#define BASE_TASK_THREAD_POOL_POOLED_SEQUENCED_TASK_RUNNER_H_
 
 #include "base/base_export.h"
 #include "base/callback_forward.h"
 #include "base/location.h"
 #include "base/task/task_traits.h"
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
 #include "base/task/thread_pool/sequence.h"
 #include "base/time/time.h"
 #include "base/updateable_sequenced_task_runner.h"
@@ -18,13 +18,13 @@
 namespace internal {
 
 // A task runner that runs tasks in sequence.
-class BASE_EXPORT SchedulerSequencedTaskRunner
+class BASE_EXPORT PooledSequencedTaskRunner
     : public UpdateableSequencedTaskRunner {
  public:
-  // Constructs a SchedulerSequencedTaskRunner which can be used to post tasks.
-  SchedulerSequencedTaskRunner(
+  // Constructs a PooledSequencedTaskRunner which can be used to post tasks.
+  PooledSequencedTaskRunner(
       const TaskTraits& traits,
-      SchedulerTaskRunnerDelegate* scheduler_task_runner_delegate);
+      PooledTaskRunnerDelegate* pooled_task_runner_delegate);
 
   // UpdateableSequencedTaskRunner:
   bool PostDelayedTask(const Location& from_here,
@@ -40,17 +40,17 @@
   void UpdatePriority(TaskPriority priority) override;
 
  private:
-  ~SchedulerSequencedTaskRunner() override;
+  ~PooledSequencedTaskRunner() override;
 
-  SchedulerTaskRunnerDelegate* const scheduler_task_runner_delegate_;
+  PooledTaskRunnerDelegate* const pooled_task_runner_delegate_;
 
   // Sequence for all Tasks posted through this TaskRunner.
   const scoped_refptr<Sequence> sequence_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerSequencedTaskRunner);
+  DISALLOW_COPY_AND_ASSIGN(PooledSequencedTaskRunner);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_SEQUENCED_TASK_RUNNER_H_
+#endif  // BASE_TASK_THREAD_POOL_POOLED_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/task/thread_pool/scheduler_single_thread_task_runner_manager.cc b/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
similarity index 65%
rename from base/task/thread_pool/scheduler_single_thread_task_runner_manager.cc
rename to base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
index 1d355d4..6d2eec83 100644
--- a/base/task/thread_pool/scheduler_single_thread_task_runner_manager.cc
+++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager.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 "base/task/thread_pool/scheduler_single_thread_task_runner_manager.h"
+#include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h"
 
 #include <algorithm>
 #include <memory>
@@ -19,11 +19,11 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
 #include "base/task/thread_pool/priority_queue.h"
-#include "base/task/thread_pool/scheduler_worker.h"
 #include "base/task/thread_pool/sequence.h"
 #include "base/task/thread_pool/task.h"
 #include "base/task/thread_pool/task_source.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/worker_thread.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 
@@ -38,15 +38,15 @@
 
 namespace {
 
-// Boolean indicating whether there's a SchedulerSingleThreadTaskRunnerManager
+// Boolean indicating whether there's a PooledSingleThreadTaskRunnerManager
 // instance alive in this process. This variable should only be set when the
-// SchedulerSingleThreadTaskRunnerManager instance is brought up (on the main
+// PooledSingleThreadTaskRunnerManager instance is brought up (on the main
 // thread; before any tasks are posted) and decremented when the instance is
 // brought down (i.e., only when unit tests tear down the task environment and
 // never in production). This makes the variable const while worker threads are
 // up and as such it doesn't need to be atomic. It is used to tell when a task
 // is posted from the main thread after the task environment was brought down in
-// unit tests so that SchedulerSingleThreadTaskRunnerManager bound TaskRunners
+// unit tests so that PooledSingleThreadTaskRunnerManager bound TaskRunners
 // can return false on PostTask, letting such callers know they should complete
 // necessary work synchronously. Note: |!g_manager_is_alive| is generally
 // equivalent to |!ThreadPool::GetInstance()| but has the advantage of being
@@ -77,30 +77,30 @@
   DISALLOW_COPY_AND_ASSIGN(AtomicThreadRefChecker);
 };
 
-class SchedulerWorkerDelegate : public SchedulerWorker::Delegate {
+class WorkerThreadDelegate : public WorkerThread::Delegate {
  public:
-  SchedulerWorkerDelegate(const std::string& thread_name,
-                          SchedulerWorker::ThreadLabel thread_label,
-                          TrackedRef<TaskTracker> task_tracker)
+  WorkerThreadDelegate(const std::string& thread_name,
+                       WorkerThread::ThreadLabel thread_label,
+                       TrackedRef<TaskTracker> task_tracker)
       : thread_name_(thread_name),
         thread_label_(thread_label),
         task_tracker_(std::move(task_tracker)) {}
 
-  void set_worker(SchedulerWorker* worker) {
+  void set_worker(WorkerThread* worker) {
     DCHECK(!worker_);
     worker_ = worker;
   }
 
-  SchedulerWorker::ThreadLabel GetThreadLabel() const final {
+  WorkerThread::ThreadLabel GetThreadLabel() const final {
     return thread_label_;
   }
 
-  void OnMainEntry(const SchedulerWorker* /* worker */) override {
+  void OnMainEntry(const WorkerThread* /* worker */) override {
     thread_ref_checker_.Set();
     PlatformThread::SetName(thread_name_);
   }
 
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     CheckedAutoLock auto_lock(lock_);
     DCHECK(worker_awake_);
     auto task_source = GetWorkLockRequired(worker);
@@ -138,7 +138,7 @@
     return thread_ref_checker_.IsCurrentThreadSameAsSetThread();
   }
 
-  void OnMainExit(SchedulerWorker* /* worker */) override {}
+  void OnMainExit(WorkerThread* /* worker */) override {}
 
   void DidUpdateCanRunPolicy() {
     bool should_wakeup = false;
@@ -159,7 +159,7 @@
   }
 
  protected:
-  scoped_refptr<TaskSource> GetWorkLockRequired(SchedulerWorker* worker)
+  scoped_refptr<TaskSource> GetWorkLockRequired(WorkerThread* worker)
       EXCLUSIVE_LOCKS_REQUIRED(lock_) {
     if (!CanRunNextTaskSource()) {
       return nullptr;
@@ -194,12 +194,12 @@
   }
 
   const std::string thread_name_;
-  const SchedulerWorker::ThreadLabel thread_label_;
+  const WorkerThread::ThreadLabel thread_label_;
 
-  // The SchedulerWorker that has |this| as a delegate. Must be set before
-  // starting or posting a task to the SchedulerWorker, because it's used in
+  // The WorkerThread that has |this| as a delegate. Must be set before
+  // starting or posting a task to the WorkerThread, because it's used in
   // OnMainEntry() and PostTaskNow().
-  SchedulerWorker* worker_ = nullptr;
+  WorkerThread* worker_ = nullptr;
 
   const TrackedRef<TaskTracker> task_tracker_;
 
@@ -207,43 +207,43 @@
 
   AtomicThreadRefChecker thread_ref_checker_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegate);
+  DISALLOW_COPY_AND_ASSIGN(WorkerThreadDelegate);
 };
 
 #if defined(OS_WIN)
 
-class SchedulerWorkerCOMDelegate : public SchedulerWorkerDelegate {
+class WorkerThreadCOMDelegate : public WorkerThreadDelegate {
  public:
-  SchedulerWorkerCOMDelegate(const std::string& thread_name,
-                             SchedulerWorker::ThreadLabel thread_label,
-                             TrackedRef<TaskTracker> task_tracker)
-      : SchedulerWorkerDelegate(thread_name,
-                                thread_label,
-                                std::move(task_tracker)) {}
+  WorkerThreadCOMDelegate(const std::string& thread_name,
+                          WorkerThread::ThreadLabel thread_label,
+                          TrackedRef<TaskTracker> task_tracker)
+      : WorkerThreadDelegate(thread_name,
+                             thread_label,
+                             std::move(task_tracker)) {}
 
-  ~SchedulerWorkerCOMDelegate() override { DCHECK(!scoped_com_initializer_); }
+  ~WorkerThreadCOMDelegate() override { DCHECK(!scoped_com_initializer_); }
 
-  // SchedulerWorker::Delegate:
-  void OnMainEntry(const SchedulerWorker* worker) override {
-    SchedulerWorkerDelegate::OnMainEntry(worker);
+  // WorkerThread::Delegate:
+  void OnMainEntry(const WorkerThread* worker) override {
+    WorkerThreadDelegate::OnMainEntry(worker);
 
     scoped_com_initializer_ = std::make_unique<win::ScopedCOMInitializer>();
   }
 
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     // This scheme below allows us to cover the following scenarios:
-    // * Only SchedulerWorkerDelegate::GetWork() has work:
+    // * Only WorkerThreadDelegate::GetWork() has work:
     //   Always return the task source from GetWork().
     // * Only the Windows Message Queue has work:
     //   Always return the task source from GetWorkFromWindowsMessageQueue();
-    // * Both SchedulerWorkerDelegate::GetWork() and the Windows Message Queue
+    // * Both WorkerThreadDelegate::GetWork() and the Windows Message Queue
     //   have work:
     //   Process task sources from each source round-robin style.
     CheckedAutoLock auto_lock(lock_);
     DCHECK(worker_awake_);
     scoped_refptr<TaskSource> task_source;
     if (get_work_first_) {
-      task_source = SchedulerWorkerDelegate::GetWorkLockRequired(worker);
+      task_source = WorkerThreadDelegate::GetWorkLockRequired(worker);
       if (task_source)
         get_work_first_ = false;
     }
@@ -259,8 +259,8 @@
       // This case is important if we checked the Windows Message Queue first
       // and found there was no work. We don't want to return null immediately
       // as that could cause the thread to go to sleep while work is waiting via
-      // SchedulerWorkerDelegate::GetWork().
-      task_source = SchedulerWorkerDelegate::GetWorkLockRequired(worker);
+      // WorkerThreadDelegate::GetWork().
+      task_source = WorkerThreadDelegate::GetWorkLockRequired(worker);
     }
     if (task_source == nullptr) {
       // The worker will sleep after this returns nullptr.
@@ -269,7 +269,7 @@
     return task_source;
   }
 
-  void OnMainExit(SchedulerWorker* /* worker */) override {
+  void OnMainExit(WorkerThread* /* worker */) override {
     scoped_com_initializer_.reset();
   }
 
@@ -318,23 +318,22 @@
                                TaskSourceExecutionMode::kParallel);
   std::unique_ptr<win::ScopedCOMInitializer> scoped_com_initializer_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerCOMDelegate);
+  DISALLOW_COPY_AND_ASSIGN(WorkerThreadCOMDelegate);
 };
 
 #endif  // defined(OS_WIN)
 
 }  // namespace
 
-class SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner
+class PooledSingleThreadTaskRunnerManager::PooledSingleThreadTaskRunner
     : public SingleThreadTaskRunner {
  public:
-  // Constructs a SchedulerSingleThreadTaskRunner that indirectly controls the
+  // Constructs a PooledSingleThreadTaskRunner that indirectly controls the
   // lifetime of a dedicated |worker| for |traits|.
-  SchedulerSingleThreadTaskRunner(
-      SchedulerSingleThreadTaskRunnerManager* const outer,
-      const TaskTraits& traits,
-      SchedulerWorker* worker,
-      SingleThreadTaskRunnerThreadMode thread_mode)
+  PooledSingleThreadTaskRunner(PooledSingleThreadTaskRunnerManager* const outer,
+                               const TaskTraits& traits,
+                               WorkerThread* worker,
+                               SingleThreadTaskRunnerThreadMode thread_mode)
       : outer_(outer),
         worker_(worker),
         thread_mode_(thread_mode),
@@ -367,7 +366,7 @@
       // worker are kept alive as long as there are pending Tasks.
       outer_->delayed_task_manager_->AddDelayedTask(
           std::move(task),
-          BindOnce(&SchedulerWorkerDelegate::PostTaskNow,
+          BindOnce(&WorkerThreadDelegate::PostTaskNow,
                    Unretained(GetDelegate()), sequence_),
           this);
     }
@@ -388,44 +387,44 @@
   }
 
  private:
-  ~SchedulerSingleThreadTaskRunner() override {
+  ~PooledSingleThreadTaskRunner() override {
     // Only unregister if this is a DEDICATED SingleThreadTaskRunner. SHARED
-    // task runner SchedulerWorkers are managed separately as they are reused.
+    // task runner WorkerThreads are managed separately as they are reused.
     // |g_manager_is_alive| avoids a use-after-free should this
-    // SchedulerSingleThreadTaskRunner outlive its manager. It is safe to access
+    // PooledSingleThreadTaskRunner outlive its manager. It is safe to access
     // |g_manager_is_alive| without synchronization primitives as it is const
-    // for the lifetime of the manager and ~SchedulerSingleThreadTaskRunner()
+    // for the lifetime of the manager and ~PooledSingleThreadTaskRunner()
     // either happens prior to the end of JoinForTesting() (which happens-before
     // manager's destruction) or on main thread after the task environment's
     // entire destruction (which happens-after the manager's destruction). Yes,
     // there's a theoretical use case where the last ref to this
-    // SchedulerSingleThreadTaskRunner is handed to a thread not controlled by
+    // PooledSingleThreadTaskRunner is handed to a thread not controlled by
     // thread_pool and that this ends up causing
-    // ~SchedulerSingleThreadTaskRunner() to race with
-    // ~SchedulerSingleThreadTaskRunnerManager() but this is intentionally not
+    // ~PooledSingleThreadTaskRunner() to race with
+    // ~PooledSingleThreadTaskRunnerManager() but this is intentionally not
     // supported (and it doesn't matter in production where we leak the task
     // environment for such reasons). TSan should catch this weird paradigm
     // should anyone elect to use it in a unit test and the error would point
     // here.
     if (g_manager_is_alive &&
         thread_mode_ == SingleThreadTaskRunnerThreadMode::DEDICATED) {
-      outer_->UnregisterSchedulerWorker(worker_);
+      outer_->UnregisterWorkerThread(worker_);
     }
   }
 
-  SchedulerWorkerDelegate* GetDelegate() const {
-    return static_cast<SchedulerWorkerDelegate*>(worker_->delegate());
+  WorkerThreadDelegate* GetDelegate() const {
+    return static_cast<WorkerThreadDelegate*>(worker_->delegate());
   }
 
-  SchedulerSingleThreadTaskRunnerManager* const outer_;
-  SchedulerWorker* const worker_;
+  PooledSingleThreadTaskRunnerManager* const outer_;
+  WorkerThread* const worker_;
   const SingleThreadTaskRunnerThreadMode thread_mode_;
   const scoped_refptr<Sequence> sequence_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunner);
 };
 
-SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager(
+PooledSingleThreadTaskRunnerManager::PooledSingleThreadTaskRunnerManager(
     TrackedRef<TaskTracker> task_tracker,
     DelayedTaskManager* delayed_task_manager)
     : task_tracker_(std::move(task_tracker)),
@@ -433,32 +432,31 @@
   DCHECK(task_tracker_);
   DCHECK(delayed_task_manager_);
 #if defined(OS_WIN)
-  static_assert(std::extent<decltype(shared_com_scheduler_workers_)>() ==
-                    std::extent<decltype(shared_scheduler_workers_)>(),
-                "The size of |shared_com_scheduler_workers_| must match "
-                "|shared_scheduler_workers_|");
+  static_assert(std::extent<decltype(shared_com_worker_threads_)>() ==
+                    std::extent<decltype(shared_worker_threads_)>(),
+                "The size of |shared_com_worker_threads_| must match "
+                "|shared_worker_threads_|");
   static_assert(
-      std::extent<std::remove_reference<decltype(
-              shared_com_scheduler_workers_[0])>>() ==
+      std::extent<
+          std::remove_reference<decltype(shared_com_worker_threads_[0])>>() ==
           std::extent<
-              std::remove_reference<decltype(shared_scheduler_workers_[0])>>(),
-      "The size of |shared_com_scheduler_workers_| must match "
-      "|shared_scheduler_workers_|");
+              std::remove_reference<decltype(shared_worker_threads_[0])>>(),
+      "The size of |shared_com_worker_threads_| must match "
+      "|shared_worker_threads_|");
 #endif  // defined(OS_WIN)
   DCHECK(!g_manager_is_alive);
   g_manager_is_alive = true;
 }
 
-SchedulerSingleThreadTaskRunnerManager::
-    ~SchedulerSingleThreadTaskRunnerManager() {
+PooledSingleThreadTaskRunnerManager::~PooledSingleThreadTaskRunnerManager() {
   DCHECK(g_manager_is_alive);
   g_manager_is_alive = false;
 }
 
-void SchedulerSingleThreadTaskRunnerManager::Start(
-    SchedulerWorkerObserver* scheduler_worker_observer) {
-  DCHECK(!scheduler_worker_observer_);
-  scheduler_worker_observer_ = scheduler_worker_observer;
+void PooledSingleThreadTaskRunnerManager::Start(
+    WorkerThreadObserver* worker_thread_observer) {
+  DCHECK(!worker_thread_observer_);
+  worker_thread_observer_ = worker_thread_observer;
 
   decltype(workers_) workers_to_start;
   {
@@ -469,15 +467,15 @@
 
   // Start workers that were created before this method was called.
   // Workers that already need to wake up are already signaled as part of
-  // SchedulerSingleThreadTaskRunner::PostTaskNow(). As a result, it's
+  // PooledSingleThreadTaskRunner::PostTaskNow(). As a result, it's
   // unnecessary to call WakeUp() for each worker (in fact, an extraneous
   // WakeUp() would be racy and wrong - see https://crbug.com/862582).
-  for (scoped_refptr<SchedulerWorker> worker : workers_to_start) {
-    worker->Start(scheduler_worker_observer_);
+  for (scoped_refptr<WorkerThread> worker : workers_to_start) {
+    worker->Start(worker_thread_observer_);
   }
 }
 
-void SchedulerSingleThreadTaskRunnerManager::DidUpdateCanRunPolicy() {
+void PooledSingleThreadTaskRunnerManager::DidUpdateCanRunPolicy() {
   decltype(workers_) workers_to_update;
 
   {
@@ -490,32 +488,32 @@
   // CanRunPolicy if tasks are posted to it and thus doesn't need a
   // DidUpdateCanRunPolicy() notification.
   for (auto& worker : workers_to_update) {
-    static_cast<SchedulerWorkerDelegate*>(worker->delegate())
+    static_cast<WorkerThreadDelegate*>(worker->delegate())
         ->DidUpdateCanRunPolicy();
   }
 }
 
 scoped_refptr<SingleThreadTaskRunner>
-SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits(
+PooledSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits(
     const TaskTraits& traits,
     SingleThreadTaskRunnerThreadMode thread_mode) {
-  return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerDelegate>(traits,
-                                                                 thread_mode);
+  return CreateTaskRunnerWithTraitsImpl<WorkerThreadDelegate>(traits,
+                                                              thread_mode);
 }
 
 #if defined(OS_WIN)
 scoped_refptr<SingleThreadTaskRunner>
-SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits(
+PooledSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits(
     const TaskTraits& traits,
     SingleThreadTaskRunnerThreadMode thread_mode) {
-  return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerCOMDelegate>(
-      traits, thread_mode);
+  return CreateTaskRunnerWithTraitsImpl<WorkerThreadCOMDelegate>(traits,
+                                                                 thread_mode);
 }
 #endif  // defined(OS_WIN)
 
 // static
-SchedulerSingleThreadTaskRunnerManager::ContinueOnShutdown
-SchedulerSingleThreadTaskRunnerManager::TraitsToContinueOnShutdown(
+PooledSingleThreadTaskRunnerManager::ContinueOnShutdown
+PooledSingleThreadTaskRunnerManager::TraitsToContinueOnShutdown(
     const TaskTraits& traits) {
   if (traits.shutdown_behavior() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
     return IS_CONTINUE_ON_SHUTDOWN;
@@ -523,9 +521,8 @@
 }
 
 template <typename DelegateType>
-scoped_refptr<
-    SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>
-SchedulerSingleThreadTaskRunnerManager::CreateTaskRunnerWithTraitsImpl(
+scoped_refptr<PooledSingleThreadTaskRunnerManager::PooledSingleThreadTaskRunner>
+PooledSingleThreadTaskRunnerManager::CreateTaskRunnerWithTraitsImpl(
     const TaskTraits& traits,
     SingleThreadTaskRunnerThreadMode thread_mode) {
   DCHECK(thread_mode != SingleThreadTaskRunnerThreadMode::SHARED ||
@@ -539,11 +536,11 @@
   // SingleThreadTaskRunnerThreadMode. In DEDICATED, the scoped_refptr is backed
   // by a local variable and in SHARED, the scoped_refptr is backed by a member
   // variable.
-  SchedulerWorker* dedicated_worker = nullptr;
-  SchedulerWorker*& worker =
+  WorkerThread* dedicated_worker = nullptr;
+  WorkerThread*& worker =
       thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED
           ? dedicated_worker
-          : GetSharedSchedulerWorkerForTraits<DelegateType>(traits);
+          : GetSharedWorkerThreadForTraits<DelegateType>(traits);
   bool new_worker = false;
   bool started;
   {
@@ -555,9 +552,9 @@
       if (thread_mode == SingleThreadTaskRunnerThreadMode::SHARED)
         worker_name += "Shared";
       worker_name += environment_params.name_suffix;
-      worker = CreateAndRegisterSchedulerWorker<DelegateType>(
+      worker = CreateAndRegisterWorkerThread<DelegateType>(
           worker_name, thread_mode,
-          CanUseBackgroundPriorityForSchedulerWorker()
+          CanUseBackgroundPriorityForWorkerThread()
               ? environment_params.priority_hint
               : ThreadPriority::NORMAL);
       new_worker = true;
@@ -566,13 +563,13 @@
   }
 
   if (new_worker && started)
-    worker->Start(scheduler_worker_observer_);
+    worker->Start(worker_thread_observer_);
 
-  return MakeRefCounted<SchedulerSingleThreadTaskRunner>(this, traits, worker,
-                                                         thread_mode);
+  return MakeRefCounted<PooledSingleThreadTaskRunner>(this, traits, worker,
+                                                      thread_mode);
 }
 
-void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() {
+void PooledSingleThreadTaskRunnerManager::JoinForTesting() {
   decltype(workers_) local_workers;
   {
     CheckedAutoLock auto_lock(lock_);
@@ -580,7 +577,7 @@
   }
 
   for (const auto& worker : local_workers) {
-    static_cast<SchedulerWorkerDelegate*>(worker->delegate())
+    static_cast<WorkerThreadDelegate*>(worker->delegate())
         ->EnableFlushPriorityQueueTaskSourcesOnDestroyForTesting();
     worker->JoinForTesting();
   }
@@ -592,53 +589,53 @@
     workers_ = std::move(local_workers);
   }
 
-  // Release shared SchedulerWorkers at the end so they get joined above. If
-  // this call happens before the joins, the SchedulerWorkers are effectively
-  // detached and may outlive the SchedulerSingleThreadTaskRunnerManager.
-  ReleaseSharedSchedulerWorkers();
+  // Release shared WorkerThreads at the end so they get joined above. If
+  // this call happens before the joins, the WorkerThreads are effectively
+  // detached and may outlive the PooledSingleThreadTaskRunnerManager.
+  ReleaseSharedWorkerThreads();
 }
 
 template <>
-std::unique_ptr<SchedulerWorkerDelegate>
-SchedulerSingleThreadTaskRunnerManager::CreateSchedulerWorkerDelegate<
-    SchedulerWorkerDelegate>(const std::string& name,
-                             int id,
-                             SingleThreadTaskRunnerThreadMode thread_mode) {
-  return std::make_unique<SchedulerWorkerDelegate>(
+std::unique_ptr<WorkerThreadDelegate>
+PooledSingleThreadTaskRunnerManager::CreateWorkerThreadDelegate<
+    WorkerThreadDelegate>(const std::string& name,
+                          int id,
+                          SingleThreadTaskRunnerThreadMode thread_mode) {
+  return std::make_unique<WorkerThreadDelegate>(
       StringPrintf("ThreadPoolSingleThread%s%d", name.c_str(), id),
       thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED
-          ? SchedulerWorker::ThreadLabel::DEDICATED
-          : SchedulerWorker::ThreadLabel::SHARED,
+          ? WorkerThread::ThreadLabel::DEDICATED
+          : WorkerThread::ThreadLabel::SHARED,
       task_tracker_);
 }
 
 #if defined(OS_WIN)
 template <>
-std::unique_ptr<SchedulerWorkerDelegate>
-SchedulerSingleThreadTaskRunnerManager::CreateSchedulerWorkerDelegate<
-    SchedulerWorkerCOMDelegate>(const std::string& name,
-                                int id,
-                                SingleThreadTaskRunnerThreadMode thread_mode) {
-  return std::make_unique<SchedulerWorkerCOMDelegate>(
+std::unique_ptr<WorkerThreadDelegate>
+PooledSingleThreadTaskRunnerManager::CreateWorkerThreadDelegate<
+    WorkerThreadCOMDelegate>(const std::string& name,
+                             int id,
+                             SingleThreadTaskRunnerThreadMode thread_mode) {
+  return std::make_unique<WorkerThreadCOMDelegate>(
       StringPrintf("ThreadPoolSingleThreadCOMSTA%s%d", name.c_str(), id),
       thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED
-          ? SchedulerWorker::ThreadLabel::DEDICATED_COM
-          : SchedulerWorker::ThreadLabel::SHARED_COM,
+          ? WorkerThread::ThreadLabel::DEDICATED_COM
+          : WorkerThread::ThreadLabel::SHARED_COM,
       task_tracker_);
 }
 #endif  // defined(OS_WIN)
 
 template <typename DelegateType>
-SchedulerWorker*
-SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker(
+WorkerThread*
+PooledSingleThreadTaskRunnerManager::CreateAndRegisterWorkerThread(
     const std::string& name,
     SingleThreadTaskRunnerThreadMode thread_mode,
     ThreadPriority priority_hint) {
   int id = next_worker_id_++;
-  std::unique_ptr<SchedulerWorkerDelegate> delegate =
-      CreateSchedulerWorkerDelegate<DelegateType>(name, id, thread_mode);
-  SchedulerWorkerDelegate* delegate_raw = delegate.get();
-  scoped_refptr<SchedulerWorker> worker = MakeRefCounted<SchedulerWorker>(
+  std::unique_ptr<WorkerThreadDelegate> delegate =
+      CreateWorkerThreadDelegate<DelegateType>(name, id, thread_mode);
+  WorkerThreadDelegate* delegate_raw = delegate.get();
+  scoped_refptr<WorkerThread> worker = MakeRefCounted<WorkerThread>(
       priority_hint, std::move(delegate), task_tracker_);
   delegate_raw->set_worker(worker.get());
   workers_.emplace_back(std::move(worker));
@@ -646,27 +643,27 @@
 }
 
 template <>
-SchedulerWorker*&
-SchedulerSingleThreadTaskRunnerManager::GetSharedSchedulerWorkerForTraits<
-    SchedulerWorkerDelegate>(const TaskTraits& traits) {
-  return shared_scheduler_workers_[GetEnvironmentIndexForTraits(traits)]
-                                  [TraitsToContinueOnShutdown(traits)];
+WorkerThread*&
+PooledSingleThreadTaskRunnerManager::GetSharedWorkerThreadForTraits<
+    WorkerThreadDelegate>(const TaskTraits& traits) {
+  return shared_worker_threads_[GetEnvironmentIndexForTraits(traits)]
+                               [TraitsToContinueOnShutdown(traits)];
 }
 
 #if defined(OS_WIN)
 template <>
-SchedulerWorker*&
-SchedulerSingleThreadTaskRunnerManager::GetSharedSchedulerWorkerForTraits<
-    SchedulerWorkerCOMDelegate>(const TaskTraits& traits) {
-  return shared_com_scheduler_workers_[GetEnvironmentIndexForTraits(traits)]
-                                      [TraitsToContinueOnShutdown(traits)];
+WorkerThread*&
+PooledSingleThreadTaskRunnerManager::GetSharedWorkerThreadForTraits<
+    WorkerThreadCOMDelegate>(const TaskTraits& traits) {
+  return shared_com_worker_threads_[GetEnvironmentIndexForTraits(traits)]
+                                   [TraitsToContinueOnShutdown(traits)];
 }
 #endif  // defined(OS_WIN)
 
-void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker(
-    SchedulerWorker* worker) {
+void PooledSingleThreadTaskRunnerManager::UnregisterWorkerThread(
+    WorkerThread* worker) {
   // Cleanup uses a CheckedLock, so call Cleanup() after releasing |lock_|.
-  scoped_refptr<SchedulerWorker> worker_to_destroy;
+  scoped_refptr<WorkerThread> worker_to_destroy;
   {
     CheckedAutoLock auto_lock(lock_);
 
@@ -682,33 +679,33 @@
   worker_to_destroy->Cleanup();
 }
 
-void SchedulerSingleThreadTaskRunnerManager::ReleaseSharedSchedulerWorkers() {
-  decltype(shared_scheduler_workers_) local_shared_scheduler_workers;
+void PooledSingleThreadTaskRunnerManager::ReleaseSharedWorkerThreads() {
+  decltype(shared_worker_threads_) local_shared_worker_threads;
 #if defined(OS_WIN)
-  decltype(shared_com_scheduler_workers_) local_shared_com_scheduler_workers;
+  decltype(shared_com_worker_threads_) local_shared_com_worker_threads;
 #endif
   {
     CheckedAutoLock auto_lock(lock_);
-    for (size_t i = 0; i < base::size(shared_scheduler_workers_); ++i) {
-      for (size_t j = 0; j < base::size(shared_scheduler_workers_[i]); ++j) {
-        local_shared_scheduler_workers[i][j] = shared_scheduler_workers_[i][j];
-        shared_scheduler_workers_[i][j] = nullptr;
+    for (size_t i = 0; i < base::size(shared_worker_threads_); ++i) {
+      for (size_t j = 0; j < base::size(shared_worker_threads_[i]); ++j) {
+        local_shared_worker_threads[i][j] = shared_worker_threads_[i][j];
+        shared_worker_threads_[i][j] = nullptr;
 #if defined(OS_WIN)
-        local_shared_com_scheduler_workers[i][j] =
-            shared_com_scheduler_workers_[i][j];
-        shared_com_scheduler_workers_[i][j] = nullptr;
+        local_shared_com_worker_threads[i][j] =
+            shared_com_worker_threads_[i][j];
+        shared_com_worker_threads_[i][j] = nullptr;
 #endif
       }
     }
   }
 
-  for (size_t i = 0; i < base::size(local_shared_scheduler_workers); ++i) {
-    for (size_t j = 0; j < base::size(local_shared_scheduler_workers[i]); ++j) {
-      if (local_shared_scheduler_workers[i][j])
-        UnregisterSchedulerWorker(local_shared_scheduler_workers[i][j]);
+  for (size_t i = 0; i < base::size(local_shared_worker_threads); ++i) {
+    for (size_t j = 0; j < base::size(local_shared_worker_threads[i]); ++j) {
+      if (local_shared_worker_threads[i][j])
+        UnregisterWorkerThread(local_shared_worker_threads[i][j]);
 #if defined(OS_WIN)
-      if (local_shared_com_scheduler_workers[i][j])
-        UnregisterSchedulerWorker(local_shared_com_scheduler_workers[i][j]);
+      if (local_shared_com_worker_threads[i][j])
+        UnregisterWorkerThread(local_shared_com_worker_threads[i][j]);
 #endif
     }
   }
diff --git a/base/task/thread_pool/scheduler_single_thread_task_runner_manager.h b/base/task/thread_pool/pooled_single_thread_task_runner_manager.h
similarity index 72%
rename from base/task/thread_pool/scheduler_single_thread_task_runner_manager.h
rename to base/task/thread_pool/pooled_single_thread_task_runner_manager.h
index bb665f6..14f62ec0 100644
--- a/base/task/thread_pool/scheduler_single_thread_task_runner_manager.h
+++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager.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 BASE_TASK_THREAD_POOL_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
+#ifndef BASE_TASK_THREAD_POOL_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
+#define BASE_TASK_THREAD_POOL_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
 
 #include <memory>
 #include <string>
@@ -23,18 +23,18 @@
 namespace base {
 
 class TaskTraits;
-class SchedulerWorkerObserver;
+class WorkerThreadObserver;
 class SingleThreadTaskRunner;
 
 namespace internal {
 
 class DelayedTaskManager;
-class SchedulerWorker;
+class WorkerThread;
 class TaskTracker;
 
 namespace {
 
-class SchedulerWorkerDelegate;
+class WorkerThreadDelegate;
 
 }  // namespace
 
@@ -42,26 +42,25 @@
 // SingleThreadTaskRunners.
 //
 // SingleThreadTaskRunners using SingleThreadTaskRunnerThreadMode::SHARED are
-// backed by shared SchedulerWorkers for each COM+task environment combination.
+// backed by shared WorkerThreads for each COM+task environment combination.
 // These workers are lazily instantiated and then only reclaimed during
 // JoinForTesting()
 //
 // No threads are created (and hence no tasks can run) before Start() is called.
 //
 // This class is thread-safe.
-class BASE_EXPORT SchedulerSingleThreadTaskRunnerManager final {
+class BASE_EXPORT PooledSingleThreadTaskRunnerManager final {
  public:
-  SchedulerSingleThreadTaskRunnerManager(
-      TrackedRef<TaskTracker> task_tracker,
-      DelayedTaskManager* delayed_task_manager);
-  ~SchedulerSingleThreadTaskRunnerManager();
+  PooledSingleThreadTaskRunnerManager(TrackedRef<TaskTracker> task_tracker,
+                                      DelayedTaskManager* delayed_task_manager);
+  ~PooledSingleThreadTaskRunnerManager();
 
   // Starts threads for existing SingleThreadTaskRunners and allows threads to
   // be started when SingleThreadTaskRunners are created in the future. If
-  // specified, |scheduler_worker_observer| will be notified when a worker
+  // specified, |worker_thread_observer| will be notified when a worker
   // enters and exits its main function. It must not be destroyed before
   // JoinForTesting() has returned (must never be destroyed in production).
-  void Start(SchedulerWorkerObserver* scheduler_worker_observer = nullptr);
+  void Start(WorkerThreadObserver* worker_thread_observer = nullptr);
 
   // Wakes up workers as appropriate for the new CanRunPolicy policy. Must be
   // called after an update to CanRunPolicy in TaskTracker.
@@ -88,7 +87,7 @@
   void JoinForTesting();
 
  private:
-  class SchedulerSingleThreadTaskRunner;
+  class PooledSingleThreadTaskRunner;
 
   enum ContinueOnShutdown {
     IS_CONTINUE_ON_SHUTDOWN,
@@ -100,38 +99,38 @@
       const TaskTraits& traits);
 
   template <typename DelegateType>
-  scoped_refptr<SchedulerSingleThreadTaskRunner> CreateTaskRunnerWithTraitsImpl(
+  scoped_refptr<PooledSingleThreadTaskRunner> CreateTaskRunnerWithTraitsImpl(
       const TaskTraits& traits,
       SingleThreadTaskRunnerThreadMode thread_mode);
 
   template <typename DelegateType>
-  std::unique_ptr<SchedulerWorkerDelegate> CreateSchedulerWorkerDelegate(
+  std::unique_ptr<WorkerThreadDelegate> CreateWorkerThreadDelegate(
       const std::string& name,
       int id,
       SingleThreadTaskRunnerThreadMode thread_mode);
 
   template <typename DelegateType>
-  SchedulerWorker* CreateAndRegisterSchedulerWorker(
+  WorkerThread* CreateAndRegisterWorkerThread(
       const std::string& name,
       SingleThreadTaskRunnerThreadMode thread_mode,
       ThreadPriority priority_hint) EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
   template <typename DelegateType>
-  SchedulerWorker*& GetSharedSchedulerWorkerForTraits(const TaskTraits& traits);
+  WorkerThread*& GetSharedWorkerThreadForTraits(const TaskTraits& traits);
 
-  void UnregisterSchedulerWorker(SchedulerWorker* worker);
+  void UnregisterWorkerThread(WorkerThread* worker);
 
-  void ReleaseSharedSchedulerWorkers();
+  void ReleaseSharedWorkerThreads();
 
   const TrackedRef<TaskTracker> task_tracker_;
   DelayedTaskManager* const delayed_task_manager_;
 
   // Optional observer notified when a worker enters and exits its main
   // function. Set in Start() and never modified afterwards.
-  SchedulerWorkerObserver* scheduler_worker_observer_ = nullptr;
+  WorkerThreadObserver* worker_thread_observer_ = nullptr;
 
   CheckedLock lock_;
-  std::vector<scoped_refptr<SchedulerWorker>> workers_ GUARDED_BY(lock_);
+  std::vector<scoped_refptr<WorkerThread>> workers_ GUARDED_BY(lock_);
   int next_worker_id_ GUARDED_BY(lock_) = 0;
 
   // Workers for SingleThreadTaskRunnerThreadMode::SHARED tasks. It is
@@ -139,20 +138,21 @@
   // CONTINUE_ON_SHUTDOWN to avoid being in a situation where a
   // CONTINUE_ON_SHUTDOWN task effectively blocks shutdown by preventing a
   // BLOCK_SHUTDOWN task to be scheduled. https://crbug.com/829786
-  SchedulerWorker* shared_scheduler_workers_
-      [ENVIRONMENT_COUNT][CONTINUE_ON_SHUTDOWN_COUNT] GUARDED_BY(lock_) = {};
+  WorkerThread* shared_worker_threads_[ENVIRONMENT_COUNT]
+                                      [CONTINUE_ON_SHUTDOWN_COUNT] GUARDED_BY(
+                                          lock_) = {};
 #if defined(OS_WIN)
-  SchedulerWorker* shared_com_scheduler_workers_
+  WorkerThread* shared_com_worker_threads_
       [ENVIRONMENT_COUNT][CONTINUE_ON_SHUTDOWN_COUNT] GUARDED_BY(lock_) = {};
 #endif  // defined(OS_WIN)
 
   // Set to true when Start() is called.
   bool started_ GUARDED_BY(lock_) = false;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunnerManager);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManager);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
+#endif  // BASE_TASK_THREAD_POOL_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_
diff --git a/base/task/thread_pool/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc
similarity index 86%
rename from base/task/thread_pool/scheduler_single_thread_task_runner_manager_unittest.cc
rename to base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.cc
index d7fdbfbf..8de4fe9e 100644
--- a/base/task/thread_pool/scheduler_single_thread_task_runner_manager_unittest.cc
+++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager_unittest.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 "base/task/thread_pool/scheduler_single_thread_task_runner_manager.h"
+#include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -15,9 +15,9 @@
 #include "base/task/thread_pool/can_run_policy_test.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
 #include "base/task/thread_pool/environment_config.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
 #include "base/task/thread_pool/task_tracker.h"
 #include "base/task/thread_pool/test_utils.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/gtest_util.h"
 #include "base/test/test_timeouts.h"
@@ -40,16 +40,16 @@
 
 namespace {
 
-class ThreadPoolSingleThreadTaskRunnerManagerTest : public testing::Test {
+class PooledSingleThreadTaskRunnerManagerTest : public testing::Test {
  protected:
-  ThreadPoolSingleThreadTaskRunnerManagerTest()
+  PooledSingleThreadTaskRunnerManagerTest()
       : service_thread_("ThreadPoolServiceThread") {}
 
   void SetUp() override {
     service_thread_.Start();
     delayed_task_manager_.Start(service_thread_.task_runner());
     single_thread_task_runner_manager_ =
-        std::make_unique<SchedulerSingleThreadTaskRunnerManager>(
+        std::make_unique<PooledSingleThreadTaskRunnerManager>(
             task_tracker_.GetTrackedRef(), &delayed_task_manager_);
     StartSingleThreadTaskRunnerManagerFromSetUp();
   }
@@ -72,11 +72,11 @@
   Thread service_thread_;
   TaskTracker task_tracker_ = {"Test"};
   DelayedTaskManager delayed_task_manager_;
-  std::unique_ptr<SchedulerSingleThreadTaskRunnerManager>
+  std::unique_ptr<PooledSingleThreadTaskRunnerManager>
       single_thread_task_runner_manager_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolSingleThreadTaskRunnerManagerTest);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManagerTest);
 };
 
 void CaptureThreadRef(PlatformThreadRef* thread_ref) {
@@ -99,7 +99,7 @@
 
 }  // namespace
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) {
+TEST_F(PooledSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) {
   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
       single_thread_task_runner_manager_
           ->CreateSingleThreadTaskRunnerWithTraits(
@@ -125,7 +125,7 @@
   EXPECT_NE(thread_ref_1, thread_ref_2);
 }
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest, SameThreadUsed) {
+TEST_F(PooledSingleThreadTaskRunnerManagerTest, SameThreadUsed) {
   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
       single_thread_task_runner_manager_
           ->CreateSingleThreadTaskRunnerWithTraits(
@@ -151,8 +151,7 @@
   EXPECT_EQ(thread_ref_1, thread_ref_2);
 }
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest,
-       RunsTasksInCurrentSequence) {
+TEST_F(PooledSingleThreadTaskRunnerManagerTest, RunsTasksInCurrentSequence) {
   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
       single_thread_task_runner_manager_
           ->CreateSingleThreadTaskRunnerWithTraits(
@@ -190,7 +189,7 @@
   test::ShutdownTaskTracker(&task_tracker_);
 }
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest,
+TEST_F(PooledSingleThreadTaskRunnerManagerTest,
        SharedWithBaseSyncPrimitivesDCHECKs) {
   testing::GTEST_FLAG(death_test_style) = "threadsafe";
   EXPECT_DCHECK_DEATH({
@@ -200,7 +199,7 @@
 }
 
 // Regression test for https://crbug.com/829786
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest,
+TEST_F(PooledSingleThreadTaskRunnerManagerTest,
        ContinueOnShutdownDoesNotBlockBlockShutdown) {
   WaitableEvent task_has_started;
   WaitableEvent task_can_continue;
@@ -244,11 +243,11 @@
 
 namespace {
 
-class ThreadPoolSingleThreadTaskRunnerManagerCommonTest
-    : public ThreadPoolSingleThreadTaskRunnerManagerTest,
+class PooledSingleThreadTaskRunnerManagerCommonTest
+    : public PooledSingleThreadTaskRunnerManagerTest,
       public ::testing::WithParamInterface<SingleThreadTaskRunnerThreadMode> {
  public:
-  ThreadPoolSingleThreadTaskRunnerManagerCommonTest() = default;
+  PooledSingleThreadTaskRunnerManagerCommonTest() = default;
 
   scoped_refptr<SingleThreadTaskRunner> CreateTaskRunner(
       TaskTraits traits = TaskTraits()) {
@@ -257,13 +256,12 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolSingleThreadTaskRunnerManagerCommonTest);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManagerCommonTest);
 };
 
 }  // namespace
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest,
-       PrioritySetCorrectly) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PrioritySetCorrectly) {
   // Why are events used here instead of the task tracker?
   // Shutting down can cause priorities to get raised. This means we have to use
   // events to determine when a task is run.
@@ -291,14 +289,14 @@
   waitable_event_background.Wait();
   waitable_event_normal.Wait();
 
-  if (CanUseBackgroundPriorityForSchedulerWorker())
+  if (CanUseBackgroundPriorityForWorkerThread())
     EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background);
   else
     EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background);
   EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal);
 }
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) {
   constexpr TaskTraits foo_traits = {TaskPriority::BEST_EFFORT,
                                      TaskShutdownBehavior::BLOCK_SHUTDOWN};
   scoped_refptr<SingleThreadTaskRunner> foo_task_runner =
@@ -340,15 +338,14 @@
   }
 }
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest,
-       PostTaskAfterShutdown) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterShutdown) {
   auto task_runner = CreateTaskRunner();
   test::ShutdownTaskTracker(&task_tracker_);
   EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
 }
 
 // Verify that a Task runs shortly after its delay expires.
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) {
   TimeTicks start_time = TimeTicks::Now();
 
   WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC,
@@ -380,8 +377,7 @@
 
 // Verify that posting tasks after the single-thread manager is destroyed fails
 // but doesn't crash.
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest,
-       PostTaskAfterDestroy) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterDestroy) {
   auto task_runner = CreateTaskRunner();
   EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
   test::ShutdownTaskTracker(&task_tracker_);
@@ -390,14 +386,14 @@
 }
 
 // Verify that tasks only run when allowed by the CanRunPolicy.
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyBasic) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyBasic) {
   test::TestCanRunPolicyBasic(
       single_thread_task_runner_manager_.get(),
       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
       &task_tracker_);
 }
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest,
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,
        CanRunPolicyUpdatedBeforeRun) {
   test::TestCanRunPolicyChangedBeforeRun(
       single_thread_task_runner_manager_.get(),
@@ -405,7 +401,7 @@
       &task_tracker_);
 }
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyLoad) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyLoad) {
   test::TestCanRunPolicyLoad(
       single_thread_task_runner_manager_.get(),
       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
@@ -414,7 +410,7 @@
 
 INSTANTIATE_TEST_SUITE_P(
     AllModes,
-    ThreadPoolSingleThreadTaskRunnerManagerCommonTest,
+    PooledSingleThreadTaskRunnerManagerCommonTest,
     ::testing::Values(SingleThreadTaskRunnerThreadMode::SHARED,
                       SingleThreadTaskRunnerThreadMode::DEDICATED));
 
@@ -423,8 +419,8 @@
 class CallJoinFromDifferentThread : public SimpleThread {
  public:
   CallJoinFromDifferentThread(
-      SchedulerSingleThreadTaskRunnerManager* manager_to_join)
-      : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"),
+      PooledSingleThreadTaskRunnerManager* manager_to_join)
+      : SimpleThread("PooledSingleThreadTaskRunnerManagerJoinThread"),
         manager_to_join_(manager_to_join) {}
 
   ~CallJoinFromDifferentThread() override = default;
@@ -437,17 +433,17 @@
   void WaitForRunToStart() { run_started_event_.Wait(); }
 
  private:
-  SchedulerSingleThreadTaskRunnerManager* const manager_to_join_;
+  PooledSingleThreadTaskRunnerManager* const manager_to_join_;
   WaitableEvent run_started_event_;
 
   DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
 };
 
-class ThreadPoolSingleThreadTaskRunnerManagerJoinTest
-    : public ThreadPoolSingleThreadTaskRunnerManagerTest {
+class PooledSingleThreadTaskRunnerManagerJoinTest
+    : public PooledSingleThreadTaskRunnerManagerTest {
  public:
-  ThreadPoolSingleThreadTaskRunnerManagerJoinTest() = default;
-  ~ThreadPoolSingleThreadTaskRunnerManagerJoinTest() override = default;
+  PooledSingleThreadTaskRunnerManagerJoinTest() = default;
+  ~PooledSingleThreadTaskRunnerManagerJoinTest() override = default;
 
  protected:
   void TearDownSingleThreadTaskRunnerManager() override {
@@ -456,12 +452,12 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolSingleThreadTaskRunnerManagerJoinTest);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManagerJoinTest);
 };
 
 }  // namespace
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
+TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
   // Exercises the codepath where the workers are unavailable for unregistration
   // because of a Join call.
   WaitableEvent task_running;
@@ -488,7 +484,7 @@
   join_from_different_thread.Join();
 }
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerJoinTest,
+TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest,
        ConcurrentJoinExtraSkippedTask) {
   // Tests to make sure that tasks are properly cleaned up at Join, allowing
   // SingleThreadTaskRunners to unregister themselves.
@@ -519,7 +515,7 @@
 
 #if defined(OS_WIN)
 
-TEST_P(ThreadPoolSingleThreadTaskRunnerManagerCommonTest, COMSTAInitialized) {
+TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, COMSTAInitialized) {
   scoped_refptr<SingleThreadTaskRunner> com_task_runner =
       single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
           {TaskShutdownBehavior::BLOCK_SHUTDOWN}, GetParam());
@@ -530,7 +526,7 @@
   test::ShutdownTaskTracker(&task_tracker_);
 }
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) {
+TEST_F(PooledSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) {
   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
       single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
@@ -557,15 +553,15 @@
 namespace {
 
 const wchar_t* const kTestWindowClassName =
-    L"ThreadPoolSingleThreadTaskRunnerManagerTestWinMessageWindow";
+    L"PooledSingleThreadTaskRunnerManagerTestWinMessageWindow";
 
-class ThreadPoolSingleThreadTaskRunnerManagerTestWin
-    : public ThreadPoolSingleThreadTaskRunnerManagerTest {
+class PooledSingleThreadTaskRunnerManagerTestWin
+    : public PooledSingleThreadTaskRunnerManagerTest {
  public:
-  ThreadPoolSingleThreadTaskRunnerManagerTestWin() = default;
+  PooledSingleThreadTaskRunnerManagerTestWin() = default;
 
   void SetUp() override {
-    ThreadPoolSingleThreadTaskRunnerManagerTest::SetUp();
+    PooledSingleThreadTaskRunnerManagerTest::SetUp();
     register_class_succeeded_ = RegisterTestWindowClass();
     ASSERT_TRUE(register_class_succeeded_);
   }
@@ -574,7 +570,7 @@
     if (register_class_succeeded_)
       ::UnregisterClass(kTestWindowClassName, CURRENT_MODULE());
 
-    ThreadPoolSingleThreadTaskRunnerManagerTest::TearDown();
+    PooledSingleThreadTaskRunnerManagerTest::TearDown();
   }
 
   HWND CreateTestWindow() {
@@ -594,12 +590,12 @@
 
   bool register_class_succeeded_ = false;
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolSingleThreadTaskRunnerManagerTestWin);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManagerTestWin);
 };
 
 }  // namespace
 
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
+TEST_F(PooledSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
   scoped_refptr<SingleThreadTaskRunner> com_task_runner =
       single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
@@ -610,7 +606,7 @@
   // COM callback.
   com_task_runner->PostTask(
       FROM_HERE,
-      BindOnce([](ThreadPoolSingleThreadTaskRunnerManagerTestWin* test_harness,
+      BindOnce([](PooledSingleThreadTaskRunnerManagerTestWin* test_harness,
                   HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); },
                Unretained(this), &hwnd));
 
@@ -631,23 +627,23 @@
 
 namespace {
 
-class ThreadPoolSingleThreadTaskRunnerManagerStartTest
-    : public ThreadPoolSingleThreadTaskRunnerManagerTest {
+class PooledSingleThreadTaskRunnerManagerStartTest
+    : public PooledSingleThreadTaskRunnerManagerTest {
  public:
-  ThreadPoolSingleThreadTaskRunnerManagerStartTest() = default;
+  PooledSingleThreadTaskRunnerManagerStartTest() = default;
 
  private:
   void StartSingleThreadTaskRunnerManagerFromSetUp() override {
     // Start() is called in the test body rather than in SetUp().
   }
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolSingleThreadTaskRunnerManagerStartTest);
+  DISALLOW_COPY_AND_ASSIGN(PooledSingleThreadTaskRunnerManagerStartTest);
 };
 
 }  // namespace
 
 // Verify that a task posted before Start() doesn't run until Start() is called.
-TEST_F(ThreadPoolSingleThreadTaskRunnerManagerStartTest, PostTaskBeforeStart) {
+TEST_F(PooledSingleThreadTaskRunnerManagerStartTest, PostTaskBeforeStart) {
   AtomicFlag manager_started;
   WaitableEvent task_finished;
   single_thread_task_runner_manager_
diff --git a/base/task/thread_pool/scheduler_task_runner_delegate.cc b/base/task/thread_pool/pooled_task_runner_delegate.cc
similarity index 69%
rename from base/task/thread_pool/scheduler_task_runner_delegate.cc
rename to base/task/thread_pool/pooled_task_runner_delegate.cc
index f7aedcf..4bd597c 100644
--- a/base/task/thread_pool/scheduler_task_runner_delegate.cc
+++ b/base/task/thread_pool/pooled_task_runner_delegate.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
 
 namespace base {
 namespace internal {
 
 namespace {
 
-// Indicates whether a SchedulerTaskRunnerDelegate instance exists in the
+// Indicates whether a PooledTaskRunnerDelegate instance exists in the
 // process. Used to tell when a task is posted from the main thread after the
 // task environment was brought down in unit tests so that TaskRunners can
 // return false on PostTask, letting callers know they should complete
-// necessary work synchronously. A SchedulerTaskRunnerDelegate is usually
+// necessary work synchronously. A PooledTaskRunnerDelegate is usually
 // instantiated before worker threads are started and deleted after worker
 // threads have been joined. This makes the variable const while worker threads
 // are up and as such it doesn't need to be atomic.
@@ -21,18 +21,18 @@
 
 }  // namespace
 
-SchedulerTaskRunnerDelegate::SchedulerTaskRunnerDelegate() {
+PooledTaskRunnerDelegate::PooledTaskRunnerDelegate() {
   DCHECK(!g_exists);
   g_exists = true;
 }
 
-SchedulerTaskRunnerDelegate::~SchedulerTaskRunnerDelegate() {
+PooledTaskRunnerDelegate::~PooledTaskRunnerDelegate() {
   DCHECK(g_exists);
   g_exists = false;
 }
 
 // static
-bool SchedulerTaskRunnerDelegate::Exists() {
+bool PooledTaskRunnerDelegate::Exists() {
   return g_exists;
 }
 
diff --git a/base/task/thread_pool/scheduler_task_runner_delegate.h b/base/task/thread_pool/pooled_task_runner_delegate.h
similarity index 64%
rename from base/task/thread_pool/scheduler_task_runner_delegate.h
rename to base/task/thread_pool/pooled_task_runner_delegate.h
index 42e3d19..dace20e 100644
--- a/base/task/thread_pool/scheduler_task_runner_delegate.h
+++ b/base/task/thread_pool/pooled_task_runner_delegate.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 BASE_TASK_THREAD_POOL_SCHEDULER_TASK_RUNNER_DELEGATE_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_TASK_RUNNER_DELEGATE_H_
+#ifndef BASE_TASK_THREAD_POOL_POOLED_TASK_RUNNER_DELEGATE_H_
+#define BASE_TASK_THREAD_POOL_POOLED_TASK_RUNNER_DELEGATE_H_
 
 #include "base/base_export.h"
 #include "base/task/task_traits.h"
@@ -14,28 +14,28 @@
 namespace base {
 namespace internal {
 
-// Delegate interface for SchedulerParallelTaskRunner and
-// SchedulerSequencedTaskRunner.
-class BASE_EXPORT SchedulerTaskRunnerDelegate {
+// Delegate interface for PooledParallelTaskRunner and
+// PooledSequencedTaskRunner.
+class BASE_EXPORT PooledTaskRunnerDelegate {
  public:
-  SchedulerTaskRunnerDelegate();
-  virtual ~SchedulerTaskRunnerDelegate();
+  PooledTaskRunnerDelegate();
+  virtual ~PooledTaskRunnerDelegate();
 
-  // Returns true if a SchedulerTaskRunnerDelegate instance exists in the
+  // Returns true if a PooledTaskRunnerDelegate instance exists in the
   // process. This is needed in case of unit tests wherein a TaskRunner
   // outlives the ThreadPool that created it.
   static bool Exists();
 
-  // Invoked when a |task| is posted to the SchedulerParallelTaskRunner or
-  // SchedulerSequencedTaskRunner. The implementation must post |task| to
+  // Invoked when a |task| is posted to the PooledParallelTaskRunner or
+  // PooledSequencedTaskRunner. The implementation must post |task| to
   // |sequence| within the appropriate priority queue, depending on |sequence|
   // traits. Returns true if task was successfully posted.
   virtual bool PostTaskWithSequence(Task task,
                                     scoped_refptr<Sequence> sequence) = 0;
 
   // Invoked when RunsTasksInCurrentSequence() is called on a
-  // SchedulerParallelTaskRunner. Returns true if the worker pool used by the
-  // SchedulerParallelTaskRunner (as determined by |traits|) is running on
+  // PooledParallelTaskRunner. Returns true if the worker pool used by the
+  // PooledParallelTaskRunner (as determined by |traits|) is running on
   // this thread.
   virtual bool IsRunningPoolWithTraits(const TaskTraits& traits) const = 0;
 
@@ -50,4 +50,4 @@
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_TASK_RUNNER_DELEGATE_H_
+#endif  // BASE_TASK_THREAD_POOL_POOLED_TASK_RUNNER_DELEGATE_H_
diff --git a/base/task/thread_pool/priority_queue_unittest.cc b/base/task/thread_pool/priority_queue_unittest.cc
index 6cff85f..559aed2b 100644
--- a/base/task/thread_pool/priority_queue_unittest.cc
+++ b/base/task/thread_pool/priority_queue_unittest.cc
@@ -32,7 +32,7 @@
   return sequence;
 }
 
-class ThreadPoolPriorityQueueWithSequencesTest : public testing::Test {
+class PriorityQueueWithSequencesTest : public testing::Test {
  protected:
   void ExpectNumSequences(size_t num_best_effort,
                           size_t num_user_visible,
@@ -66,7 +66,7 @@
 
 }  // namespace
 
-TEST_F(ThreadPoolPriorityQueueWithSequencesTest, PushPopPeek) {
+TEST_F(PriorityQueueWithSequencesTest, PushPopPeek) {
   EXPECT_TRUE(pq.IsEmpty());
   ExpectNumSequences(0U, 0U, 0U);
 
@@ -118,7 +118,7 @@
   ExpectNumSequences(0U, 0U, 0U);
 }
 
-TEST_F(ThreadPoolPriorityQueueWithSequencesTest, RemoveSequence) {
+TEST_F(PriorityQueueWithSequencesTest, RemoveSequence) {
   EXPECT_TRUE(pq.IsEmpty());
 
   // Push all test Sequences into the PriorityQueue. |sequence_b|
@@ -163,7 +163,7 @@
   ExpectNumSequences(0U, 0U, 0U);
 }
 
-TEST_F(ThreadPoolPriorityQueueWithSequencesTest, UpdateSortKey) {
+TEST_F(PriorityQueueWithSequencesTest, UpdateSortKey) {
   EXPECT_TRUE(pq.IsEmpty());
 
   // Push all test Sequences into the PriorityQueue. |sequence_b| becomes the
diff --git a/base/task/thread_pool/scheduler_parallel_task_runner.cc b/base/task/thread_pool/scheduler_parallel_task_runner.cc
deleted file mode 100644
index f83395a8..0000000
--- a/base/task/thread_pool/scheduler_parallel_task_runner.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 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/task/thread_pool/scheduler_parallel_task_runner.h"
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
-
-#include "base/task/thread_pool/sequence.h"
-
-namespace base {
-namespace internal {
-
-SchedulerParallelTaskRunner::SchedulerParallelTaskRunner(
-    const TaskTraits& traits,
-    SchedulerTaskRunnerDelegate* scheduler_task_runner_delegate)
-    : traits_(traits),
-      scheduler_task_runner_delegate_(scheduler_task_runner_delegate) {}
-
-SchedulerParallelTaskRunner::~SchedulerParallelTaskRunner() = default;
-
-bool SchedulerParallelTaskRunner::PostDelayedTask(const Location& from_here,
-                                                  OnceClosure closure,
-                                                  TimeDelta delay) {
-  if (!SchedulerTaskRunnerDelegate::Exists())
-    return false;
-
-  // Post the task as part of a one-off single-task Sequence.
-  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
-      traits_, this, TaskSourceExecutionMode::kParallel);
-
-  {
-    CheckedAutoLock auto_lock(lock_);
-    sequences_.insert(sequence.get());
-  }
-
-  return scheduler_task_runner_delegate_->PostTaskWithSequence(
-      Task(from_here, std::move(closure), delay), std::move(sequence));
-}
-
-bool SchedulerParallelTaskRunner::RunsTasksInCurrentSequence() const {
-  return scheduler_task_runner_delegate_->IsRunningPoolWithTraits(traits_);
-}
-
-void SchedulerParallelTaskRunner::UnregisterSequence(Sequence* sequence) {
-  DCHECK(sequence);
-
-  CheckedAutoLock auto_lock(lock_);
-  sequences_.erase(sequence);
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/task/thread_pool/scheduler_sequenced_task_runner.cc b/base/task/thread_pool/scheduler_sequenced_task_runner.cc
deleted file mode 100644
index b85312b..0000000
--- a/base/task/thread_pool/scheduler_sequenced_task_runner.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2018 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/task/thread_pool/scheduler_sequenced_task_runner.h"
-
-#include "base/sequence_token.h"
-
-namespace base {
-namespace internal {
-
-SchedulerSequencedTaskRunner::SchedulerSequencedTaskRunner(
-    const TaskTraits& traits,
-    SchedulerTaskRunnerDelegate* scheduler_task_runner_delegate)
-    : scheduler_task_runner_delegate_(scheduler_task_runner_delegate),
-      sequence_(MakeRefCounted<Sequence>(traits,
-                                         this,
-                                         TaskSourceExecutionMode::kSequenced)) {
-}
-
-SchedulerSequencedTaskRunner::~SchedulerSequencedTaskRunner() = default;
-
-bool SchedulerSequencedTaskRunner::PostDelayedTask(const Location& from_here,
-                                                   OnceClosure closure,
-                                                   TimeDelta delay) {
-  if (!SchedulerTaskRunnerDelegate::Exists())
-    return false;
-
-  Task task(from_here, std::move(closure), delay);
-
-  // Post the task as part of |sequence_|.
-  return scheduler_task_runner_delegate_->PostTaskWithSequence(std::move(task),
-                                                               sequence_);
-}
-
-bool SchedulerSequencedTaskRunner::PostNonNestableDelayedTask(
-    const Location& from_here,
-    OnceClosure closure,
-    TimeDelta delay) {
-  // Tasks are never nested within the thread pool.
-  return PostDelayedTask(from_here, std::move(closure), delay);
-}
-
-bool SchedulerSequencedTaskRunner::RunsTasksInCurrentSequence() const {
-  return sequence_->token() == SequenceToken::GetForCurrentThread();
-}
-
-void SchedulerSequencedTaskRunner::UpdatePriority(TaskPriority priority) {
-  scheduler_task_runner_delegate_->UpdatePriority(sequence_, priority);
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/task/thread_pool/scheduler_worker_observer.h b/base/task/thread_pool/scheduler_worker_observer.h
deleted file mode 100644
index bd04bf4..0000000
--- a/base/task/thread_pool/scheduler_worker_observer.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 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_TASK_THREAD_POOL_SCHEDULER_WORKER_OBSERVER_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_OBSERVER_H_
-
-namespace base {
-
-// Interface to observe entry and exit of the main function of a ThreadPool
-// worker.
-class SchedulerWorkerObserver {
- public:
-  virtual ~SchedulerWorkerObserver() = default;
-
-  // Invoked at the beginning of the main function of a ThreadPool worker,
-  // before any task runs.
-  virtual void OnSchedulerWorkerMainEntry() = 0;
-
-  // Invoked at the end of the main function of a ThreadPool worker, when it
-  // can no longer run tasks.
-  virtual void OnSchedulerWorkerMainExit() = 0;
-};
-
-}  // namespace base
-
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_OBSERVER_H_
diff --git a/base/task/thread_pool/scheduler_worker_pool_params.cc b/base/task/thread_pool/scheduler_worker_pool_params.cc
deleted file mode 100644
index fbe2b05..0000000
--- a/base/task/thread_pool/scheduler_worker_pool_params.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 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/task/thread_pool/scheduler_worker_pool_params.h"
-
-namespace base {
-
-SchedulerWorkerPoolParams::SchedulerWorkerPoolParams(
-    int max_tasks,
-    TimeDelta suggested_reclaim_time,
-    SchedulerBackwardCompatibility backward_compatibility)
-    : max_tasks_(max_tasks),
-      suggested_reclaim_time_(suggested_reclaim_time),
-      backward_compatibility_(backward_compatibility) {}
-
-SchedulerWorkerPoolParams::SchedulerWorkerPoolParams(
-    const SchedulerWorkerPoolParams& other) = default;
-
-SchedulerWorkerPoolParams& SchedulerWorkerPoolParams::operator=(
-    const SchedulerWorkerPoolParams& other) = default;
-
-}  // namespace base
diff --git a/base/task/thread_pool/scheduler_worker_pool_params.h b/base/task/thread_pool/scheduler_worker_pool_params.h
deleted file mode 100644
index 64d6f9e8..0000000
--- a/base/task/thread_pool/scheduler_worker_pool_params.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 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_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_PARAMS_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_PARAMS_H_
-
-#include "base/task/thread_pool/scheduler_worker_params.h"
-#include "base/time/time.h"
-
-namespace base {
-
-class BASE_EXPORT SchedulerWorkerPoolParams final {
- public:
-  // Constructs a set of params used to initialize a pool. The pool will run
-  // concurrently at most |max_tasks| that aren't blocked (ScopedBlockingCall).
-  // |suggested_reclaim_time| sets a suggestion on when to reclaim idle threads.
-  // The pool is free to ignore this value for performance or correctness
-  // reasons. |backward_compatibility| indicates whether backward compatibility
-  // is enabled.
-  SchedulerWorkerPoolParams(
-      int max_tasks,
-      TimeDelta suggested_reclaim_time,
-      SchedulerBackwardCompatibility backward_compatibility =
-          SchedulerBackwardCompatibility::DISABLED);
-
-  SchedulerWorkerPoolParams(const SchedulerWorkerPoolParams& other);
-  SchedulerWorkerPoolParams& operator=(const SchedulerWorkerPoolParams& other);
-
-  int max_tasks() const { return max_tasks_; }
-  TimeDelta suggested_reclaim_time() const { return suggested_reclaim_time_; }
-  SchedulerBackwardCompatibility backward_compatibility() const {
-    return backward_compatibility_;
-  }
-
- private:
-  int max_tasks_;
-  TimeDelta suggested_reclaim_time_;
-  SchedulerBackwardCompatibility backward_compatibility_;
-};
-
-}  // namespace base
-
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_PARAMS_H_
diff --git a/base/task/thread_pool/scheduler_worker_stack.cc b/base/task/thread_pool/scheduler_worker_stack.cc
deleted file mode 100644
index 00cec88..0000000
--- a/base/task/thread_pool/scheduler_worker_stack.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 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/task/thread_pool/scheduler_worker_stack.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/task/thread_pool/scheduler_worker.h"
-
-namespace base {
-namespace internal {
-
-SchedulerWorkerStack::SchedulerWorkerStack() = default;
-
-SchedulerWorkerStack::~SchedulerWorkerStack() = default;
-
-void SchedulerWorkerStack::Push(SchedulerWorker* worker) {
-  DCHECK(!Contains(worker)) << "SchedulerWorker already on stack";
-  if (!IsEmpty())
-    stack_.back()->BeginUnusedPeriod();
-  stack_.push_back(worker);
-}
-
-SchedulerWorker* SchedulerWorkerStack::Pop() {
-  if (IsEmpty())
-    return nullptr;
-  SchedulerWorker* const worker = stack_.back();
-  stack_.pop_back();
-  if (!IsEmpty())
-    stack_.back()->EndUnusedPeriod();
-  return worker;
-}
-
-SchedulerWorker* SchedulerWorkerStack::Peek() const {
-  if (IsEmpty())
-    return nullptr;
-  return stack_.back();
-}
-
-bool SchedulerWorkerStack::Contains(const SchedulerWorker* worker) const {
-  return ContainsValue(stack_, worker);
-}
-
-void SchedulerWorkerStack::Remove(const SchedulerWorker* worker) {
-  DCHECK(!IsEmpty());
-  DCHECK_NE(worker, stack_.back());
-  auto it = std::find(stack_.begin(), stack_.end(), worker);
-  DCHECK(it != stack_.end());
-  DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime());
-  stack_.erase(it);
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/task/thread_pool/scheduler_worker_stack.h b/base/task/thread_pool/scheduler_worker_stack.h
deleted file mode 100644
index e3ab767..0000000
--- a/base/task/thread_pool/scheduler_worker_stack.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 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_TASK_THREAD_POOL_SCHEDULER_WORKER_STACK_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_STACK_H_
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-
-namespace base {
-namespace internal {
-
-class SchedulerWorker;
-
-// A stack of SchedulerWorkers which has custom logic to treat the worker on top
-// of the stack as being "in-use" (so its time in that position doesn't count
-// towards being inactive / reclaimable). Supports removal of arbitrary
-// SchedulerWorkers. DCHECKs when a SchedulerWorker is inserted multiple times.
-// SchedulerWorkers are not owned by the stack. Push() is amortized O(1). Pop(),
-// Peek(), Size() and Empty() are O(1). Contains() and Remove() are O(n). This
-// class is NOT thread-safe.
-class BASE_EXPORT SchedulerWorkerStack {
- public:
-  SchedulerWorkerStack();
-  ~SchedulerWorkerStack();
-
-  // Inserts |worker| at the top of the stack. |worker| must not already be on
-  // the stack. Flags the SchedulerWorker previously on top of the stack, if
-  // any, as unused.
-  void Push(SchedulerWorker* worker);
-
-  // Removes the top SchedulerWorker from the stack and returns it. Returns
-  // nullptr if the stack is empty. Flags the SchedulerWorker now on top of the
-  // stack, if any, as being in-use.
-  SchedulerWorker* Pop();
-
-  // Returns the top SchedulerWorker from the stack, nullptr if empty.
-  SchedulerWorker* Peek() const;
-
-  // Returns true if |worker| is already on the stack.
-  bool Contains(const SchedulerWorker* worker) const;
-
-  // Removes |worker| from the stack. Must not be invoked for the first worker
-  // on the stack.
-  void Remove(const SchedulerWorker* worker);
-
-  // Returns the number of SchedulerWorkers on the stack.
-  size_t Size() const { return stack_.size(); }
-
-  // Returns true if the stack is empty.
-  bool IsEmpty() const { return stack_.empty(); }
-
- private:
-  std::vector<SchedulerWorker*> stack_;
-
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerStack);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_STACK_H_
diff --git a/base/task/thread_pool/sequence.cc b/base/task/thread_pool/sequence.cc
index 7ff0fa8..761702a8 100644
--- a/base/task/thread_pool/sequence.cc
+++ b/base/task/thread_pool/sequence.cc
@@ -107,7 +107,7 @@
   if (!task_runner())
     return;
   if (execution_mode() == TaskSourceExecutionMode::kParallel) {
-    static_cast<SchedulerParallelTaskRunner*>(task_runner())
+    static_cast<PooledParallelTaskRunner*>(task_runner())
         ->UnregisterSequence(this);
   }
   // No member access after this point, releasing |task_runner()| might delete
diff --git a/base/task/thread_pool/sequence.h b/base/task/thread_pool/sequence.h
index a4f8495..66863e48 100644
--- a/base/task/thread_pool/sequence.h
+++ b/base/task/thread_pool/sequence.h
@@ -13,7 +13,7 @@
 #include "base/optional.h"
 #include "base/sequence_token.h"
 #include "base/task/task_traits.h"
-#include "base/task/thread_pool/scheduler_parallel_task_runner.h"
+#include "base/task/thread_pool/pooled_parallel_task_runner.h"
 #include "base/task/thread_pool/sequence_sort_key.h"
 #include "base/task/thread_pool/task.h"
 #include "base/task/thread_pool/task_source.h"
@@ -30,8 +30,8 @@
 // Note: there is a known refcounted-ownership cycle in the Scheduler
 // architecture: Sequence -> Task -> TaskRunner -> Sequence -> ...
 // This is okay so long as the other owners of Sequence (PriorityQueue and
-// SchedulerWorker in alternation and
-// SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
+// WorkerThread in alternation and
+// ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork()
 // temporarily) keep running it (and taking Tasks from it as a result). A
 // dangling reference cycle would only occur should they release their reference
 // to it while it's not empty. In other words, it is only correct for them to
diff --git a/base/task/thread_pool/sequence_sort_key_unittest.cc b/base/task/thread_pool/sequence_sort_key_unittest.cc
index 4791486f..b9308db8 100644
--- a/base/task/thread_pool/sequence_sort_key_unittest.cc
+++ b/base/task/thread_pool/sequence_sort_key_unittest.cc
@@ -11,7 +11,7 @@
 namespace base {
 namespace internal {
 
-TEST(ThreadPoolSequenceSortKeyTest, OperatorLessThanOrEqual) {
+TEST(SequenceSortKeyTest, OperatorLessThanOrEqual) {
   SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
                         TimeTicks::FromInternalValue(1000));
   SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
@@ -68,7 +68,7 @@
   EXPECT_LE(key_f, key_f);
 }
 
-TEST(ThreadPoolSequenceSortKeyTest, OperatorEqual) {
+TEST(SequenceSortKeyTest, OperatorEqual) {
   SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
                         TimeTicks::FromInternalValue(1000));
   SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
@@ -125,7 +125,7 @@
   EXPECT_EQ(key_f, key_f);
 }
 
-TEST(ThreadPoolSequenceSortKeyTest, OperatorNotEqual) {
+TEST(SequenceSortKeyTest, OperatorNotEqual) {
   SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
                         TimeTicks::FromInternalValue(1000));
   SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
diff --git a/base/task/thread_pool/service_thread_unittest.cc b/base/task/thread_pool/service_thread_unittest.cc
index be5a09d2..6b666356 100644
--- a/base/task/thread_pool/service_thread_unittest.cc
+++ b/base/task/thread_pool/service_thread_unittest.cc
@@ -28,7 +28,7 @@
   SCOPED_TRACE(stack);
   const bool found_on_stack = stack.find(query) != std::string::npos;
   const bool stack_has_symbols =
-      stack.find("SchedulerWorker") != std::string::npos;
+      stack.find("WorkerThread") != std::string::npos;
   EXPECT_TRUE(found_on_stack || !stack_has_symbols) << query;
 }
 
diff --git a/base/task/thread_pool/task_source.h b/base/task/thread_pool/task_source.h
index b61ad8d7..93ad825 100644
--- a/base/task/thread_pool/task_source.h
+++ b/base/task/thread_pool/task_source.h
@@ -49,8 +49,8 @@
 // Note: there is a known refcounted-ownership cycle in the Scheduler
 // architecture: TaskSource -> Task -> TaskRunner -> TaskSource -> ...
 // This is okay so long as the other owners of TaskSource (PriorityQueue and
-// SchedulerWorker in alternation and
-// SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork()
+// WorkerThread in alternation and
+// ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork()
 // temporarily) keep running it (and taking Tasks from it as a result). A
 // dangling reference cycle would only occur should they release their reference
 // to it while it's not empty. In other words, it is only correct for them to
diff --git a/base/task/thread_pool/test_utils.cc b/base/task/thread_pool/test_utils.cc
index db69497..77c9da3 100644
--- a/base/task/thread_pool/test_utils.cc
+++ b/base/task/thread_pool/test_utils.cc
@@ -8,8 +8,8 @@
 
 #include "base/bind.h"
 #include "base/synchronization/condition_variable.h"
-#include "base/task/thread_pool/scheduler_parallel_task_runner.h"
-#include "base/task/thread_pool/scheduler_sequenced_task_runner.h"
+#include "base/task/thread_pool/pooled_parallel_task_runner.h"
+#include "base/task/thread_pool/pooled_sequenced_task_runner.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_restrictions.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -18,26 +18,26 @@
 namespace internal {
 namespace test {
 
-MockSchedulerWorkerObserver::MockSchedulerWorkerObserver()
+MockWorkerThreadObserver::MockWorkerThreadObserver()
     : on_main_exit_cv_(lock_.CreateConditionVariable()) {}
 
-MockSchedulerWorkerObserver::~MockSchedulerWorkerObserver() {
+MockWorkerThreadObserver::~MockWorkerThreadObserver() {
   WaitCallsOnMainExit();
 }
 
-void MockSchedulerWorkerObserver::AllowCallsOnMainExit(int num_calls) {
+void MockWorkerThreadObserver::AllowCallsOnMainExit(int num_calls) {
   CheckedAutoLock auto_lock(lock_);
   EXPECT_EQ(0, allowed_calls_on_main_exit_);
   allowed_calls_on_main_exit_ = num_calls;
 }
 
-void MockSchedulerWorkerObserver::WaitCallsOnMainExit() {
+void MockWorkerThreadObserver::WaitCallsOnMainExit() {
   CheckedAutoLock auto_lock(lock_);
   while (allowed_calls_on_main_exit_ != 0)
     on_main_exit_cv_->Wait();
 }
 
-void MockSchedulerWorkerObserver::OnSchedulerWorkerMainExit() {
+void MockWorkerThreadObserver::OnWorkerThreadMainExit() {
   CheckedAutoLock auto_lock(lock_);
   EXPECT_GE(allowed_calls_on_main_exit_, 0);
   --allowed_calls_on_main_exit_;
@@ -58,15 +58,15 @@
 
 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode(
     test::ExecutionMode execution_mode,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate,
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate,
     const TaskTraits& traits) {
   switch (execution_mode) {
     case test::ExecutionMode::PARALLEL:
       return CreateTaskRunnerWithTraits(traits,
-                                        mock_scheduler_task_runner_delegate);
+                                        mock_pooled_task_runner_delegate);
     case test::ExecutionMode::SEQUENCED:
       return CreateSequencedTaskRunnerWithTraits(
-          traits, mock_scheduler_task_runner_delegate);
+          traits, mock_pooled_task_runner_delegate);
     default:
       // Fall through.
       break;
@@ -77,16 +77,16 @@
 
 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
     const TaskTraits& traits,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate) {
-  return MakeRefCounted<SchedulerParallelTaskRunner>(
-      traits, mock_scheduler_task_runner_delegate);
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate) {
+  return MakeRefCounted<PooledParallelTaskRunner>(
+      traits, mock_pooled_task_runner_delegate);
 }
 
 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
     const TaskTraits& traits,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate) {
-  return MakeRefCounted<SchedulerSequencedTaskRunner>(
-      traits, mock_scheduler_task_runner_delegate);
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate) {
+  return MakeRefCounted<PooledSequencedTaskRunner>(
+      traits, mock_pooled_task_runner_delegate);
 }
 
 // Waits on |event| in a scope where the blocking observer is null, to avoid
@@ -97,19 +97,20 @@
   event->Wait();
 }
 
-MockSchedulerTaskRunnerDelegate::MockSchedulerTaskRunnerDelegate(
+MockPooledTaskRunnerDelegate::MockPooledTaskRunnerDelegate(
     TrackedRef<TaskTracker> task_tracker,
     DelayedTaskManager* delayed_task_manager)
     : task_tracker_(task_tracker),
       delayed_task_manager_(delayed_task_manager) {}
 
-MockSchedulerTaskRunnerDelegate::~MockSchedulerTaskRunnerDelegate() = default;
+MockPooledTaskRunnerDelegate::~MockPooledTaskRunnerDelegate() = default;
 
-bool MockSchedulerTaskRunnerDelegate::PostTaskWithSequence(
+bool MockPooledTaskRunnerDelegate::PostTaskWithSequence(
     Task task,
     scoped_refptr<Sequence> sequence) {
-  // |worker_pool_| must be initialized with SetWorkerPool() before proceeding.
-  DCHECK(worker_pool_);
+  // |thread_group_| must be initialized with SetThreadGroup() before
+  // proceeding.
+  DCHECK(thread_group_);
   DCHECK(task.task);
   DCHECK(sequence);
 
@@ -117,7 +118,7 @@
     return false;
 
   if (task.delayed_run_time.is_null()) {
-    worker_pool_->PostTaskWithSequenceNow(
+    thread_group_->PostTaskWithSequenceNow(
         std::move(task),
         SequenceAndTransaction::FromSequence(std::move(sequence)));
   } else {
@@ -127,39 +128,39 @@
     delayed_task_manager_->AddDelayedTask(
         std::move(task),
         BindOnce(
-            [](scoped_refptr<Sequence> sequence,
-               SchedulerWorkerPool* worker_pool, Task task) {
-              worker_pool->PostTaskWithSequenceNow(
+            [](scoped_refptr<Sequence> sequence, ThreadGroup* thread_group,
+               Task task) {
+              thread_group->PostTaskWithSequenceNow(
                   std::move(task),
                   SequenceAndTransaction::FromSequence(std::move(sequence)));
             },
-            std::move(sequence), worker_pool_),
+            std::move(sequence), thread_group_),
         std::move(task_runner));
   }
 
   return true;
 }
 
-bool MockSchedulerTaskRunnerDelegate::IsRunningPoolWithTraits(
+bool MockPooledTaskRunnerDelegate::IsRunningPoolWithTraits(
     const TaskTraits& traits) const {
-  // |worker_pool_| must be initialized with SetWorkerPool() before proceeding.
-  DCHECK(worker_pool_);
+  // |thread_group_| must be initialized with SetThreadGroup() before
+  // proceeding.
+  DCHECK(thread_group_);
 
-  return worker_pool_->IsBoundToCurrentThread();
+  return thread_group_->IsBoundToCurrentThread();
 }
 
-void MockSchedulerTaskRunnerDelegate::UpdatePriority(
+void MockPooledTaskRunnerDelegate::UpdatePriority(
     scoped_refptr<TaskSource> task_source,
     TaskPriority priority) {
   auto task_source_and_transaction =
       TaskSourceAndTransaction::FromTaskSource(std::move(task_source));
   task_source_and_transaction.transaction.UpdatePriority(priority);
-  worker_pool_->UpdateSortKey(std::move(task_source_and_transaction));
+  thread_group_->UpdateSortKey(std::move(task_source_and_transaction));
 }
 
-void MockSchedulerTaskRunnerDelegate::SetWorkerPool(
-    SchedulerWorkerPool* worker_pool) {
-  worker_pool_ = worker_pool;
+void MockPooledTaskRunnerDelegate::SetThreadGroup(ThreadGroup* thread_group) {
+  thread_group_ = thread_group;
 }
 
 void ShutdownTaskTracker(TaskTracker* task_tracker) {
diff --git a/base/task/thread_pool/test_utils.h b/base/task/thread_pool/test_utils.h
index ee5835b..7a168a0 100644
--- a/base/task/thread_pool/test_utils.h
+++ b/base/task/thread_pool/test_utils.h
@@ -8,11 +8,11 @@
 #include "base/task/common/checked_lock.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
-#include "base/task/thread_pool/scheduler_worker_observer.h"
-#include "base/task/thread_pool/scheduler_worker_pool.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
 #include "base/task/thread_pool/sequence.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/thread_group.h"
+#include "base/task/thread_pool/worker_thread_observer.h"
 #include "base/task_runner.h"
 #include "base/thread_annotations.h"
 #include "build/build_config.h"
@@ -25,47 +25,47 @@
 
 namespace test {
 
-class MockSchedulerWorkerObserver : public SchedulerWorkerObserver {
+class MockWorkerThreadObserver : public WorkerThreadObserver {
  public:
-  MockSchedulerWorkerObserver();
-  ~MockSchedulerWorkerObserver();
+  MockWorkerThreadObserver();
+  ~MockWorkerThreadObserver();
 
   void AllowCallsOnMainExit(int num_calls);
   void WaitCallsOnMainExit();
 
-  // SchedulerWorkerObserver:
-  MOCK_METHOD0(OnSchedulerWorkerMainEntry, void());
+  // WorkerThreadObserver:
+  MOCK_METHOD0(OnWorkerThreadMainEntry, void());
   // This doesn't use MOCK_METHOD0 because some tests need to wait for all calls
   // to happen, which isn't possible with gmock.
-  void OnSchedulerWorkerMainExit() override;
+  void OnWorkerThreadMainExit() override;
 
  private:
   CheckedLock lock_;
   std::unique_ptr<ConditionVariable> on_main_exit_cv_ GUARDED_BY(lock_);
   int allowed_calls_on_main_exit_ GUARDED_BY(lock_) = 0;
 
-  DISALLOW_COPY_AND_ASSIGN(MockSchedulerWorkerObserver);
+  DISALLOW_COPY_AND_ASSIGN(MockWorkerThreadObserver);
 };
 
-class MockSchedulerTaskRunnerDelegate : public SchedulerTaskRunnerDelegate {
+class MockPooledTaskRunnerDelegate : public PooledTaskRunnerDelegate {
  public:
-  MockSchedulerTaskRunnerDelegate(TrackedRef<TaskTracker> task_tracker,
-                                  DelayedTaskManager* delayed_task_manager);
-  ~MockSchedulerTaskRunnerDelegate() override;
+  MockPooledTaskRunnerDelegate(TrackedRef<TaskTracker> task_tracker,
+                               DelayedTaskManager* delayed_task_manager);
+  ~MockPooledTaskRunnerDelegate() override;
 
-  // SchedulerTaskRunnerDelegate:
+  // PooledTaskRunnerDelegate:
   bool PostTaskWithSequence(Task task,
                             scoped_refptr<Sequence> sequence) override;
   bool IsRunningPoolWithTraits(const TaskTraits& traits) const override;
   void UpdatePriority(scoped_refptr<TaskSource> task_source,
                       TaskPriority priority) override;
 
-  void SetWorkerPool(SchedulerWorkerPool* worker_pool);
+  void SetThreadGroup(ThreadGroup* thread_group);
 
  private:
   const TrackedRef<TaskTracker> task_tracker_;
   DelayedTaskManager* const delayed_task_manager_;
-  SchedulerWorkerPool* worker_pool_ = nullptr;
+  ThreadGroup* thread_group_ = nullptr;
 };
 
 // An enumeration of possible thread pool TaskRunner types. Used to
@@ -93,21 +93,21 @@
         TaskSourceExecutionMode::kParallel);
 
 // Creates a TaskRunner that posts tasks to the worker pool owned by
-// |scheduler_task_runner_delegate| with the |execution_mode| execution mode
+// |pooled_task_runner_delegate| with the |execution_mode| execution mode
 // and the WithBaseSyncPrimitives() trait.
 // Caveat: this does not support ExecutionMode::SINGLE_THREADED.
 scoped_refptr<TaskRunner> CreateTaskRunnerWithExecutionMode(
     test::ExecutionMode execution_mode,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate,
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate,
     const TaskTraits& traits = TaskTraits());
 
 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
     const TaskTraits& traits,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate);
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate);
 
 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
     const TaskTraits& traits,
-    MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate);
+    MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate);
 
 void WaitWithoutBlockingObserver(WaitableEvent* event);
 
diff --git a/base/task/thread_pool/scheduler_worker_pool.cc b/base/task/thread_pool/thread_group.cc
similarity index 68%
rename from base/task/thread_pool/scheduler_worker_pool.cc
rename to base/task/thread_pool/thread_group.cc
index ca44ea6d..a640be9 100644
--- a/base/task/thread_pool/scheduler_worker_pool.cc
+++ b/base/task/thread_pool/thread_group.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 "base/task/thread_pool/scheduler_worker_pool.h"
+#include "base/task/thread_pool/thread_group.h"
 
 #include <utility>
 
@@ -17,30 +17,29 @@
 
 namespace {
 
-// SchedulerWorkerPool that owns the current thread, if any.
-LazyInstance<ThreadLocalPointer<const SchedulerWorkerPool>>::Leaky
-    tls_current_worker_pool = LAZY_INSTANCE_INITIALIZER;
+// ThreadGroup that owns the current thread, if any.
+LazyInstance<ThreadLocalPointer<const ThreadGroup>>::Leaky
+    tls_current_thread_group = LAZY_INSTANCE_INITIALIZER;
 
-const SchedulerWorkerPool* GetCurrentWorkerPool() {
-  return tls_current_worker_pool.Get().Get();
+const ThreadGroup* GetCurrentThreadGroup() {
+  return tls_current_thread_group.Get().Get();
 }
 
 }  // namespace
 
-SchedulerWorkerPool::ScopedReenqueueExecutor::ScopedReenqueueExecutor() =
-    default;
+ThreadGroup::ScopedReenqueueExecutor::ScopedReenqueueExecutor() = default;
 
-SchedulerWorkerPool::ScopedReenqueueExecutor::~ScopedReenqueueExecutor() {
+ThreadGroup::ScopedReenqueueExecutor::~ScopedReenqueueExecutor() {
   if (destination_pool_) {
     destination_pool_->PushTaskSourceAndWakeUpWorkers(
         std::move(task_source_and_transaction_.value()));
   }
 }
 
-void SchedulerWorkerPool::ScopedReenqueueExecutor::
+void ThreadGroup::ScopedReenqueueExecutor::
     SchedulePushTaskSourceAndWakeUpWorkers(
         TaskSourceAndTransaction task_source_and_transaction,
-        SchedulerWorkerPool* destination_pool) {
+        ThreadGroup* destination_pool) {
   DCHECK(destination_pool);
   DCHECK(!destination_pool_);
   DCHECK(!task_source_and_transaction_);
@@ -48,32 +47,32 @@
   destination_pool_ = destination_pool;
 }
 
-SchedulerWorkerPool::SchedulerWorkerPool(TrackedRef<TaskTracker> task_tracker,
-                                         TrackedRef<Delegate> delegate,
-                                         SchedulerWorkerPool* predecessor_pool)
+ThreadGroup::ThreadGroup(TrackedRef<TaskTracker> task_tracker,
+                         TrackedRef<Delegate> delegate,
+                         ThreadGroup* predecessor_pool)
     : task_tracker_(std::move(task_tracker)),
       delegate_(std::move(delegate)),
       lock_(predecessor_pool ? &predecessor_pool->lock_ : nullptr) {
   DCHECK(task_tracker_);
 }
 
-SchedulerWorkerPool::~SchedulerWorkerPool() = default;
+ThreadGroup::~ThreadGroup() = default;
 
-void SchedulerWorkerPool::BindToCurrentThread() {
-  DCHECK(!GetCurrentWorkerPool());
-  tls_current_worker_pool.Get().Set(this);
+void ThreadGroup::BindToCurrentThread() {
+  DCHECK(!GetCurrentThreadGroup());
+  tls_current_thread_group.Get().Set(this);
 }
 
-void SchedulerWorkerPool::UnbindFromCurrentThread() {
-  DCHECK(GetCurrentWorkerPool());
-  tls_current_worker_pool.Get().Set(nullptr);
+void ThreadGroup::UnbindFromCurrentThread() {
+  DCHECK(GetCurrentThreadGroup());
+  tls_current_thread_group.Get().Set(nullptr);
 }
 
-bool SchedulerWorkerPool::IsBoundToCurrentThread() const {
-  return GetCurrentWorkerPool() == this;
+bool ThreadGroup::IsBoundToCurrentThread() const {
+  return GetCurrentThreadGroup() == this;
 }
 
-void SchedulerWorkerPool::PostTaskWithSequenceNow(
+void ThreadGroup::PostTaskWithSequenceNow(
     Task task,
     SequenceAndTransaction sequence_and_transaction) {
   DCHECK(task.task);
@@ -91,7 +90,7 @@
   }
 }
 
-size_t SchedulerWorkerPool::GetNumQueuedCanRunBestEffortTaskSources() const {
+size_t ThreadGroup::GetNumQueuedCanRunBestEffortTaskSources() const {
   const size_t num_queued =
       priority_queue_.GetNumTaskSourcesWithPriority(TaskPriority::BEST_EFFORT);
   if (num_queued == 0 ||
@@ -101,7 +100,7 @@
   return num_queued;
 }
 
-size_t SchedulerWorkerPool::GetNumQueuedCanRunForegroundTaskSources() const {
+size_t ThreadGroup::GetNumQueuedCanRunForegroundTaskSources() const {
   const size_t num_queued = priority_queue_.GetNumTaskSourcesWithPriority(
                                 TaskPriority::USER_VISIBLE) +
                             priority_queue_.GetNumTaskSourcesWithPriority(
@@ -113,18 +112,17 @@
   return num_queued;
 }
 
-bool SchedulerWorkerPool::RemoveTaskSource(
-    scoped_refptr<TaskSource> task_source) {
+bool ThreadGroup::RemoveTaskSource(scoped_refptr<TaskSource> task_source) {
   CheckedAutoLock auto_lock(lock_);
   return priority_queue_.RemoveTaskSource(std::move(task_source));
 }
 
-void SchedulerWorkerPool::ReEnqueueTaskSourceLockRequired(
+void ThreadGroup::ReEnqueueTaskSourceLockRequired(
     BaseScopedWorkersExecutor* workers_executor,
     ScopedReenqueueExecutor* reenqueue_executor,
     TaskSourceAndTransaction task_source_and_transaction) {
   // Decide in which pool the TaskSource should be reenqueued.
-  SchedulerWorkerPool* destination_pool = delegate_->GetWorkerPoolForTraits(
+  ThreadGroup* destination_pool = delegate_->GetThreadGroupForTraits(
       task_source_and_transaction.transaction.traits());
 
   if (destination_pool == this) {
@@ -140,7 +138,7 @@
   }
 }
 
-void SchedulerWorkerPool::UpdateSortKeyImpl(
+void ThreadGroup::UpdateSortKeyImpl(
     BaseScopedWorkersExecutor* executor,
     TaskSourceAndTransaction task_source_and_transaction) {
   CheckedAutoLock auto_lock(lock_);
@@ -148,7 +146,7 @@
   EnsureEnoughWorkersLockRequired(executor);
 }
 
-void SchedulerWorkerPool::PushTaskSourceAndWakeUpWorkersImpl(
+void ThreadGroup::PushTaskSourceAndWakeUpWorkersImpl(
     BaseScopedWorkersExecutor* executor,
     TaskSourceAndTransaction task_source_and_transaction) {
   CheckedAutoLock auto_lock(lock_);
@@ -158,8 +156,8 @@
   EnsureEnoughWorkersLockRequired(executor);
 }
 
-void SchedulerWorkerPool::InvalidateAndHandoffAllTaskSourcesToOtherPool(
-    SchedulerWorkerPool* destination_pool) {
+void ThreadGroup::InvalidateAndHandoffAllTaskSourcesToOtherPool(
+    ThreadGroup* destination_pool) {
   CheckedAutoLock current_pool_lock(lock_);
   CheckedAutoLock destination_pool_lock(destination_pool->lock_);
   destination_pool->priority_queue_ = std::move(priority_queue_);
diff --git a/base/task/thread_pool/scheduler_worker_pool.h b/base/task/thread_pool/thread_group.h
similarity index 87%
rename from base/task/thread_pool/scheduler_worker_pool.h
rename to base/task/thread_pool/thread_group.h
index 0b85a3e..aba2af2 100644
--- a/base/task/thread_pool/scheduler_worker_pool.h
+++ b/base/task/thread_pool/thread_group.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 BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_H_
+#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_H_
 
 #include "base/base_export.h"
 #include "base/memory/ref_counted.h"
@@ -21,18 +21,17 @@
 class TaskTracker;
 
 // Interface and base implementation for a worker pool.
-class BASE_EXPORT SchedulerWorkerPool {
+class BASE_EXPORT ThreadGroup {
  public:
-  // Delegate interface for SchedulerWorkerPool.
+  // Delegate interface for ThreadGroup.
   class BASE_EXPORT Delegate {
    public:
     virtual ~Delegate() = default;
 
     // Invoked when the TaskSource in |task_source_and_transaction| is non-empty
-    // after the SchedulerWorkerPool has run a task from it. The implementation
+    // after the ThreadGroup has run a task from it. The implementation
     // must return the pool in which the TaskSource should be reenqueued.
-    virtual SchedulerWorkerPool* GetWorkerPoolForTraits(
-        const TaskTraits& traits) = 0;
+    virtual ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) = 0;
   };
 
   enum class WorkerEnvironment {
@@ -44,9 +43,9 @@
 #endif  // defined(OS_WIN)
   };
 
-  virtual ~SchedulerWorkerPool();
+  virtual ~ThreadGroup();
 
-  // Posts |task| to be executed by this SchedulerWorkerPool as part of
+  // Posts |task| to be executed by this ThreadGroup as part of
   // the Sequence in |sequence_and_transaction|. This must only be called after
   // |task| has gone through TaskTracker::WillPostTask() and after |task|'s
   // delayed run time.
@@ -90,11 +89,11 @@
   // TODO(crbug.com/756547): Remove this method once the UseNativeThreadPool
   // experiment is complete.
   void InvalidateAndHandoffAllTaskSourcesToOtherPool(
-      SchedulerWorkerPool* destination_pool);
+      ThreadGroup* destination_pool);
 
   // Prevents new tasks from starting to run and waits for currently running
   // tasks to complete their execution. It is guaranteed that no thread will do
-  // work on behalf of this SchedulerWorkerPool after this returns. It is
+  // work on behalf of this ThreadGroup after this returns. It is
   // invalid to post a task once this is called. TaskTracker::Flush() can be
   // called before this to complete existing tasks, which might otherwise post a
   // task during JoinForTesting(). This can only be called once.
@@ -133,12 +132,12 @@
 
     void SchedulePushTaskSourceAndWakeUpWorkers(
         TaskSourceAndTransaction task_source_and_transaction,
-        SchedulerWorkerPool* destination_pool);
+        ThreadGroup* destination_pool);
 
    private:
     // A TaskSourceAndTransaction and the pool in which it should be enqueued.
     Optional<TaskSourceAndTransaction> task_source_and_transaction_;
-    SchedulerWorkerPool* destination_pool_ = nullptr;
+    ThreadGroup* destination_pool_ = nullptr;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedReenqueueExecutor);
   };
@@ -150,9 +149,9 @@
   //
   // TODO(crbug.com/756547): Remove |predecessor_pool| once the experiment is
   // complete.
-  SchedulerWorkerPool(TrackedRef<TaskTracker> task_tracker,
-                      TrackedRef<Delegate> delegate,
-                      SchedulerWorkerPool* predecessor_pool = nullptr);
+  ThreadGroup(TrackedRef<TaskTracker> task_tracker,
+              TrackedRef<Delegate> delegate,
+              ThreadGroup* predecessor_pool = nullptr);
 
   const TrackedRef<TaskTracker> task_tracker_;
   const TrackedRef<Delegate> delegate_;
@@ -200,13 +199,13 @@
   // If |replacement_pool_| is non-null, this pool is invalid and all task
   // sources should be scheduled on |replacement_pool_|. Used to support the
   // UseNativeThreadPool experiment.
-  SchedulerWorkerPool* replacement_pool_ = nullptr;
+  ThreadGroup* replacement_pool_ = nullptr;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPool);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroup);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_H_
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_H_
diff --git a/base/task/thread_pool/scheduler_worker_pool_impl.cc b/base/task/thread_pool/thread_group_impl.cc
similarity index 82%
rename from base/task/thread_pool/scheduler_worker_pool_impl.cc
rename to base/task/thread_pool/thread_group_impl.cc
index 0f8fd5b..a18cbfc 100644
--- a/base/task/thread_pool/scheduler_worker_pool_impl.cc
+++ b/base/task/thread_pool/thread_group_impl.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 "base/task/thread_pool/scheduler_worker_pool_impl.h"
+#include "base/task/thread_pool/thread_group_impl.h"
 
 #include <stddef.h>
 
@@ -25,8 +25,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/task/task_features.h"
 #include "base/task/task_traits.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread_checker.h"
@@ -83,10 +83,10 @@
 constexpr TimeDelta kBackgroundBlockedWorkersPoll = TimeDelta::FromSeconds(12);
 
 // Only used in DCHECKs.
-bool ContainsWorker(const std::vector<scoped_refptr<SchedulerWorker>>& workers,
-                    const SchedulerWorker* worker) {
+bool ContainsWorker(const std::vector<scoped_refptr<WorkerThread>>& workers,
+                    const WorkerThread* worker) {
   auto it = std::find_if(workers.begin(), workers.end(),
-                         [worker](const scoped_refptr<SchedulerWorker>& i) {
+                         [worker](const scoped_refptr<WorkerThread>& i) {
                            return i.get() == worker;
                          });
   return it != workers.end();
@@ -96,18 +96,18 @@
 
 // Upon destruction, executes actions that control the number of active workers.
 // Useful to satisfy locking requirements of these actions.
-class SchedulerWorkerPoolImpl::ScopedWorkersExecutor
-    : public SchedulerWorkerPool::BaseScopedWorkersExecutor {
+class ThreadGroupImpl::ScopedWorkersExecutor
+    : public ThreadGroup::BaseScopedWorkersExecutor {
  public:
-  ScopedWorkersExecutor(SchedulerWorkerPoolImpl* outer) : outer_(outer) {}
+  ScopedWorkersExecutor(ThreadGroupImpl* outer) : outer_(outer) {}
 
   ~ScopedWorkersExecutor() { FlushImpl(); }
 
-  void ScheduleWakeUp(scoped_refptr<SchedulerWorker> worker) {
+  void ScheduleWakeUp(scoped_refptr<WorkerThread> worker) {
     workers_to_wake_up_.AddWorker(std::move(worker));
   }
 
-  void ScheduleStart(scoped_refptr<SchedulerWorker> worker) {
+  void ScheduleStart(scoped_refptr<WorkerThread> worker) {
     workers_to_start_.AddWorker(std::move(worker));
   }
 
@@ -136,7 +136,7 @@
    public:
     WorkerContainer() = default;
 
-    void AddWorker(scoped_refptr<SchedulerWorker> worker) {
+    void AddWorker(scoped_refptr<WorkerThread> worker) {
       if (!worker)
         return;
       if (!first_worker_)
@@ -149,7 +149,7 @@
     void ForEachWorker(Action action) {
       if (first_worker_) {
         action(first_worker_.get());
-        for (scoped_refptr<SchedulerWorker> worker : additional_workers_)
+        for (scoped_refptr<WorkerThread> worker : additional_workers_)
           action(worker.get());
       } else {
         DCHECK(additional_workers_.empty());
@@ -166,8 +166,8 @@
    private:
     // The purpose of |first_worker| is to avoid a heap allocation by the vector
     // in the case where there is only one worker in the container.
-    scoped_refptr<SchedulerWorker> first_worker_;
-    std::vector<scoped_refptr<SchedulerWorker>> additional_workers_;
+    scoped_refptr<WorkerThread> first_worker_;
+    std::vector<scoped_refptr<WorkerThread>> additional_workers_;
 
     DISALLOW_COPY_AND_ASSIGN(WorkerContainer);
   };
@@ -177,20 +177,20 @@
 
     // Wake up workers.
     workers_to_wake_up_.ForEachWorker(
-        [](SchedulerWorker* worker) { worker->WakeUp(); });
+        [](WorkerThread* worker) { worker->WakeUp(); });
 
     // Start workers. Happens after wake ups to prevent the case where a worker
     // enters its main function, is descheduled because it wasn't woken up yet,
     // and is woken up immediately after.
-    workers_to_start_.ForEachWorker([&](SchedulerWorker* worker) {
-      worker->Start(outer_->after_start().scheduler_worker_observer);
+    workers_to_start_.ForEachWorker([&](WorkerThread* worker) {
+      worker->Start(outer_->after_start().worker_thread_observer);
     });
 
     if (must_schedule_adjust_max_tasks_)
       outer_->ScheduleAdjustMaxTasks();
   }
 
-  SchedulerWorkerPoolImpl* const outer_;
+  ThreadGroupImpl* const outer_;
 
   WorkerContainer workers_to_wake_up_;
   WorkerContainer workers_to_start_;
@@ -199,21 +199,20 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedWorkersExecutor);
 };
 
-class SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl
-    : public SchedulerWorker::Delegate,
-      public BlockingObserver {
+class ThreadGroupImpl::WorkerThreadDelegateImpl : public WorkerThread::Delegate,
+                                                  public BlockingObserver {
  public:
   // |outer| owns the worker for which this delegate is constructed.
-  SchedulerWorkerDelegateImpl(TrackedRef<SchedulerWorkerPoolImpl> outer);
-  ~SchedulerWorkerDelegateImpl() override;
+  WorkerThreadDelegateImpl(TrackedRef<ThreadGroupImpl> outer);
+  ~WorkerThreadDelegateImpl() override;
 
-  // SchedulerWorker::Delegate:
-  SchedulerWorker::ThreadLabel GetThreadLabel() const override;
-  void OnMainEntry(const SchedulerWorker* worker) override;
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override;
+  // WorkerThread::Delegate:
+  WorkerThread::ThreadLabel GetThreadLabel() const override;
+  void OnMainEntry(const WorkerThread* worker) override;
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override;
   void DidRunTask(scoped_refptr<TaskSource> task_source) override;
   TimeDelta GetSleepTimeout() override;
-  void OnMainExit(SchedulerWorker* worker) override;
+  void OnMainExit(WorkerThread* worker) override;
 
   // BlockingObserver:
   void BlockingStarted(BlockingType blocking_type) override;
@@ -225,7 +224,7 @@
 
   // Returns true iff the worker can get work. Cleans up the worker or puts it
   // on the idle stack if it can't get work.
-  bool CanGetWorkLockRequired(SchedulerWorker* worker)
+  bool CanGetWorkLockRequired(WorkerThread* worker)
       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
 
   // Returns true iff this worker has been within a MAY_BLOCK ScopedBlockingCall
@@ -240,7 +239,7 @@
   }
 
   // Exposed for AnnotateCheckedLockAcquired in
-  // SchedulerWorkerPoolImpl::AdjustMaxTasks()
+  // ThreadGroupImpl::AdjustMaxTasks()
   const CheckedLock& lock() const LOCK_RETURNED(outer_->lock_) {
     return outer_->lock_;
   }
@@ -248,17 +247,17 @@
  private:
   // Returns true if |worker| is allowed to cleanup and remove itself from the
   // pool. Called from GetWork() when no work is available.
-  bool CanCleanupLockRequired(const SchedulerWorker* worker) const
+  bool CanCleanupLockRequired(const WorkerThread* worker) const
       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
 
   // Calls cleanup on |worker| and removes it from the pool. Called from
   // GetWork() when no work is available and CanCleanupLockRequired() returns
   // true.
-  void CleanupLockRequired(SchedulerWorker* worker)
+  void CleanupLockRequired(WorkerThread* worker)
       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
 
   // Called in GetWork() when a worker becomes idle.
-  void OnWorkerBecomesIdleLockRequired(SchedulerWorker* worker)
+  void OnWorkerBecomesIdleLockRequired(WorkerThread* worker)
       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
 
   // Accessed only from the worker thread.
@@ -312,7 +311,7 @@
     return write_worker_read_any_;
   }
 
-  const TrackedRef<SchedulerWorkerPoolImpl> outer_;
+  const TrackedRef<ThreadGroupImpl> outer_;
 
   // Whether |outer_->max_tasks_| was incremented due to a ScopedBlockingCall on
   // the thread.
@@ -321,16 +320,15 @@
   // Verifies that specific calls are always made from the worker thread.
   THREAD_CHECKER(worker_thread_checker_);
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegateImpl);
+  DISALLOW_COPY_AND_ASSIGN(WorkerThreadDelegateImpl);
 };
 
-SchedulerWorkerPoolImpl::SchedulerWorkerPoolImpl(
-    StringPiece histogram_label,
-    StringPiece pool_label,
-    ThreadPriority priority_hint,
-    TrackedRef<TaskTracker> task_tracker,
-    TrackedRef<Delegate> delegate)
-    : SchedulerWorkerPool(std::move(task_tracker), std::move(delegate)),
+ThreadGroupImpl::ThreadGroupImpl(StringPiece histogram_label,
+                                 StringPiece pool_label,
+                                 ThreadPriority priority_hint,
+                                 TrackedRef<TaskTracker> task_tracker,
+                                 TrackedRef<Delegate> delegate)
+    : ThreadGroup(std::move(task_tracker), std::move(delegate)),
       pool_label_(pool_label.as_string()),
       priority_hint_(priority_hint),
       idle_workers_stack_cv_for_testing_(lock_.CreateConditionVariable()),
@@ -351,7 +349,7 @@
           1000,
           50,
           HistogramBase::kUmaTargetedHistogramFlag)),
-      // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A SchedulerWorker is
+      // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A WorkerThread is
       // expected to run between zero and a few tens of tasks between waits.
       // When it runs more than 100 tasks, there is no need to know the exact
       // number of tasks that ran.
@@ -362,7 +360,7 @@
           100,
           50,
           HistogramBase::kUmaTargetedHistogramFlag)),
-      // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A SchedulerWorkerPool is
+      // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A ThreadGroup is
       // expected to run between zero and a few tens of workers.
       // When it runs more than 100 worker, there is no need to know the exact
       // number of workers that ran.
@@ -383,11 +381,11 @@
   DCHECK(!pool_label_.empty());
 }
 
-void SchedulerWorkerPoolImpl::Start(
-    const SchedulerWorkerPoolParams& params,
+void ThreadGroupImpl::Start(
+    const ThreadGroupParams& params,
     int max_best_effort_tasks,
     scoped_refptr<TaskRunner> service_thread_task_runner,
-    SchedulerWorkerObserver* scheduler_worker_observer,
+    WorkerThreadObserver* worker_thread_observer,
     WorkerEnvironment worker_environment,
     Optional<TimeDelta> may_block_threshold) {
   DCHECK(!replacement_pool_);
@@ -418,7 +416,7 @@
   in_start().backward_compatibility = params.backward_compatibility();
   in_start().worker_environment = worker_environment;
   in_start().service_thread_task_runner = std::move(service_thread_task_runner);
-  in_start().scheduler_worker_observer = scheduler_worker_observer;
+  in_start().worker_thread_observer = worker_thread_observer;
 
 #if DCHECK_IS_ON()
   in_start().initialized = true;
@@ -427,29 +425,28 @@
   EnsureEnoughWorkersLockRequired(&executor);
 }
 
-SchedulerWorkerPoolImpl::~SchedulerWorkerPoolImpl() {
-  // SchedulerWorkerPool should only ever be deleted:
+ThreadGroupImpl::~ThreadGroupImpl() {
+  // ThreadGroup should only ever be deleted:
   //  1) In tests, after JoinForTesting().
   //  2) In production, iff initialization failed.
   // In both cases |workers_| should be empty.
   DCHECK(workers_.empty());
 }
 
-void SchedulerWorkerPoolImpl::UpdateSortKey(
+void ThreadGroupImpl::UpdateSortKey(
     TaskSourceAndTransaction task_source_and_transaction) {
   ScopedWorkersExecutor executor(this);
   UpdateSortKeyImpl(&executor, std::move(task_source_and_transaction));
 }
 
-void SchedulerWorkerPoolImpl::PushTaskSourceAndWakeUpWorkers(
+void ThreadGroupImpl::PushTaskSourceAndWakeUpWorkers(
     TaskSourceAndTransaction task_source_and_transaction) {
   ScopedWorkersExecutor executor(this);
   PushTaskSourceAndWakeUpWorkersImpl(&executor,
                                      std::move(task_source_and_transaction));
 }
 
-size_t SchedulerWorkerPoolImpl::GetMaxConcurrentNonBlockedTasksDeprecated()
-    const {
+size_t ThreadGroupImpl::GetMaxConcurrentNonBlockedTasksDeprecated() const {
 #if DCHECK_IS_ON()
   CheckedAutoLock auto_lock(lock_);
   DCHECK_NE(after_start().initial_max_tasks, 0U)
@@ -459,7 +456,7 @@
   return after_start().initial_max_tasks;
 }
 
-void SchedulerWorkerPoolImpl::WaitForWorkersIdleForTesting(size_t n) {
+void ThreadGroupImpl::WaitForWorkersIdleForTesting(size_t n) {
   CheckedAutoLock auto_lock(lock_);
 
 #if DCHECK_IS_ON()
@@ -472,12 +469,12 @@
   WaitForWorkersIdleLockRequiredForTesting(n);
 }
 
-void SchedulerWorkerPoolImpl::WaitForAllWorkersIdleForTesting() {
+void ThreadGroupImpl::WaitForAllWorkersIdleForTesting() {
   CheckedAutoLock auto_lock(lock_);
   WaitForWorkersIdleLockRequiredForTesting(workers_.size());
 }
 
-void SchedulerWorkerPoolImpl::WaitForWorkersCleanedUpForTesting(size_t n) {
+void ThreadGroupImpl::WaitForWorkersCleanedUpForTesting(size_t n) {
   CheckedAutoLock auto_lock(lock_);
 
   if (!num_workers_cleaned_up_for_testing_cv_)
@@ -489,7 +486,7 @@
   num_workers_cleaned_up_for_testing_ = 0;
 }
 
-void SchedulerWorkerPoolImpl::JoinForTesting() {
+void ThreadGroupImpl::JoinForTesting() {
 #if DCHECK_IS_ON()
   join_for_testing_started_.Set();
 #endif
@@ -501,13 +498,13 @@
 
     DCHECK_GT(workers_.size(), size_t(0)) << "Joined an unstarted worker pool.";
 
-    // Ensure SchedulerWorkers in |workers_| do not attempt to cleanup while
+    // Ensure WorkerThreads in |workers_| do not attempt to cleanup while
     // being joined.
     worker_cleanup_disallowed_for_testing_ = true;
 
-    // Make a copy of the SchedulerWorkers so that we can call
-    // SchedulerWorker::JoinForTesting() without holding |lock_| since
-    // SchedulerWorkers may need to access |workers_|.
+    // Make a copy of the WorkerThreads so that we can call
+    // WorkerThread::JoinForTesting() without holding |lock_| since
+    // WorkerThreads may need to access |workers_|.
     workers_copy = workers_;
   }
   for (const auto& worker : workers_copy)
@@ -519,22 +516,22 @@
   workers_.clear();
 }
 
-size_t SchedulerWorkerPoolImpl::NumberOfWorkersForTesting() const {
+size_t ThreadGroupImpl::NumberOfWorkersForTesting() const {
   CheckedAutoLock auto_lock(lock_);
   return workers_.size();
 }
 
-size_t SchedulerWorkerPoolImpl::GetMaxTasksForTesting() const {
+size_t ThreadGroupImpl::GetMaxTasksForTesting() const {
   CheckedAutoLock auto_lock(lock_);
   return max_tasks_;
 }
 
-size_t SchedulerWorkerPoolImpl::NumberOfIdleWorkersForTesting() const {
+size_t ThreadGroupImpl::NumberOfIdleWorkersForTesting() const {
   CheckedAutoLock auto_lock(lock_);
   return idle_workers_stack_.Size();
 }
 
-void SchedulerWorkerPoolImpl::ReportHeartbeatMetrics() const {
+void ThreadGroupImpl::ReportHeartbeatMetrics() const {
   CheckedAutoLock auto_lock(lock_);
   num_workers_histogram_->Add(workers_.size());
 
@@ -542,25 +539,25 @@
                                      idle_workers_stack_.Size());
 }
 
-SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    SchedulerWorkerDelegateImpl(TrackedRef<SchedulerWorkerPoolImpl> outer)
+ThreadGroupImpl::WorkerThreadDelegateImpl::WorkerThreadDelegateImpl(
+    TrackedRef<ThreadGroupImpl> outer)
     : outer_(std::move(outer)) {
   // Bound in OnMainEntry().
   DETACH_FROM_THREAD(worker_thread_checker_);
 }
 
-// OnMainExit() handles the thread-affine cleanup; SchedulerWorkerDelegateImpl
+// OnMainExit() handles the thread-affine cleanup; WorkerThreadDelegateImpl
 // can thereafter safely be deleted from any thread.
-SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    ~SchedulerWorkerDelegateImpl() = default;
+ThreadGroupImpl::WorkerThreadDelegateImpl::~WorkerThreadDelegateImpl() =
+    default;
 
-SchedulerWorker::ThreadLabel
-SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetThreadLabel() const {
-  return SchedulerWorker::ThreadLabel::POOLED;
+WorkerThread::ThreadLabel
+ThreadGroupImpl::WorkerThreadDelegateImpl::GetThreadLabel() const {
+  return WorkerThread::ThreadLabel::POOLED;
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::OnMainEntry(
-    const SchedulerWorker* worker) {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::OnMainEntry(
+    const WorkerThread* worker) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
 
   {
@@ -593,9 +590,8 @@
   SetBlockingObserverForCurrentThread(this);
 }
 
-scoped_refptr<TaskSource>
-SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetWork(
-    SchedulerWorker* worker) {
+scoped_refptr<TaskSource> ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork(
+    WorkerThread* worker) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(!worker_only().is_running_task);
   DCHECK(!read_worker().is_running_best_effort_task);
@@ -650,7 +646,7 @@
   return outer_->priority_queue_.PopTaskSource();
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::DidRunTask(
+void ThreadGroupImpl::WorkerThreadDelegateImpl::DidRunTask(
     scoped_refptr<TaskSource> task_source) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
@@ -693,8 +689,7 @@
   }
 }
 
-TimeDelta
-SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::GetSleepTimeout() {
+TimeDelta ThreadGroupImpl::WorkerThreadDelegateImpl::GetSleepTimeout() {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   // Sleep for an extra 10% to avoid the following pathological case:
 
@@ -728,8 +723,8 @@
   return outer_->after_start().suggested_reclaim_time * 1.1;
 }
 
-bool SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    CanCleanupLockRequired(const SchedulerWorker* worker) const {
+bool ThreadGroupImpl::WorkerThreadDelegateImpl::CanCleanupLockRequired(
+    const WorkerThread* worker) const {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
 
   const TimeTicks last_used_time = worker->GetLastUsedTime();
@@ -741,8 +736,8 @@
          LIKELY(!outer_->worker_cleanup_disallowed_for_testing_);
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::CleanupLockRequired(
-    SchedulerWorker* worker) {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::CleanupLockRequired(
+    WorkerThread* worker) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
 
   outer_->num_tasks_before_detach_histogram_->Add(
@@ -765,12 +760,12 @@
     outer_->num_workers_cleaned_up_for_testing_cv_->Signal();
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    OnWorkerBecomesIdleLockRequired(SchedulerWorker* worker) {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::OnWorkerBecomesIdleLockRequired(
+    WorkerThread* worker) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
 
   // Record the ThreadPool.NumTasksBetweenWaits histogram. After GetWork()
-  // returns nullptr, the SchedulerWorker will perform a wait on its
+  // returns nullptr, the WorkerThread will perform a wait on its
   // WaitableEvent, so we record how many tasks were ran since the last wait
   // here.
   outer_->num_tasks_between_waits_histogram_->Add(
@@ -784,8 +779,8 @@
   outer_->idle_workers_stack_cv_for_testing_->Broadcast();
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::OnMainExit(
-    SchedulerWorker* worker) {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::OnMainExit(
+    WorkerThread* worker) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
 
 #if DCHECK_IS_ON()
@@ -809,7 +804,7 @@
 #endif  // defined(OS_WIN)
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::BlockingStarted(
+void ThreadGroupImpl::WorkerThreadDelegateImpl::BlockingStarted(
     BlockingType blocking_type) {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
@@ -828,8 +823,7 @@
   }
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    BlockingTypeUpgraded() {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::BlockingTypeUpgraded() {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
 
@@ -859,7 +853,7 @@
   WillBlockEntered();
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::BlockingEnded() {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::BlockingEnded() {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
 
@@ -878,7 +872,7 @@
   write_worker().may_block_start_time = TimeTicks();
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::MayBlockEntered() {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::MayBlockEntered() {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
 
@@ -895,7 +889,7 @@
   outer_->MaybeScheduleAdjustMaxTasksLockRequired(&executor);
 }
 
-void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::WillBlockEntered() {
+void ThreadGroupImpl::WorkerThreadDelegateImpl::WillBlockEntered() {
   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_only().is_running_task);
 
@@ -910,8 +904,8 @@
   outer_->EnsureEnoughWorkersLockRequired(&executor);
 }
 
-bool SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
-    CanGetWorkLockRequired(SchedulerWorker* worker) {
+bool ThreadGroupImpl::WorkerThreadDelegateImpl::CanGetWorkLockRequired(
+    WorkerThread* worker) {
   // To avoid searching through the idle stack : use GetLastUsedTime() not being
   // null (or being directly on top of the idle stack) as a proxy for being on
   // the idle stack.
@@ -939,7 +933,7 @@
   return true;
 }
 
-bool SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
+bool ThreadGroupImpl::WorkerThreadDelegateImpl::
     MustIncrementMaxTasksLockRequired() {
   if (!incremented_max_tasks_since_blocked_ &&
       !read_any().may_block_start_time.is_null() &&
@@ -957,8 +951,7 @@
   return false;
 }
 
-void SchedulerWorkerPoolImpl::WaitForWorkersIdleLockRequiredForTesting(
-    size_t n) {
+void ThreadGroupImpl::WaitForWorkersIdleLockRequiredForTesting(size_t n) {
   // Make sure workers do not cleanup while watching the idle count.
   AutoReset<bool> ban_cleanups(&worker_cleanup_disallowed_for_testing_, true);
 
@@ -966,7 +959,7 @@
     idle_workers_stack_cv_for_testing_->Wait();
 }
 
-void SchedulerWorkerPoolImpl::MaintainAtLeastOneIdleWorkerLockRequired(
+void ThreadGroupImpl::MaintainAtLeastOneIdleWorkerLockRequired(
     ScopedWorkersExecutor* executor) {
   if (workers_.size() == kMaxNumberOfWorkers)
     return;
@@ -978,25 +971,25 @@
   if (workers_.size() >= max_tasks_)
     return;
 
-  scoped_refptr<SchedulerWorker> new_worker =
+  scoped_refptr<WorkerThread> new_worker =
       CreateAndRegisterWorkerLockRequired(executor);
   DCHECK(new_worker);
   idle_workers_stack_.Push(new_worker.get());
 }
 
-scoped_refptr<SchedulerWorker>
-SchedulerWorkerPoolImpl::CreateAndRegisterWorkerLockRequired(
+scoped_refptr<WorkerThread>
+ThreadGroupImpl::CreateAndRegisterWorkerLockRequired(
     ScopedWorkersExecutor* executor) {
   DCHECK_LT(workers_.size(), max_tasks_);
   DCHECK_LT(workers_.size(), kMaxNumberOfWorkers);
   DCHECK(idle_workers_stack_.IsEmpty());
 
-  // SchedulerWorker needs |lock_| as a predecessor for its thread lock
+  // WorkerThread needs |lock_| as a predecessor for its thread lock
   // because in WakeUpOneWorker, |lock_| is first acquired and then
   // the thread lock is acquired when WakeUp is called on the worker.
-  scoped_refptr<SchedulerWorker> worker = MakeRefCounted<SchedulerWorker>(
+  scoped_refptr<WorkerThread> worker = MakeRefCounted<WorkerThread>(
       priority_hint_,
-      std::make_unique<SchedulerWorkerDelegateImpl>(
+      std::make_unique<WorkerThreadDelegateImpl>(
           tracked_ref_factory_.GetTrackedRef()),
       task_tracker_, &lock_, after_start().backward_compatibility);
 
@@ -1013,14 +1006,14 @@
   return worker;
 }
 
-size_t SchedulerWorkerPoolImpl::GetNumAwakeWorkersLockRequired() const {
+size_t ThreadGroupImpl::GetNumAwakeWorkersLockRequired() const {
   DCHECK_GE(workers_.size(), idle_workers_stack_.Size());
   size_t num_awake_workers = workers_.size() - idle_workers_stack_.Size();
   DCHECK_GE(num_awake_workers, num_running_tasks_);
   return num_awake_workers;
 }
 
-size_t SchedulerWorkerPoolImpl::GetDesiredNumAwakeWorkersLockRequired() const {
+size_t ThreadGroupImpl::GetDesiredNumAwakeWorkersLockRequired() const {
   // Number of BEST_EFFORT task sources that are running or queued and allowed
   // to run by the CanRunPolicy.
   const size_t num_running_or_queued_can_run_best_effort_task_sources =
@@ -1045,13 +1038,13 @@
                    max_tasks_, kMaxNumberOfWorkers});
 }
 
-void SchedulerWorkerPoolImpl::DidUpdateCanRunPolicy() {
+void ThreadGroupImpl::DidUpdateCanRunPolicy() {
   ScopedWorkersExecutor executor(this);
   CheckedAutoLock auto_lock(lock_);
   EnsureEnoughWorkersLockRequired(&executor);
 }
 
-void SchedulerWorkerPoolImpl::EnsureEnoughWorkersLockRequired(
+void ThreadGroupImpl::EnsureEnoughWorkersLockRequired(
     BaseScopedWorkersExecutor* base_executor) {
   // Don't do anything if the pool isn't started.
   if (max_tasks_ == 0)
@@ -1071,7 +1064,7 @@
   // Wake up the appropriate number of workers.
   for (size_t i = 0; i < num_workers_to_wake_up; ++i) {
     MaintainAtLeastOneIdleWorkerLockRequired(executor);
-    SchedulerWorker* worker_to_wakeup = idle_workers_stack_.Pop();
+    WorkerThread* worker_to_wakeup = idle_workers_stack_.Pop();
     DCHECK(worker_to_wakeup);
     executor->ScheduleWakeUp(worker_to_wakeup);
   }
@@ -1087,7 +1080,7 @@
   MaybeScheduleAdjustMaxTasksLockRequired(executor);
 }
 
-void SchedulerWorkerPoolImpl::AdjustMaxTasks() {
+void ThreadGroupImpl::AdjustMaxTasks() {
   DCHECK(
       after_start().service_thread_task_runner->RunsTasksInCurrentSequence());
 
@@ -1098,11 +1091,11 @@
 
   // Increment max tasks for each worker that has been within a MAY_BLOCK
   // ScopedBlockingCall for more than may_block_threshold.
-  for (scoped_refptr<SchedulerWorker> worker : workers_) {
-    // The delegates of workers inside a SchedulerWorkerPoolImpl should be
-    // SchedulerWorkerDelegateImpls.
-    SchedulerWorkerDelegateImpl* delegate =
-        static_cast<SchedulerWorkerDelegateImpl*>(worker->delegate());
+  for (scoped_refptr<WorkerThread> worker : workers_) {
+    // The delegates of workers inside a ThreadGroupImpl should be
+    // WorkerThreadDelegateImpls.
+    WorkerThreadDelegateImpl* delegate =
+        static_cast<WorkerThreadDelegateImpl*>(worker->delegate());
     AnnotateAcquiredLockAlias annotate(lock_, delegate->lock());
     if (delegate->MustIncrementMaxTasksLockRequired()) {
       IncrementMaxTasksLockRequired(
@@ -1115,7 +1108,7 @@
   EnsureEnoughWorkersLockRequired(&executor);
 }
 
-void SchedulerWorkerPoolImpl::ScheduleAdjustMaxTasks() {
+void ThreadGroupImpl::ScheduleAdjustMaxTasks() {
   // |adjust_max_tasks_posted_| can't change before the task posted below runs.
   // Skip check on NaCl to avoid unsafe reference acquisition warning.
 #if !defined(OS_NACL)
@@ -1123,12 +1116,11 @@
 #endif
 
   after_start().service_thread_task_runner->PostDelayedTask(
-      FROM_HERE,
-      BindOnce(&SchedulerWorkerPoolImpl::AdjustMaxTasks, Unretained(this)),
+      FROM_HERE, BindOnce(&ThreadGroupImpl::AdjustMaxTasks, Unretained(this)),
       after_start().blocked_workers_poll_period);
 }
 
-void SchedulerWorkerPoolImpl::MaybeScheduleAdjustMaxTasksLockRequired(
+void ThreadGroupImpl::MaybeScheduleAdjustMaxTasksLockRequired(
     ScopedWorkersExecutor* executor) {
   if (!adjust_max_tasks_posted_ &&
       ShouldPeriodicallyAdjustMaxTasksLockRequired()) {
@@ -1137,7 +1129,7 @@
   }
 }
 
-bool SchedulerWorkerPoolImpl::ShouldPeriodicallyAdjustMaxTasksLockRequired() {
+bool ThreadGroupImpl::ShouldPeriodicallyAdjustMaxTasksLockRequired() {
   // AdjustMaxTasks() should be scheduled to periodically adjust |max_tasks_|
   // and |max_best_effort_tasks_| when (1) the concurrency limits are not large
   // enough to accommodate all queued and running task sources and an idle
@@ -1162,22 +1154,22 @@
          num_unresolved_may_block_ > 0;
 }
 
-void SchedulerWorkerPoolImpl::DecrementMaxTasksLockRequired(
+void ThreadGroupImpl::DecrementMaxTasksLockRequired(
     bool is_running_best_effort_task) {
   --max_tasks_;
   if (is_running_best_effort_task)
     --max_best_effort_tasks_;
 }
 
-void SchedulerWorkerPoolImpl::IncrementMaxTasksLockRequired(
+void ThreadGroupImpl::IncrementMaxTasksLockRequired(
     bool is_running_best_effort_task) {
   ++max_tasks_;
   if (is_running_best_effort_task)
     ++max_best_effort_tasks_;
 }
 
-SchedulerWorkerPoolImpl::InitializedInStart::InitializedInStart() = default;
-SchedulerWorkerPoolImpl::InitializedInStart::~InitializedInStart() = default;
+ThreadGroupImpl::InitializedInStart::InitializedInStart() = default;
+ThreadGroupImpl::InitializedInStart::~InitializedInStart() = default;
 
 }  // namespace internal
 }  // namespace base
diff --git a/base/task/thread_pool/scheduler_worker_pool_impl.h b/base/task/thread_pool/thread_group_impl.h
similarity index 86%
rename from base/task/thread_pool/scheduler_worker_pool_impl.h
rename to base/task/thread_pool/thread_group_impl.h
index 7af46ef..418c701 100644
--- a/base/task/thread_pool/scheduler_worker_pool_impl.h
+++ b/base/task/thread_pool/thread_group_impl.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 BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_IMPL_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_IMPL_H_
+#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_IMPL_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_IMPL_H_
 
 #include <stddef.h>
 
@@ -23,20 +23,20 @@
 #include "base/synchronization/atomic_flag.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/task/thread_pool/scheduler_worker.h"
-#include "base/task/thread_pool/scheduler_worker_pool.h"
-#include "base/task/thread_pool/scheduler_worker_stack.h"
 #include "base/task/thread_pool/task.h"
 #include "base/task/thread_pool/task_source.h"
+#include "base/task/thread_pool/thread_group.h"
 #include "base/task/thread_pool/tracked_ref.h"
+#include "base/task/thread_pool/worker_thread.h"
+#include "base/task/thread_pool/worker_thread_stack.h"
 #include "base/task_runner.h"
 #include "base/time/time.h"
 
 namespace base {
 
 class HistogramBase;
-class SchedulerWorkerObserver;
-class SchedulerWorkerPoolParams;
+class WorkerThreadObserver;
+class ThreadGroupParams;
 
 namespace internal {
 
@@ -48,7 +48,7 @@
 // at any time but will not run until after Start() is called.
 //
 // This class is thread-safe.
-class BASE_EXPORT SchedulerWorkerPoolImpl : public SchedulerWorkerPool {
+class BASE_EXPORT ThreadGroupImpl : public ThreadGroup {
  public:
   // Constructs a pool without workers.
   //
@@ -58,36 +58,36 @@
   // empty. |priority_hint| is the preferred thread priority; the actual thread
   // priority depends on shutdown state and platform capabilities.
   // |task_tracker| keeps track of tasks.
-  SchedulerWorkerPoolImpl(StringPiece histogram_label,
-                          StringPiece pool_label,
-                          ThreadPriority priority_hint,
-                          TrackedRef<TaskTracker> task_tracker,
-                          TrackedRef<Delegate> delegate);
+  ThreadGroupImpl(StringPiece histogram_label,
+                  StringPiece pool_label,
+                  ThreadPriority priority_hint,
+                  TrackedRef<TaskTracker> task_tracker,
+                  TrackedRef<Delegate> delegate);
 
   // Creates workers following the |params| specification, allowing existing and
   // future tasks to run. The pool runs at most |max_best_effort_tasks|
   // unblocked BEST_EFFORT tasks concurrently, uses |service_thread_task_runner|
   // to monitor for blocked tasks, and, if specified, notifies
-  // |scheduler_worker_observer| when a worker enters and exits its main
+  // |worker_thread_observer| when a worker enters and exits its main
   // function (the observer must not be destroyed before JoinForTesting() has
   // returned). |worker_environment| specifies the environment in which tasks
   // are executed. |may_block_threshold| is the timeout after which a task in a
   // MAY_BLOCK ScopedBlockingCall is considered blocked (the pool will choose an
   // appropriate value if none is specified). Can only be called once. CHECKs on
   // failure.
-  void Start(const SchedulerWorkerPoolParams& params,
+  void Start(const ThreadGroupParams& params,
              int max_best_effort_tasks,
              scoped_refptr<TaskRunner> service_thread_task_runner,
-             SchedulerWorkerObserver* scheduler_worker_observer,
+             WorkerThreadObserver* worker_thread_observer,
              WorkerEnvironment worker_environment,
              Optional<TimeDelta> may_block_threshold = Optional<TimeDelta>());
 
-  // Destroying a SchedulerWorkerPoolImpl returned by Create() is not allowed in
+  // Destroying a ThreadGroupImpl returned by Create() is not allowed in
   // production; it is always leaked. In tests, it can only be destroyed after
   // JoinForTesting() has returned.
-  ~SchedulerWorkerPoolImpl() override;
+  ~ThreadGroupImpl() override;
 
-  // SchedulerWorkerPool:
+  // ThreadGroup:
   void JoinForTesting() override;
   size_t GetMaxConcurrentNonBlockedTasksDeprecated() const override;
   void ReportHeartbeatMetrics() const override;
@@ -135,16 +135,16 @@
 
  private:
   class ScopedWorkersExecutor;
-  class SchedulerWorkerDelegateImpl;
+  class WorkerThreadDelegateImpl;
 
   // Friend tests so that they can access |blocked_workers_poll_period| and
   // may_block_threshold().
-  friend class ThreadPoolWorkerPoolBlockingTest;
-  friend class ThreadPoolWorkerPoolMayBlockTest;
-  FRIEND_TEST_ALL_PREFIXES(ThreadPoolWorkerPoolBlockingTest,
+  friend class ThreadGroupImplBlockingTest;
+  friend class ThreadGroupImplMayBlockTest;
+  FRIEND_TEST_ALL_PREFIXES(ThreadGroupImplBlockingTest,
                            ThreadBlockUnblockPremature);
 
-  // SchedulerWorkerPool:
+  // ThreadGroup:
   void UpdateSortKey(
       TaskSourceAndTransaction task_source_and_transaction) override;
   void PushTaskSourceAndWakeUpWorkers(
@@ -162,7 +162,7 @@
 
   // Creates a worker, adds it to the pool, schedules its start and returns it.
   // Cannot be called before Start().
-  scoped_refptr<SchedulerWorker> CreateAndRegisterWorkerLockRequired(
+  scoped_refptr<WorkerThread> CreateAndRegisterWorkerLockRequired(
       ScopedWorkersExecutor* executor) EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
   // Returns the number of workers that are awake (i.e. not on the idle stack).
@@ -173,7 +173,7 @@
   size_t GetDesiredNumAwakeWorkersLockRequired() const
       EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
-  // Examines the list of SchedulerWorkers and increments |max_tasks_| for each
+  // Examines the list of WorkerThreads and increments |max_tasks_| for each
   // worker that has been within the scope of a MAY_BLOCK ScopedBlockingCall for
   // more than BlockedThreshold(). Reschedules a call if necessary.
   void AdjustMaxTasks();
@@ -228,7 +228,7 @@
     // Suggested reclaim time for workers.
     TimeDelta suggested_reclaim_time;
 
-    SchedulerBackwardCompatibility backward_compatibility;
+    WorkerThreadBackwardCompatibility backward_compatibility;
 
     // Environment to be initialized per worker.
     WorkerEnvironment worker_environment = WorkerEnvironment::NONE;
@@ -236,7 +236,7 @@
     scoped_refptr<TaskRunner> service_thread_task_runner;
 
     // Optional observer notified when a worker enters and exits its main.
-    SchedulerWorkerObserver* scheduler_worker_observer = nullptr;
+    WorkerThreadObserver* worker_thread_observer = nullptr;
 
     bool may_block_without_delay;
 
@@ -266,7 +266,7 @@
   const ThreadPriority priority_hint_;
 
   // All workers owned by this worker pool.
-  std::vector<scoped_refptr<SchedulerWorker>> workers_ GUARDED_BY(lock_);
+  std::vector<scoped_refptr<WorkerThread>> workers_ GUARDED_BY(lock_);
 
   // Maximum number of tasks of any priority / BEST_EFFORT priority that can run
   // concurrently in this pool.
@@ -289,7 +289,7 @@
   // it receives work from GetWork() (a worker calls GetWork() when its sleep
   // timeout expires, even if its WakeUp() method hasn't been called). A worker
   // is pushed on this stack when it receives nullptr from GetWork().
-  SchedulerWorkerStack idle_workers_stack_ GUARDED_BY(lock_);
+  WorkerThreadStack idle_workers_stack_ GUARDED_BY(lock_);
 
   // Signaled when a worker is added to the idle workers stack.
   std::unique_ptr<ConditionVariable> idle_workers_stack_cv_for_testing_
@@ -348,18 +348,18 @@
   HistogramBase* const num_active_workers_histogram_;
 
   // Ensures recently cleaned up workers (ref.
-  // SchedulerWorkerDelegateImpl::CleanupLockRequired()) had time to exit as
+  // WorkerThreadDelegateImpl::CleanupLockRequired()) had time to exit as
   // they have a raw reference to |this| (and to TaskTracker) which can
   // otherwise result in racy use-after-frees per no longer being part of
   // |workers_| and hence not being explicitly joined in JoinForTesting():
   // https://crbug.com/810464. Uses AtomicRefCount to make its only public
   // method thread-safe.
-  TrackedRefFactory<SchedulerWorkerPoolImpl> tracked_ref_factory_;
+  TrackedRefFactory<ThreadGroupImpl> tracked_ref_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolImpl);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImpl);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_POOL_IMPL_H_
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_IMPL_H_
diff --git a/base/task/thread_pool/scheduler_worker_pool_impl_unittest.cc b/base/task/thread_pool/thread_group_impl_unittest.cc
similarity index 75%
rename from base/task/thread_pool/scheduler_worker_pool_impl_unittest.cc
rename to base/task/thread_pool/thread_group_impl_unittest.cc
index 4446a1ed..2f09337 100644
--- a/base/task/thread_pool/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task/thread_pool/thread_group_impl_unittest.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 "base/task/thread_pool/scheduler_worker_pool_impl.h"
+#include "base/task/thread_pool/thread_group_impl.h"
 
 #include <stddef.h>
 
@@ -29,14 +29,14 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/task/task_features.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
-#include "base/task/thread_pool/scheduler_worker_observer.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
 #include "base/task/thread_pool/sequence.h"
 #include "base/task/thread_pool/sequence_sort_key.h"
 #include "base/task/thread_pool/task_tracker.h"
 #include "base/task/thread_pool/test_task_factory.h"
 #include "base/task/thread_pool/test_utils.h"
+#include "base/task/thread_pool/thread_group_params.h"
+#include "base/task/thread_pool/worker_thread_observer.h"
 #include "base/task_runner.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/gtest_util.h"
@@ -69,123 +69,118 @@
     TimeDelta::FromMilliseconds(500);
 constexpr size_t kLargeNumber = 512;
 
-class ThreadPoolWorkerPoolImplTestBase : public SchedulerWorkerPool::Delegate {
+class ThreadGroupImplImplTestBase : public ThreadGroup::Delegate {
  protected:
-  ThreadPoolWorkerPoolImplTestBase()
+  ThreadGroupImplImplTestBase()
       : service_thread_("ThreadPoolServiceThread"),
         tracked_ref_factory_(this) {}
 
   void CommonTearDown() {
     service_thread_.Stop();
     task_tracker_.FlushForTesting();
-    if (worker_pool_)
-      worker_pool_->JoinForTesting();
-    worker_pool_.reset();
+    if (thread_group_)
+      thread_group_->JoinForTesting();
+    thread_group_.reset();
   }
 
-  void CreateWorkerPool() {
-    ASSERT_FALSE(worker_pool_);
+  void CreateThreadGroup() {
+    ASSERT_FALSE(thread_group_);
     service_thread_.Start();
     delayed_task_manager_.Start(service_thread_.task_runner());
-    worker_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
-        "TestWorkerPool", "A", ThreadPriority::NORMAL,
+    thread_group_ = std::make_unique<ThreadGroupImpl>(
+        "TestThreadGroup", "A", ThreadPriority::NORMAL,
         task_tracker_.GetTrackedRef(), tracked_ref_factory_.GetTrackedRef());
-    ASSERT_TRUE(worker_pool_);
+    ASSERT_TRUE(thread_group_);
 
-    mock_scheduler_task_runner_delegate_.SetWorkerPool(worker_pool_.get());
+    mock_pooled_task_runner_delegate_.SetThreadGroup(thread_group_.get());
   }
 
-  void StartWorkerPool(TimeDelta suggested_reclaim_time,
-                       size_t max_tasks,
-                       Optional<int> max_best_effort_tasks = nullopt,
-                       SchedulerWorkerObserver* worker_observer = nullptr,
-                       Optional<TimeDelta> may_block_threshold = nullopt) {
-    ASSERT_TRUE(worker_pool_);
-    worker_pool_->Start(
-        SchedulerWorkerPoolParams(max_tasks, suggested_reclaim_time),
+  void StartThreadGroup(TimeDelta suggested_reclaim_time,
+                        size_t max_tasks,
+                        Optional<int> max_best_effort_tasks = nullopt,
+                        WorkerThreadObserver* worker_observer = nullptr,
+                        Optional<TimeDelta> may_block_threshold = nullopt) {
+    ASSERT_TRUE(thread_group_);
+    thread_group_->Start(
+        ThreadGroupParams(max_tasks, suggested_reclaim_time),
         max_best_effort_tasks ? max_best_effort_tasks.value() : max_tasks,
         service_thread_.task_runner(), worker_observer,
-        SchedulerWorkerPool::WorkerEnvironment::NONE, may_block_threshold);
+        ThreadGroup::WorkerEnvironment::NONE, may_block_threshold);
   }
 
-  void CreateAndStartWorkerPool(
+  void CreateAndStartThreadGroup(
       TimeDelta suggested_reclaim_time = TimeDelta::Max(),
       size_t max_tasks = kMaxTasks,
       Optional<int> max_best_effort_tasks = nullopt,
-      SchedulerWorkerObserver* worker_observer = nullptr,
+      WorkerThreadObserver* worker_observer = nullptr,
       Optional<TimeDelta> may_block_threshold = nullopt) {
-    CreateWorkerPool();
-    StartWorkerPool(suggested_reclaim_time, max_tasks, max_best_effort_tasks,
-                    worker_observer, may_block_threshold);
+    CreateThreadGroup();
+    StartThreadGroup(suggested_reclaim_time, max_tasks, max_best_effort_tasks,
+                     worker_observer, may_block_threshold);
   }
 
   Thread service_thread_;
   TaskTracker task_tracker_ = {"Test"};
-  std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool_;
+  std::unique_ptr<ThreadGroupImpl> thread_group_;
   DelayedTaskManager delayed_task_manager_;
-  TrackedRefFactory<SchedulerWorkerPool::Delegate> tracked_ref_factory_;
-  test::MockSchedulerTaskRunnerDelegate mock_scheduler_task_runner_delegate_ = {
+  TrackedRefFactory<ThreadGroup::Delegate> tracked_ref_factory_;
+  test::MockPooledTaskRunnerDelegate mock_pooled_task_runner_delegate_ = {
       task_tracker_.GetTrackedRef(), &delayed_task_manager_};
 
  private:
-  // SchedulerWorkerPool::Delegate:
-  SchedulerWorkerPool* GetWorkerPoolForTraits(
-      const TaskTraits& traits) override {
-    return worker_pool_.get();
+  // ThreadGroup::Delegate:
+  ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) override {
+    return thread_group_.get();
   }
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolImplTestBase);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplImplTestBase);
 };
 
-class ThreadPoolWorkerPoolImplTest : public ThreadPoolWorkerPoolImplTestBase,
-                                     public testing::Test {
+class ThreadGroupImplImplTest : public ThreadGroupImplImplTestBase,
+                                public testing::Test {
  protected:
-  ThreadPoolWorkerPoolImplTest() = default;
+  ThreadGroupImplImplTest() = default;
 
-  void SetUp() override { CreateAndStartWorkerPool(); }
+  void SetUp() override { CreateAndStartThreadGroup(); }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolImplTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplImplTest);
 };
 
-class ThreadPoolWorkerPoolImplTestParam
-    : public ThreadPoolWorkerPoolImplTestBase,
+class ThreadGroupImplImplTestParam
+    : public ThreadGroupImplImplTestBase,
       public testing::TestWithParam<test::ExecutionMode> {
  protected:
-  ThreadPoolWorkerPoolImplTestParam() = default;
+  ThreadGroupImplImplTestParam() = default;
 
-  void SetUp() override { CreateAndStartWorkerPool(); }
+  void SetUp() override { CreateAndStartThreadGroup(); }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolImplTestParam);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplImplTestParam);
 };
 
 using PostNestedTask = test::TestTaskFactory::PostNestedTask;
 
 class ThreadPostingTasksWaitIdle : public SimpleThread {
  public:
-  // Constructs a thread that posts tasks to |worker_pool| through an
+  // Constructs a thread that posts tasks to |thread_group| through an
   // |execution_mode| task runner. The thread waits until all workers in
-  // |worker_pool| are idle before posting a new task.
-  ThreadPostingTasksWaitIdle(SchedulerWorkerPoolImpl* worker_pool,
-                             test::MockSchedulerTaskRunnerDelegate*
-                                 mock_scheduler_task_runner_delegate_,
-                             test::ExecutionMode execution_mode)
+  // |thread_group| are idle before posting a new task.
+  ThreadPostingTasksWaitIdle(
+      ThreadGroupImpl* thread_group,
+      test::MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate_,
+      test::ExecutionMode execution_mode)
       : SimpleThread("ThreadPostingTasksWaitIdle"),
-        worker_pool_(worker_pool),
+        thread_group_(thread_group),
         factory_(CreateTaskRunnerWithExecutionMode(
                      execution_mode,
-                     mock_scheduler_task_runner_delegate_),
+                     mock_pooled_task_runner_delegate_),
                  execution_mode) {
-    DCHECK(worker_pool_);
+    DCHECK(thread_group_);
   }
 
   const test::TestTaskFactory* factory() const { return &factory_; }
@@ -195,12 +190,12 @@
     EXPECT_FALSE(factory_.task_runner()->RunsTasksInCurrentSequence());
 
     for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) {
-      worker_pool_->WaitForAllWorkersIdleForTesting();
+      thread_group_->WaitForAllWorkersIdleForTesting();
       EXPECT_TRUE(factory_.PostTask(PostNestedTask::NO, Closure()));
     }
   }
 
-  SchedulerWorkerPoolImpl* const worker_pool_;
+  ThreadGroupImpl* const thread_group_;
   const scoped_refptr<TaskRunner> task_runner_;
   test::TestTaskFactory factory_;
 
@@ -209,7 +204,7 @@
 
 }  // namespace
 
-TEST_P(ThreadPoolWorkerPoolImplTestParam, PostTasksWaitAllWorkersIdle) {
+TEST_P(ThreadGroupImplImplTestParam, PostTasksWaitAllWorkersIdle) {
   // Create threads to post tasks. To verify that workers can sleep and be woken
   // up when new tasks are posted, wait for all workers to become idle before
   // posting a new task.
@@ -218,7 +213,7 @@
   for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
     threads_posting_tasks.push_back(
         std::make_unique<ThreadPostingTasksWaitIdle>(
-            worker_pool_.get(), &mock_scheduler_task_runner_delegate_,
+            thread_group_.get(), &mock_pooled_task_runner_delegate_,
             GetParam()));
     threads_posting_tasks.back()->Start();
   }
@@ -231,10 +226,10 @@
 
   // Wait until all workers are idle to be sure that no task accesses its
   // TestTaskFactory after |thread_posting_tasks| is destroyed.
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 }
 
-TEST_P(ThreadPoolWorkerPoolImplTestParam, PostTasksWithOneAvailableWorker) {
+TEST_P(ThreadGroupImplImplTestParam, PostTasksWithOneAvailableWorker) {
   // Post blocking tasks to keep all workers busy except one until |event| is
   // signaled. Use different factories so that tasks are added to different
   // sequences and can run simultaneously when the execution mode is SEQUENCED.
@@ -242,8 +237,8 @@
   std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories;
   for (size_t i = 0; i < (kMaxTasks - 1); ++i) {
     blocked_task_factories.push_back(std::make_unique<test::TestTaskFactory>(
-        CreateTaskRunnerWithExecutionMode(
-            GetParam(), &mock_scheduler_task_runner_delegate_),
+        CreateTaskRunnerWithExecutionMode(GetParam(),
+                                          &mock_pooled_task_runner_delegate_),
         GetParam()));
     EXPECT_TRUE(blocked_task_factories.back()->PostTask(
         PostNestedTask::NO,
@@ -252,10 +247,10 @@
   }
 
   // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact
-  // that only one worker in |worker_pool_| isn't busy.
+  // that only one worker in |thread_group_| isn't busy.
   test::TestTaskFactory short_task_factory(
       CreateTaskRunnerWithExecutionMode(GetParam(),
-                                        &mock_scheduler_task_runner_delegate_),
+                                        &mock_pooled_task_runner_delegate_),
       GetParam());
   for (size_t i = 0; i < kNumTasksPostedPerThread; ++i)
     EXPECT_TRUE(short_task_factory.PostTask(PostNestedTask::NO, Closure()));
@@ -266,10 +261,10 @@
 
   // Wait until all workers are idle to be sure that no task accesses
   // its TestTaskFactory after it is destroyed.
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 }
 
-TEST_P(ThreadPoolWorkerPoolImplTestParam, Saturate) {
+TEST_P(ThreadGroupImplImplTestParam, Saturate) {
   // Verify that it is possible to have |kMaxTasks| tasks/sequences running
   // simultaneously. Use different factories so that the blocking tasks are
   // added to different sequences and can run simultaneously when the execution
@@ -278,8 +273,8 @@
   std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
   for (size_t i = 0; i < kMaxTasks; ++i) {
     factories.push_back(std::make_unique<test::TestTaskFactory>(
-        CreateTaskRunnerWithExecutionMode(
-            GetParam(), &mock_scheduler_task_runner_delegate_),
+        CreateTaskRunnerWithExecutionMode(GetParam(),
+                                          &mock_pooled_task_runner_delegate_),
         GetParam()));
     EXPECT_TRUE(factories.back()->PostTask(
         PostNestedTask::NO,
@@ -292,23 +287,22 @@
 
   // Wait until all workers are idle to be sure that no task accesses
   // its TestTaskFactory after it is destroyed.
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 }
 
 INSTANTIATE_TEST_SUITE_P(Parallel,
-                         ThreadPoolWorkerPoolImplTestParam,
+                         ThreadGroupImplImplTestParam,
                          ::testing::Values(test::ExecutionMode::PARALLEL));
 INSTANTIATE_TEST_SUITE_P(Sequenced,
-                         ThreadPoolWorkerPoolImplTestParam,
+                         ThreadGroupImplImplTestParam,
                          ::testing::Values(test::ExecutionMode::SEQUENCED));
 
 namespace {
 
-class ThreadPoolWorkerPoolImplStartInBodyTest
-    : public ThreadPoolWorkerPoolImplTest {
+class ThreadGroupImplImplStartInBodyTest : public ThreadGroupImplImplTest {
  public:
   void SetUp() override {
-    CreateWorkerPool();
+    CreateThreadGroup();
     // Let the test start the worker pool.
   }
 };
@@ -323,9 +317,9 @@
 
 }  // namespace
 
-// Verify that 2 tasks posted before Start() to a SchedulerWorkerPoolImpl with
+// Verify that 2 tasks posted before Start() to a ThreadGroupImpl with
 // more than 2 workers run on different workers when Start() is called.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest, PostTasksBeforeStart) {
+TEST_F(ThreadGroupImplImplStartInBodyTest, PostTasksBeforeStart) {
   PlatformThreadRef task_1_thread_ref;
   PlatformThreadRef task_2_thread_ref;
   WaitableEvent task_1_running;
@@ -338,13 +332,13 @@
   WaitableEvent barrier;
 
   test::CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()},
-                                   &mock_scheduler_task_runner_delegate_)
+                                   &mock_pooled_task_runner_delegate_)
       ->PostTask(
           FROM_HERE,
           BindOnce(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref),
                    Unretained(&task_1_running), Unretained(&barrier)));
   test::CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()},
-                                   &mock_scheduler_task_runner_delegate_)
+                                   &mock_pooled_task_runner_delegate_)
       ->PostTask(
           FROM_HERE,
           BindOnce(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref),
@@ -352,11 +346,11 @@
 
   // Workers should not be created and tasks should not run before the pool is
   // started.
-  EXPECT_EQ(0U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(0U, thread_group_->NumberOfWorkersForTesting());
   EXPECT_FALSE(task_1_running.IsSignaled());
   EXPECT_FALSE(task_2_running.IsSignaled());
 
-  StartWorkerPool(TimeDelta::Max(), kMaxTasks);
+  StartThreadGroup(TimeDelta::Max(), kMaxTasks);
 
   // Tasks should run shortly after the pool is started.
   task_1_running.Wait();
@@ -371,9 +365,9 @@
 
 // Verify that posting many tasks before Start will cause the number of workers
 // to grow to |max_tasks_| after Start.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest, PostManyTasks) {
+TEST_F(ThreadGroupImplImplStartInBodyTest, PostManyTasks) {
   scoped_refptr<TaskRunner> task_runner = test::CreateTaskRunnerWithTraits(
-      {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+      {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
   constexpr size_t kNumTasksPosted = 2 * kMaxTasks;
 
   WaitableEvent threads_running;
@@ -395,15 +389,15 @@
   for (size_t i = kMaxTasks; i < kNumTasksPosted; ++i)
     task_runner->PostTask(FROM_HERE, DoNothing());
 
-  EXPECT_EQ(0U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(0U, thread_group_->NumberOfWorkersForTesting());
 
-  StartWorkerPool(TimeDelta::Max(), kMaxTasks);
-  EXPECT_GT(worker_pool_->NumberOfWorkersForTesting(), 0U);
-  EXPECT_EQ(kMaxTasks, worker_pool_->GetMaxTasksForTesting());
+  StartThreadGroup(TimeDelta::Max(), kMaxTasks);
+  EXPECT_GT(thread_group_->NumberOfWorkersForTesting(), 0U);
+  EXPECT_EQ(kMaxTasks, thread_group_->GetMaxTasksForTesting());
 
   threads_running.Wait();
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(),
-            worker_pool_->GetMaxTasksForTesting());
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(),
+            thread_group_->GetMaxTasksForTesting());
   threads_continue.Signal();
   task_tracker_.FlushForTesting();
 }
@@ -412,7 +406,7 @@
 
 constexpr size_t kMagicTlsValue = 42;
 
-class ThreadPoolWorkerPoolCheckTlsReuse : public ThreadPoolWorkerPoolImplTest {
+class ThreadGroupImplCheckTlsReuse : public ThreadGroupImplImplTest {
  public:
   void SetTlsValueAndWait() {
     slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
@@ -428,10 +422,10 @@
   }
 
  protected:
-  ThreadPoolWorkerPoolCheckTlsReuse() = default;
+  ThreadGroupImplCheckTlsReuse() = default;
 
   void SetUp() override {
-    CreateAndStartWorkerPool(kReclaimTimeForCleanupTests, kMaxTasks);
+    CreateAndStartThreadGroup(kReclaimTimeForCleanupTests, kMaxTasks);
   }
 
   subtle::Atomic32 zero_tls_values_ = 0;
@@ -441,36 +435,36 @@
  private:
   ThreadLocalStorage::Slot slot_;
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolCheckTlsReuse);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplCheckTlsReuse);
 };
 
 }  // namespace
 
 // Checks that at least one worker has been cleaned up by checking the TLS.
-TEST_F(ThreadPoolWorkerPoolCheckTlsReuse, CheckCleanupWorkers) {
+TEST_F(ThreadGroupImplCheckTlsReuse, CheckCleanupWorkers) {
   // Saturate the workers and mark each worker's thread with a magic TLS value.
   std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
   for (size_t i = 0; i < kMaxTasks; ++i) {
     factories.push_back(std::make_unique<test::TestTaskFactory>(
         test::CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()},
-                                         &mock_scheduler_task_runner_delegate_),
+                                         &mock_pooled_task_runner_delegate_),
         test::ExecutionMode::PARALLEL));
     ASSERT_TRUE(factories.back()->PostTask(
         PostNestedTask::NO,
-        Bind(&ThreadPoolWorkerPoolCheckTlsReuse::SetTlsValueAndWait,
+        Bind(&ThreadGroupImplCheckTlsReuse::SetTlsValueAndWait,
              Unretained(this))));
     factories.back()->WaitForAllTasksToRun();
   }
 
   // Release tasks waiting on |waiter_|.
   waiter_.Signal();
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 
   // All workers should be done running by now, so reset for the next phase.
   waiter_.Reset();
 
   // Wait for the worker pool to clean up at least one worker.
-  worker_pool_->WaitForWorkersCleanedUpForTesting(1U);
+  thread_group_->WaitForWorkersCleanedUpForTesting(1U);
 
   // Saturate and count the worker threads that do not have the magic TLS value.
   // If the value is not there, that means we're at a new worker.
@@ -479,7 +473,7 @@
     count_waiters.push_back(std::make_unique<WaitableEvent>());
     ASSERT_TRUE(factory->PostTask(
         PostNestedTask::NO,
-        Bind(&ThreadPoolWorkerPoolCheckTlsReuse::CountZeroTlsValuesAndWait,
+        Bind(&ThreadGroupImplCheckTlsReuse::CountZeroTlsValuesAndWait,
              Unretained(this), count_waiters.back().get())));
     factory->WaitForAllTasksToRun();
   }
@@ -496,27 +490,27 @@
 
 namespace {
 
-class ThreadPoolWorkerPoolHistogramTest : public ThreadPoolWorkerPoolImplTest {
+class ThreadGroupImplHistogramTest : public ThreadGroupImplImplTest {
  public:
-  ThreadPoolWorkerPoolHistogramTest() = default;
+  ThreadGroupImplHistogramTest() = default;
 
  protected:
   // Override SetUp() to allow every test case to initialize a worker pool with
   // its own arguments.
   void SetUp() override {}
 
-  // Floods |worker_pool_| with a single task each that blocks until
+  // Floods |thread_group_| with a single task each that blocks until
   // |continue_event| is signaled. Every worker in the pool is blocked on
   // |continue_event| when this method returns. Note: this helper can easily be
   // generalized to be useful in other tests, but it's here for now because it's
-  // only used in a ThreadPoolWorkerPoolHistogramTest at the moment.
+  // only used in a ThreadGroupImplHistogramTest at the moment.
   void FloodPool(WaitableEvent* continue_event) {
     ASSERT_FALSE(continue_event->IsSignaled());
 
     auto task_runner = test::CreateTaskRunnerWithTraits(
-        {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+        {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
-    const auto max_tasks = worker_pool_->GetMaxTasksForTesting();
+    const auto max_tasks = thread_group_->GetMaxTasksForTesting();
 
     WaitableEvent workers_flooded;
     RepeatingClosure all_workers_running_barrier = BarrierClosure(
@@ -539,16 +533,16 @@
   std::unique_ptr<StatisticsRecorder> statistics_recorder_ =
       StatisticsRecorder::CreateTemporaryForTesting();
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolHistogramTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplHistogramTest);
 };
 
 }  // namespace
 
-TEST_F(ThreadPoolWorkerPoolHistogramTest, NumTasksBetweenWaits) {
+TEST_F(ThreadGroupImplHistogramTest, NumTasksBetweenWaits) {
   WaitableEvent event;
-  CreateAndStartWorkerPool(TimeDelta::Max(), kMaxTasks);
+  CreateAndStartThreadGroup(TimeDelta::Max(), kMaxTasks);
   auto task_runner = test::CreateSequencedTaskRunnerWithTraits(
-      {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+      {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
   // Post a task.
   task_runner->PostTask(FROM_HERE, BindOnce(&test::WaitWithoutBlockingObserver,
@@ -560,18 +554,18 @@
   task_runner->PostTask(FROM_HERE, DoNothing());
   task_runner->PostTask(FROM_HERE, DoNothing());
 
-  // Allow tasks to run and wait until the SchedulerWorker is idle.
+  // Allow tasks to run and wait until the WorkerThread is idle.
   event.Signal();
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 
-  // Wake up the SchedulerWorker that just became idle by posting a task and
-  // wait until it becomes idle again. The SchedulerWorker should record the
+  // Wake up the WorkerThread that just became idle by posting a task and
+  // wait until it becomes idle again. The WorkerThread should record the
   // ThreadPool.NumTasksBetweenWaits.* histogram on wake up.
   task_runner->PostTask(FROM_HERE, DoNothing());
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 
   // Verify that counts were recorded to the histogram as expected.
-  const auto* histogram = worker_pool_->num_tasks_between_waits_histogram();
+  const auto* histogram = thread_group_->num_tasks_between_waits_histogram();
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
   EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3));
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
@@ -579,16 +573,16 @@
 
 // Verifies that NumTasksBetweenWaits histogram is logged as expected across
 // idle and cleanup periods.
-TEST_F(ThreadPoolWorkerPoolHistogramTest,
+TEST_F(ThreadGroupImplHistogramTest,
        NumTasksBetweenWaitsWithIdlePeriodAndCleanup) {
   WaitableEvent tasks_can_exit_event;
-  CreateAndStartWorkerPool(kReclaimTimeForCleanupTests, kMaxTasks);
+  CreateAndStartThreadGroup(kReclaimTimeForCleanupTests, kMaxTasks);
 
   WaitableEvent workers_continue;
 
   FloodPool(&workers_continue);
 
-  const auto* histogram = worker_pool_->num_tasks_between_waits_histogram();
+  const auto* histogram = thread_group_->num_tasks_between_waits_histogram();
 
   // NumTasksBetweenWaits shouldn't be logged until idle.
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
@@ -597,7 +591,7 @@
 
   // Make all workers go idle.
   workers_continue.Signal();
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 
   // All workers should have reported a single hit in the "1" bucket per the the
   // histogram being reported when going idle and each worker having processed
@@ -607,7 +601,7 @@
             histogram->SnapshotSamples()->GetCount(1));
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
 
-  worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
+  thread_group_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
 
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
   EXPECT_EQ(static_cast<int>(kMaxTasks),
@@ -626,14 +620,14 @@
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
 
   workers_continue.Signal();
-  worker_pool_->WaitForAllWorkersIdleForTesting();
+  thread_group_->WaitForAllWorkersIdleForTesting();
 }
 
-TEST_F(ThreadPoolWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
-  CreateWorkerPool();
+TEST_F(ThreadGroupImplHistogramTest, NumTasksBeforeCleanup) {
+  CreateThreadGroup();
   auto histogrammed_thread_task_runner =
       test::CreateSequencedTaskRunnerWithTraits(
-          {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+          {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
   // Post 3 tasks and hold the thread for idle thread stack ordering.
   // This test assumes |histogrammed_thread_task_runner| gets assigned the same
@@ -684,22 +678,22 @@
   // 3: Worker #2:        Runs the tasks, violating the expectation that the 3
   //                      initial tasks run on the same worker.
   constexpr size_t kTwoWorkers = 2;
-  StartWorkerPool(kReclaimTimeForCleanupTests, kTwoWorkers);
+  StartThreadGroup(kReclaimTimeForCleanupTests, kTwoWorkers);
 
   // Wait until the 3rd task is scheduled.
   cleanup_thread_running.Wait();
 
-  // To allow the SchedulerWorker associated with
+  // To allow the WorkerThread associated with
   // |histogrammed_thread_task_runner| to cleanup, make sure it isn't on top of
-  // the idle stack by waking up another SchedulerWorker via
+  // the idle stack by waking up another WorkerThread via
   // |task_runner_for_top_idle|. |histogrammed_thread_task_runner| should
   // release and go idle first and then |task_runner_for_top_idle| should
-  // release and go idle. This allows the SchedulerWorker associated with
+  // release and go idle. This allows the WorkerThread associated with
   // |histogrammed_thread_task_runner| to cleanup.
   WaitableEvent top_idle_thread_running;
   WaitableEvent top_idle_thread_continue;
   auto task_runner_for_top_idle = test::CreateSequencedTaskRunnerWithTraits(
-      {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+      {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
   task_runner_for_top_idle->PostTask(
       FROM_HERE,
       BindOnce(
@@ -716,17 +710,17 @@
           thread_ref, Unretained(&top_idle_thread_running),
           Unretained(&top_idle_thread_continue)));
   top_idle_thread_running.Wait();
-  EXPECT_EQ(0U, worker_pool_->NumberOfIdleWorkersForTesting());
+  EXPECT_EQ(0U, thread_group_->NumberOfIdleWorkersForTesting());
   cleanup_thread_continue.Signal();
   // Wait for the cleanup thread to also become idle.
-  worker_pool_->WaitForWorkersIdleForTesting(1U);
+  thread_group_->WaitForWorkersIdleForTesting(1U);
   top_idle_thread_continue.Signal();
   // Allow the thread processing the |histogrammed_thread_task_runner| work to
   // cleanup.
-  worker_pool_->WaitForWorkersCleanedUpForTesting(1U);
+  thread_group_->WaitForWorkersCleanedUpForTesting(1U);
 
   // Verify that counts were recorded to the histogram as expected.
-  const auto* histogram = worker_pool_->num_tasks_before_detach_histogram();
+  const auto* histogram = thread_group_->num_tasks_before_detach_histogram();
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(1));
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(2));
@@ -739,35 +733,32 @@
 
 namespace {
 
-class ThreadPoolWorkerPoolStandbyPolicyTest
-    : public ThreadPoolWorkerPoolImplTestBase,
-      public testing::Test {
+class ThreadGroupImplStandbyPolicyTest : public ThreadGroupImplImplTestBase,
+                                         public testing::Test {
  public:
-  ThreadPoolWorkerPoolStandbyPolicyTest() = default;
+  ThreadGroupImplStandbyPolicyTest() = default;
 
   void SetUp() override {
-    CreateAndStartWorkerPool(kReclaimTimeForCleanupTests);
+    CreateAndStartThreadGroup(kReclaimTimeForCleanupTests);
   }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolStandbyPolicyTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplStandbyPolicyTest);
 };
 
 }  // namespace
 
-TEST_F(ThreadPoolWorkerPoolStandbyPolicyTest, InitOne) {
-  EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
+TEST_F(ThreadGroupImplStandbyPolicyTest, InitOne) {
+  EXPECT_EQ(1U, thread_group_->NumberOfWorkersForTesting());
 }
 
-// Verify that the SchedulerWorkerPoolImpl keeps at least one idle standby
+// Verify that the ThreadGroupImpl keeps at least one idle standby
 // thread, capacity permitting.
-TEST_F(ThreadPoolWorkerPoolStandbyPolicyTest, VerifyStandbyThread) {
+TEST_F(ThreadGroupImplStandbyPolicyTest, VerifyStandbyThread) {
   auto task_runner = test::CreateTaskRunnerWithTraits(
-      {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+      {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
   WaitableEvent threads_continue;
@@ -779,30 +770,30 @@
 
   // There should be one idle thread until we reach capacity
   for (size_t i = 0; i < kMaxTasks; ++i) {
-    EXPECT_EQ(i + 1, worker_pool_->NumberOfWorkersForTesting());
+    EXPECT_EQ(i + 1, thread_group_->NumberOfWorkersForTesting());
     task_runner->PostTask(FROM_HERE, thread_blocker);
     thread_running.Wait();
   }
 
   // There should not be an extra idle thread if it means going above capacity
-  EXPECT_EQ(kMaxTasks, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(kMaxTasks, thread_group_->NumberOfWorkersForTesting());
 
   threads_continue.Signal();
   // Wait long enough for all but one worker to clean up.
-  worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
-  EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
+  thread_group_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
+  EXPECT_EQ(1U, thread_group_->NumberOfWorkersForTesting());
   // Give extra time for a worker to cleanup : none should as the pool is
   // expected to keep a worker ready regardless of how long it was idle for.
   PlatformThread::Sleep(kReclaimTimeForCleanupTests);
-  EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(1U, thread_group_->NumberOfWorkersForTesting());
 }
 
 // Verify that being "the" idle thread counts as being active (i.e. won't be
 // reclaimed even if not on top of the idle stack when reclaim timeout expires).
 // Regression test for https://crbug.com/847501.
-TEST_F(ThreadPoolWorkerPoolStandbyPolicyTest, InAndOutStandbyThreadIsActive) {
+TEST_F(ThreadGroupImplStandbyPolicyTest, InAndOutStandbyThreadIsActive) {
   auto sequenced_task_runner = test::CreateSequencedTaskRunnerWithTraits(
-      {}, &mock_scheduler_task_runner_delegate_);
+      {}, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent timer_started;
 
@@ -817,31 +808,31 @@
   timer_started.Wait();
 
   // Running a task should have brought up a new standby thread.
-  EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(2U, thread_group_->NumberOfWorkersForTesting());
 
   // Give extra time for a worker to cleanup : none should as the two workers
   // are both considered "active" per the timer ticking faster than the reclaim
   // timeout.
   PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
-  EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(2U, thread_group_->NumberOfWorkersForTesting());
 
   sequenced_task_runner->PostTask(
       FROM_HERE, BindLambdaForTesting([&]() { recurring_task.Stop(); }));
 
   // Stopping the recurring task should let the second worker be reclaimed per
   // not being "the" standby thread for a full reclaim timeout.
-  worker_pool_->WaitForWorkersCleanedUpForTesting(1);
-  EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
+  thread_group_->WaitForWorkersCleanedUpForTesting(1);
+  EXPECT_EQ(1U, thread_group_->NumberOfWorkersForTesting());
 }
 
 // Verify that being "the" idle thread counts as being active but isn't sticky.
 // Regression test for https://crbug.com/847501.
-TEST_F(ThreadPoolWorkerPoolStandbyPolicyTest, OnlyKeepActiveStandbyThreads) {
+TEST_F(ThreadGroupImplStandbyPolicyTest, OnlyKeepActiveStandbyThreads) {
   auto sequenced_task_runner = test::CreateSequencedTaskRunnerWithTraits(
-      {}, &mock_scheduler_task_runner_delegate_);
+      {}, &mock_pooled_task_runner_delegate_);
 
   // Start this test like
-  // ThreadPoolWorkerPoolStandbyPolicyTest.InAndOutStandbyThreadIsActive and
+  // ThreadGroupImplStandbyPolicyTest.InAndOutStandbyThreadIsActive and
   // give it some time to stabilize.
   RepeatingTimer recurring_task;
   sequenced_task_runner->PostTask(
@@ -851,12 +842,12 @@
       }));
 
   PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
-  EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(2U, thread_group_->NumberOfWorkersForTesting());
 
   // Then also flood the pool (cycling the top of the idle stack).
   {
     auto task_runner = test::CreateTaskRunnerWithTraits(
-        {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+        {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
     WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
     WaitableEvent threads_continue;
@@ -871,7 +862,7 @@
       thread_running.Wait();
     }
 
-    EXPECT_EQ(kMaxTasks, worker_pool_->NumberOfWorkersForTesting());
+    EXPECT_EQ(kMaxTasks, thread_group_->NumberOfWorkersForTesting());
     threads_continue.Signal();
 
     // Flush to ensure all references to |threads_continue| are gone before it
@@ -880,18 +871,18 @@
   }
 
   // All workers should clean up but two (since the timer is still running).
-  worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 2);
-  EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
+  thread_group_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 2);
+  EXPECT_EQ(2U, thread_group_->NumberOfWorkersForTesting());
 
   // Extra time shouldn't change this.
   PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
-  EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
+  EXPECT_EQ(2U, thread_group_->NumberOfWorkersForTesting());
 
   // Stopping the timer should let the number of active threads go down to one.
   sequenced_task_runner->PostTask(
       FROM_HERE, BindLambdaForTesting([&]() { recurring_task.Stop(); }));
-  worker_pool_->WaitForWorkersCleanedUpForTesting(1);
-  EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
+  thread_group_->WaitForWorkersCleanedUpForTesting(1);
+  EXPECT_EQ(1U, thread_group_->NumberOfWorkersForTesting());
 }
 
 namespace {
@@ -937,11 +928,11 @@
 
 }  // namespace
 
-class ThreadPoolWorkerPoolBlockingTest
-    : public ThreadPoolWorkerPoolImplTestBase,
+class ThreadGroupImplBlockingTest
+    : public ThreadGroupImplImplTestBase,
       public testing::TestWithParam<NestedBlockingType> {
  public:
-  ThreadPoolWorkerPoolBlockingTest() = default;
+  ThreadGroupImplBlockingTest() = default;
 
   static std::string ParamInfoToString(
       ::testing::TestParamInfo<NestedBlockingType> param_info) {
@@ -955,9 +946,7 @@
     return str;
   }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  protected:
   // Saturates the worker pool with a task that first blocks, waits to be
@@ -1005,18 +994,18 @@
   // Returns how long we can expect a change to |max_tasks_| to occur
   // after a task has become blocked.
   TimeDelta GetMaxTasksChangeSleepTime() {
-    return std::max(worker_pool_->blocked_workers_poll_period_for_testing(),
-                    worker_pool_->may_block_threshold_for_testing()) +
+    return std::max(thread_group_->blocked_workers_poll_period_for_testing(),
+                    thread_group_->may_block_threshold_for_testing()) +
            TestTimeouts::tiny_timeout();
   }
 
-  // Waits indefinitely, until |worker_pool_|'s max tasks increases to
+  // Waits indefinitely, until |thread_group_|'s max tasks increases to
   // |expected_max_tasks|.
   void ExpectMaxTasksIncreasesTo(size_t expected_max_tasks) {
-    size_t max_tasks = worker_pool_->GetMaxTasksForTesting();
+    size_t max_tasks = thread_group_->GetMaxTasksForTesting();
     while (max_tasks != expected_max_tasks) {
       PlatformThread::Sleep(GetMaxTasksChangeSleepTime());
-      size_t new_max_tasks = worker_pool_->GetMaxTasksForTesting();
+      size_t new_max_tasks = thread_group_->GetMaxTasksForTesting();
       ASSERT_GE(new_max_tasks, max_tasks);
       max_tasks = new_max_tasks;
     }
@@ -1030,22 +1019,22 @@
 
   const scoped_refptr<TaskRunner> task_runner_ =
       test::CreateTaskRunnerWithTraits({MayBlock(), WithBaseSyncPrimitives()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
 
  private:
   WaitableEvent blocking_threads_continue_;
   WaitableEvent busy_threads_continue_;
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolBlockingTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplBlockingTest);
 };
 
 // Verify that SaturateWithBlockingTasks() causes max tasks to increase and
 // creates a worker if needed. Also verify that UnblockBlockingTasks() decreases
 // max tasks after an increase.
-TEST_P(ThreadPoolWorkerPoolBlockingTest, ThreadBlockedUnblocked) {
-  CreateAndStartWorkerPool();
+TEST_P(ThreadGroupImplBlockingTest, ThreadBlockedUnblocked) {
+  CreateAndStartThreadGroup();
 
-  ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  ASSERT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   SaturateWithBlockingTasks(GetParam());
 
@@ -1053,20 +1042,20 @@
   // should not block forever.
   SaturateWithBusyTasks();
 
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
 
   UnblockBusyTasks();
   UnblockBlockingTasks();
   task_tracker_.FlushForTesting();
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 }
 
 // Verify that flooding the pool with more BEST_EFFORT tasks than
 // kMaxBestEffortTasks doesn't prevent USER_VISIBLE tasks from running.
-TEST_P(ThreadPoolWorkerPoolBlockingTest, TooManyBestEffortTasks) {
+TEST_P(ThreadGroupImplBlockingTest, TooManyBestEffortTasks) {
   constexpr size_t kMaxBestEffortTasks = kMaxTasks / 2;
 
-  CreateAndStartWorkerPool(TimeDelta::Max(), kMaxTasks, kMaxBestEffortTasks);
+  CreateAndStartThreadGroup(TimeDelta::Max(), kMaxTasks, kMaxBestEffortTasks);
 
   WaitableEvent threads_continue;
   {
@@ -1083,7 +1072,7 @@
 
     const auto best_effort_task_runner = test::CreateTaskRunnerWithTraits(
         {TaskPriority::BEST_EFFORT, MayBlock()},
-        &mock_scheduler_task_runner_delegate_);
+        &mock_pooled_task_runner_delegate_);
     for (size_t i = 0; i < kMaxBestEffortTasks + 1; ++i) {
       best_effort_task_runner->PostTask(
           FROM_HERE, BindLambdaForTesting([&]() {
@@ -1104,9 +1093,11 @@
   // At this point, kMaxBestEffortTasks + 1 threads are running (plus
   // potentially the idle thread), but max_task and max_best_effort_task are
   // back to normal.
-  EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 1);
-  EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 2);
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  EXPECT_GE(thread_group_->NumberOfWorkersForTesting(),
+            kMaxBestEffortTasks + 1);
+  EXPECT_LE(thread_group_->NumberOfWorkersForTesting(),
+            kMaxBestEffortTasks + 2);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   WaitableEvent threads_running;
   task_runner_->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
@@ -1117,8 +1108,10 @@
   // This should not block forever.
   threads_running.Wait();
 
-  EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 2);
-  EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxBestEffortTasks + 3);
+  EXPECT_GE(thread_group_->NumberOfWorkersForTesting(),
+            kMaxBestEffortTasks + 2);
+  EXPECT_LE(thread_group_->NumberOfWorkersForTesting(),
+            kMaxBestEffortTasks + 3);
   threads_continue.Signal();
 
   task_tracker_.FlushForTesting();
@@ -1126,8 +1119,8 @@
 
 // Verify that tasks posted in a saturated pool before a ScopedBlockingCall will
 // execute after ScopedBlockingCall is instantiated.
-TEST_P(ThreadPoolWorkerPoolBlockingTest, PostBeforeBlocking) {
-  CreateAndStartWorkerPool();
+TEST_P(ThreadGroupImplBlockingTest, PostBeforeBlocking) {
+  CreateAndStartThreadGroup();
 
   WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
   WaitableEvent thread_can_block;
@@ -1154,8 +1147,8 @@
 
   // All workers should be occupied and the pool should be saturated. Workers
   // have not entered ScopedBlockingCall yet.
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks);
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   WaitableEvent extra_threads_running;
   WaitableEvent extra_threads_continue;
@@ -1181,7 +1174,7 @@
 
   // Should not block forever.
   extra_threads_running.Wait();
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
   extra_threads_continue.Signal();
 
   threads_continue.Signal();
@@ -1190,18 +1183,18 @@
 
 // Verify that workers become idle when the pool is over-capacity and that
 // those workers do no work.
-TEST_P(ThreadPoolWorkerPoolBlockingTest, WorkersIdleWhenOverCapacity) {
-  CreateAndStartWorkerPool();
+TEST_P(ThreadGroupImplBlockingTest, WorkersIdleWhenOverCapacity) {
+  CreateAndStartThreadGroup();
 
-  ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  ASSERT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   SaturateWithBlockingTasks(GetParam());
 
   // Forces |kMaxTasks| extra workers to be instantiated by posting tasks.
   SaturateWithBusyTasks();
 
-  ASSERT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(), 0U);
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
+  ASSERT_EQ(thread_group_->NumberOfIdleWorkersForTesting(), 0U);
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
 
   AtomicFlag is_exiting;
   // These tasks should not get executed until after other tasks become
@@ -1218,8 +1211,8 @@
   // unblocked. There will be work in the work queue, but the pool should now
   // be over-capacity and workers will become idle.
   UnblockBlockingTasks();
-  worker_pool_->WaitForWorkersIdleForTesting(kMaxTasks);
-  EXPECT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(), kMaxTasks);
+  thread_group_->WaitForWorkersIdleForTesting(kMaxTasks);
+  EXPECT_EQ(thread_group_->NumberOfIdleWorkersForTesting(), kMaxTasks);
 
   // Posting more tasks should not cause workers idle from the pool being over
   // capacity to begin doing work.
@@ -1243,7 +1236,7 @@
 
 INSTANTIATE_TEST_SUITE_P(
     ,
-    ThreadPoolWorkerPoolBlockingTest,
+    ThreadGroupImplBlockingTest,
     ::testing::Values(NestedBlockingType(BlockingType::MAY_BLOCK,
                                          OptionalBlockingType::NO_BLOCK,
                                          BlockingType::MAY_BLOCK),
@@ -1256,46 +1249,45 @@
                       NestedBlockingType(BlockingType::WILL_BLOCK,
                                          OptionalBlockingType::MAY_BLOCK,
                                          BlockingType::WILL_BLOCK)),
-    ThreadPoolWorkerPoolBlockingTest::ParamInfoToString);
+    ThreadGroupImplBlockingTest::ParamInfoToString);
 
 // Verify that if a thread enters the scope of a MAY_BLOCK ScopedBlockingCall,
 // but exits the scope before the MayBlock threshold is reached, that the max
 // tasks does not increase.
-TEST_F(ThreadPoolWorkerPoolBlockingTest, ThreadBlockUnblockPremature) {
+TEST_F(ThreadGroupImplBlockingTest, ThreadBlockUnblockPremature) {
   // Create a pool with an infinite MayBlock threshold so that a MAY_BLOCK
   // ScopedBlockingCall never increases the max tasks.
-  CreateAndStartWorkerPool(TimeDelta::Max(),  // |suggested_reclaim_time|
-                           kMaxTasks,         // |max_tasks|
-                           nullopt,           // |max_best_effort_tasks|
-                           nullptr,           // |worker_observer|
-                           TimeDelta::Max()   // |may_block_threshold|
+  CreateAndStartThreadGroup(TimeDelta::Max(),  // |suggested_reclaim_time|
+                            kMaxTasks,         // |max_tasks|
+                            nullopt,           // |max_best_effort_tasks|
+                            nullptr,           // |worker_observer|
+                            TimeDelta::Max()   // |may_block_threshold|
   );
-  ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  ASSERT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   SaturateWithBlockingTasks(NestedBlockingType(BlockingType::MAY_BLOCK,
                                                OptionalBlockingType::NO_BLOCK,
                                                BlockingType::MAY_BLOCK));
   PlatformThread::Sleep(
-      2 * worker_pool_->blocked_workers_poll_period_for_testing());
-  EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks);
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+      2 * thread_group_->blocked_workers_poll_period_for_testing());
+  EXPECT_EQ(thread_group_->NumberOfWorkersForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 
   UnblockBlockingTasks();
   task_tracker_.FlushForTesting();
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 }
 
 // Verify that if max tasks is incremented because of a MAY_BLOCK
 // ScopedBlockingCall, it isn't incremented again when there is a nested
 // WILL_BLOCK ScopedBlockingCall.
-TEST_F(ThreadPoolWorkerPoolBlockingTest,
-       MayBlockIncreaseCapacityNestedWillBlock) {
-  CreateAndStartWorkerPool();
+TEST_F(ThreadGroupImplBlockingTest, MayBlockIncreaseCapacityNestedWillBlock) {
+  CreateAndStartThreadGroup();
 
-  ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  ASSERT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
   auto task_runner =
       test::CreateTaskRunnerWithTraits({MayBlock(), WithBaseSyncPrimitives()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
   WaitableEvent can_return;
 
   // Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment
@@ -1333,51 +1325,48 @@
   did_instantiate_will_block.Wait();
 
   // Max tasks shouldn't be incremented again.
-  EXPECT_EQ(kMaxTasks + 1, worker_pool_->GetMaxTasksForTesting());
+  EXPECT_EQ(kMaxTasks + 1, thread_group_->GetMaxTasksForTesting());
 
   // Tear down.
   can_return.Signal();
   task_tracker_.FlushForTesting();
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks);
 }
 
-class ThreadPoolWorkerPoolOverCapacityTest
-    : public ThreadPoolWorkerPoolImplTestBase,
-      public testing::Test {
+class ThreadGroupImplOverCapacityTest : public ThreadGroupImplImplTestBase,
+                                        public testing::Test {
  public:
-  ThreadPoolWorkerPoolOverCapacityTest() = default;
+  ThreadGroupImplOverCapacityTest() = default;
 
   void SetUp() override {
-    CreateAndStartWorkerPool(kReclaimTimeForCleanupTests, kLocalMaxTasks);
+    CreateAndStartThreadGroup(kReclaimTimeForCleanupTests, kLocalMaxTasks);
     task_runner_ =
         test::CreateTaskRunnerWithTraits({MayBlock(), WithBaseSyncPrimitives()},
-                                         &mock_scheduler_task_runner_delegate_);
+                                         &mock_pooled_task_runner_delegate_);
   }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  protected:
   scoped_refptr<TaskRunner> task_runner_;
   static constexpr size_t kLocalMaxTasks = 3;
 
-  void CreateWorkerPool() {
-    ASSERT_FALSE(worker_pool_);
+  void CreateThreadGroup() {
+    ASSERT_FALSE(thread_group_);
     service_thread_.Start();
     delayed_task_manager_.Start(service_thread_.task_runner());
-    worker_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
-        "OverCapacityTestWorkerPool", "A", ThreadPriority::NORMAL,
+    thread_group_ = std::make_unique<ThreadGroupImpl>(
+        "OverCapacityTestThreadGroup", "A", ThreadPriority::NORMAL,
         task_tracker_.GetTrackedRef(), tracked_ref_factory_.GetTrackedRef());
-    ASSERT_TRUE(worker_pool_);
+    ASSERT_TRUE(thread_group_);
   }
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolOverCapacityTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupImplOverCapacityTest);
 };
 
 // Verify that workers that become idle due to the pool being over capacity will
 // eventually cleanup.
-TEST_F(ThreadPoolWorkerPoolOverCapacityTest, VerifyCleanup) {
+TEST_F(ThreadGroupImplOverCapacityTest, VerifyCleanup) {
   WaitableEvent threads_running;
   WaitableEvent threads_continue;
   RepeatingClosure threads_running_barrier = BarrierClosure(
@@ -1425,8 +1414,8 @@
   }
   extra_threads_running.Wait();
 
-  ASSERT_EQ(kLocalMaxTasks * 2, worker_pool_->NumberOfWorkersForTesting());
-  EXPECT_EQ(kLocalMaxTasks * 2, worker_pool_->GetMaxTasksForTesting());
+  ASSERT_EQ(kLocalMaxTasks * 2, thread_group_->NumberOfWorkersForTesting());
+  EXPECT_EQ(kLocalMaxTasks * 2, thread_group_->GetMaxTasksForTesting());
   blocked_call_continue.Signal();
   extra_threads_continue.Signal();
 
@@ -1439,8 +1428,8 @@
 
   // Note: one worker above capacity will not get cleaned up since it's on the
   // top of the idle stack.
-  worker_pool_->WaitForWorkersCleanedUpForTesting(kLocalMaxTasks - 1);
-  EXPECT_EQ(kLocalMaxTasks + 1, worker_pool_->NumberOfWorkersForTesting());
+  thread_group_->WaitForWorkersCleanedUpForTesting(kLocalMaxTasks - 1);
+  EXPECT_EQ(kLocalMaxTasks + 1, thread_group_->NumberOfWorkersForTesting());
 
   threads_continue.Signal();
   task_tracker_.FlushForTesting();
@@ -1448,8 +1437,8 @@
 
 // Verify that the maximum number of workers is 256 and that hitting the max
 // leaves the pool in a valid state with regards to max tasks.
-TEST_F(ThreadPoolWorkerPoolBlockingTest, MaximumWorkersTest) {
-  CreateAndStartWorkerPool();
+TEST_F(ThreadGroupImplBlockingTest, MaximumWorkersTest) {
+  CreateAndStartThreadGroup();
 
   constexpr size_t kMaxNumberOfWorkers = 256;
   constexpr size_t kNumExtraTasks = 10;
@@ -1489,7 +1478,7 @@
   }
 
   early_blocking_threads_running.Wait();
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(),
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(),
             kMaxTasks + kMaxNumberOfWorkers);
 
   WaitableEvent late_release_thread_contine;
@@ -1519,7 +1508,7 @@
 
   // Give time to see if we exceed the max number of workers.
   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-  EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxNumberOfWorkers);
+  EXPECT_LE(thread_group_->NumberOfWorkersForTesting(), kMaxNumberOfWorkers);
 
   early_release_threads_continue.Signal();
   early_threads_finished.Wait();
@@ -1544,7 +1533,7 @@
             Unretained(&final_tasks_continue)));
   }
   final_tasks_running.Wait();
-  EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks + kNumExtraTasks);
+  EXPECT_EQ(thread_group_->GetMaxTasksForTesting(), kMaxTasks + kNumExtraTasks);
   late_release_thread_contine.Signal();
   final_tasks_continue.Signal();
   task_tracker_.FlushForTesting();
@@ -1552,17 +1541,17 @@
 
 // Verify that the maximum number of best-effort tasks that can run concurrently
 // is honored.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest, MaxBestEffortTasks) {
+TEST_F(ThreadGroupImplImplStartInBodyTest, MaxBestEffortTasks) {
   constexpr int kMaxBestEffortTasks = kMaxTasks / 2;
-  StartWorkerPool(TimeDelta::Max(),      // |suggested_reclaim_time|
-                  kMaxTasks,             // |max_tasks|
-                  kMaxBestEffortTasks);  // |max_best_effort_tasks|
+  StartThreadGroup(TimeDelta::Max(),      // |suggested_reclaim_time|
+                   kMaxTasks,             // |max_tasks|
+                   kMaxBestEffortTasks);  // |max_best_effort_tasks|
   const scoped_refptr<TaskRunner> foreground_runner =
       test::CreateTaskRunnerWithTraits({MayBlock()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
   const scoped_refptr<TaskRunner> background_runner =
       test::CreateTaskRunnerWithTraits({TaskPriority::BEST_EFFORT, MayBlock()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
 
   // It should be possible to have |kMaxBestEffortTasks|
   // TaskPriority::BEST_EFFORT tasks running concurrently.
@@ -1609,20 +1598,20 @@
 
 // Verify that flooding the pool with BEST_EFFORT tasks doesn't cause the
 // creation of more than |max_best_effort_tasks| + 1 workers.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest,
+TEST_F(ThreadGroupImplImplStartInBodyTest,
        FloodBestEffortTasksDoesNotCreateTooManyWorkers) {
   constexpr size_t kMaxBestEffortTasks = kMaxTasks / 2;
-  StartWorkerPool(TimeDelta::Max(),      // |suggested_reclaim_time|
-                  kMaxTasks,             // |max_tasks|
-                  kMaxBestEffortTasks);  // |max_best_effort_tasks|
+  StartThreadGroup(TimeDelta::Max(),      // |suggested_reclaim_time|
+                   kMaxTasks,             // |max_tasks|
+                   kMaxBestEffortTasks);  // |max_best_effort_tasks|
 
   const scoped_refptr<TaskRunner> runner =
       test::CreateTaskRunnerWithTraits({TaskPriority::BEST_EFFORT, MayBlock()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
 
   for (size_t i = 0; i < kLargeNumber; ++i) {
     runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
-                       EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(),
+                       EXPECT_LE(thread_group_->NumberOfWorkersForTesting(),
                                  kMaxBestEffortTasks + 1);
                      }));
   }
@@ -1633,22 +1622,22 @@
 
 namespace {
 
-// A SchedulerWorkerObserver that lets one worker start, then waits until
+// A WorkerThreadObserver that lets one worker start, then waits until
 // UnblockWorkers() is called before letting any other workers start.
-class HoldWorkersObserver : public SchedulerWorkerObserver {
+class HoldWorkersObserver : public WorkerThreadObserver {
  public:
   HoldWorkersObserver() = default;
 
   void UnblockWorkers() { unblock_workers_.Signal(); }
 
-  // SchedulerWorkerObserver:
-  void OnSchedulerWorkerMainEntry() override {
+  // WorkerThreadObserver:
+  void OnWorkerThreadMainEntry() override {
     bool expected = false;
     if (allowed_first_worker_.compare_exchange_strong(expected, true))
       return;
     test::WaitWithoutBlockingObserver(&unblock_workers_);
   }
-  void OnSchedulerWorkerMainExit() override {}
+  void OnWorkerThreadMainExit() override {}
 
  private:
   std::atomic_bool allowed_first_worker_{false};
@@ -1673,16 +1662,16 @@
 // 4. Task A enters a second WILL_BLOCK ScopedBlockingCall. This should no-op
 //    because there are already enough workers.
 // 5. Unblock HoldWorkersObserver and wait for all tasks to complete.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest,
+TEST_F(ThreadGroupImplImplStartInBodyTest,
        RepeatedWillBlockDoesNotCreateTooManyWorkers) {
   constexpr size_t kNumWorkers = 2U;
   HoldWorkersObserver worker_observer;
-  StartWorkerPool(TimeDelta::Max(),   // |suggested_reclaim_time|
-                  kNumWorkers,        // |max_tasks|
-                  nullopt,            // |max_best_effort_tasks|
-                  &worker_observer);  // |worker_observer|
+  StartThreadGroup(TimeDelta::Max(),   // |suggested_reclaim_time|
+                   kNumWorkers,        // |max_tasks|
+                   nullopt,            // |max_best_effort_tasks|
+                   &worker_observer);  // |worker_observer|
   const scoped_refptr<TaskRunner> runner = test::CreateTaskRunnerWithTraits(
-      {MayBlock()}, &mock_scheduler_task_runner_delegate_);
+      {MayBlock()}, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent hold_will_block_task;
   runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
@@ -1694,58 +1683,55 @@
                        ScopedBlockingCall scoped_blocking_call(
                            FROM_HERE, BlockingType::WILL_BLOCK);
                        EXPECT_LE(kNumWorkers + 1,
-                                 worker_pool_->NumberOfWorkersForTesting());
+                                 thread_group_->NumberOfWorkersForTesting());
                      }
 
                      worker_observer.UnblockWorkers();
                    }));
 
   runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
-                     EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(),
+                     EXPECT_LE(thread_group_->NumberOfWorkersForTesting(),
                                kNumWorkers + 1);
                    }));
   hold_will_block_task.Signal();
 
   // Join the pool to avoid invalid accesses to |worker_observer|.
   task_tracker_.FlushForTesting();
-  worker_pool_->JoinForTesting();
-  worker_pool_.reset();
+  thread_group_->JoinForTesting();
+  thread_group_.reset();
 }
 
 namespace {
 
-class ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest
-    : public ThreadPoolWorkerPoolImplTestBase,
+class ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest
+    : public ThreadGroupImplImplTestBase,
       public testing::TestWithParam<BlockingType> {
  public:
   static constexpr int kMaxBestEffortTasks = kMaxTasks / 2;
 
-  ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest() = default;
+  ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest() = default;
 
   void SetUp() override {
-    CreateWorkerPool();
-    worker_pool_->Start(
-        SchedulerWorkerPoolParams(kMaxTasks, base::TimeDelta::Max()),
-        kMaxBestEffortTasks, service_thread_.task_runner(), nullptr,
-        SchedulerWorkerPool::WorkerEnvironment::NONE);
+    CreateThreadGroup();
+    thread_group_->Start(ThreadGroupParams(kMaxTasks, base::TimeDelta::Max()),
+                         kMaxBestEffortTasks, service_thread_.task_runner(),
+                         nullptr, ThreadGroup::WorkerEnvironment::NONE);
   }
 
-  void TearDown() override {
-    ThreadPoolWorkerPoolImplTestBase::CommonTearDown();
-  }
+  void TearDown() override { ThreadGroupImplImplTestBase::CommonTearDown(); }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(
-      ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest);
+      ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest);
 };
 
 }  // namespace
 
-TEST_P(ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
+TEST_P(ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest,
        BlockingCallAndMaxBestEffortTasksTest) {
   const scoped_refptr<TaskRunner> background_runner =
       test::CreateTaskRunnerWithTraits({TaskPriority::BEST_EFFORT, MayBlock()},
-                                       &mock_scheduler_task_runner_delegate_);
+                                       &mock_pooled_task_runner_delegate_);
 
   // Post |kMaxBestEffortTasks| TaskPriority::BEST_EFFORT tasks that block in a
   // ScopedBlockingCall.
@@ -1792,18 +1778,16 @@
   task_tracker_.FlushForTesting();
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    MayBlock,
-    ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
-    ::testing::Values(BlockingType::MAY_BLOCK));
-INSTANTIATE_TEST_SUITE_P(
-    WillBlock,
-    ThreadPoolWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
-    ::testing::Values(BlockingType::WILL_BLOCK));
+INSTANTIATE_TEST_SUITE_P(MayBlock,
+                         ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest,
+                         ::testing::Values(BlockingType::MAY_BLOCK));
+INSTANTIATE_TEST_SUITE_P(WillBlock,
+                         ThreadGroupImplBlockingCallAndMaxBestEffortTasksTest,
+                         ::testing::Values(BlockingType::WILL_BLOCK));
 
 // Verify that worker detachment doesn't race with worker cleanup, regression
 // test for https://crbug.com/810464.
-TEST_F(ThreadPoolWorkerPoolImplStartInBodyTest, RacyCleanup) {
+TEST_F(ThreadGroupImplImplStartInBodyTest, RacyCleanup) {
 #if defined(OS_FUCHSIA)
   // Fuchsia + QEMU doesn't deal well with *many* threads being
   // created/destroyed at once: https://crbug.com/816575.
@@ -1814,13 +1798,13 @@
   constexpr TimeDelta kReclaimTimeForRacyCleanupTest =
       TimeDelta::FromMilliseconds(10);
 
-  worker_pool_->Start(
-      SchedulerWorkerPoolParams(kLocalMaxTasks, kReclaimTimeForRacyCleanupTest),
+  thread_group_->Start(
+      ThreadGroupParams(kLocalMaxTasks, kReclaimTimeForRacyCleanupTest),
       kLocalMaxTasks, service_thread_.task_runner(), nullptr,
-      SchedulerWorkerPool::WorkerEnvironment::NONE);
+      ThreadGroup::WorkerEnvironment::NONE);
 
   scoped_refptr<TaskRunner> task_runner = test::CreateTaskRunnerWithTraits(
-      {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
+      {WithBaseSyncPrimitives()}, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent threads_running;
   WaitableEvent unblock_threads;
@@ -1847,20 +1831,20 @@
   // being idle.
   PlatformThread::Sleep(kReclaimTimeForRacyCleanupTest);
 
-  worker_pool_->JoinForTesting();
+  thread_group_->JoinForTesting();
 
   // Unwinding this test will be racy if worker cleanup can race with
-  // SchedulerWorkerPoolImpl destruction : https://crbug.com/810464.
-  worker_pool_.reset();
+  // ThreadGroupImpl destruction : https://crbug.com/810464.
+  thread_group_.reset();
 }
 
-TEST_P(ThreadPoolWorkerPoolImplTestParam, ReportHeartbeatMetrics) {
+TEST_P(ThreadGroupImplImplTestParam, ReportHeartbeatMetrics) {
   HistogramTester tester;
-  worker_pool_->ReportHeartbeatMetrics();
+  thread_group_->ReportHeartbeatMetrics();
   EXPECT_FALSE(
-      tester.GetAllSamples("ThreadPool.NumWorkers.TestWorkerPool").empty());
+      tester.GetAllSamples("ThreadPool.NumWorkers.TestThreadGroup").empty());
   EXPECT_FALSE(
-      tester.GetAllSamples("ThreadPool.NumActiveWorkers.TestWorkerPool")
+      tester.GetAllSamples("ThreadPool.NumActiveWorkers.TestThreadGroup")
           .empty());
 }
 
diff --git a/base/task/thread_pool/platform_native_worker_pool.cc b/base/task/thread_pool/thread_group_native.cc
similarity index 76%
rename from base/task/thread_pool/platform_native_worker_pool.cc
rename to base/task/thread_pool/thread_group_native.cc
index fb2f40d..0f0403b 100644
--- a/base/task/thread_pool/platform_native_worker_pool.cc
+++ b/base/task/thread_pool/thread_group_native.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 "base/task/thread_pool/platform_native_worker_pool.h"
+#include "base/task/thread_pool/thread_group_native.h"
 
 #include <algorithm>
 #include <utility>
@@ -13,10 +13,10 @@
 namespace base {
 namespace internal {
 
-class PlatformNativeWorkerPool::ScopedWorkersExecutor
-    : public SchedulerWorkerPool::BaseScopedWorkersExecutor {
+class ThreadGroupNative::ScopedWorkersExecutor
+    : public ThreadGroup::BaseScopedWorkersExecutor {
  public:
-  ScopedWorkersExecutor(PlatformNativeWorkerPool* outer) : outer_(outer) {}
+  ScopedWorkersExecutor(ThreadGroupNative* outer) : outer_(outer) {}
   ~ScopedWorkersExecutor() {
     CheckedLock::AssertNoLockHeldOnCurrentThread();
 
@@ -31,21 +31,20 @@
   }
 
  private:
-  PlatformNativeWorkerPool* const outer_;
+  ThreadGroupNative* const outer_;
   size_t num_threadpool_work_to_submit_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedWorkersExecutor);
 };
 
-PlatformNativeWorkerPool::PlatformNativeWorkerPool(
-    TrackedRef<TaskTracker> task_tracker,
-    TrackedRef<Delegate> delegate,
-    SchedulerWorkerPool* predecessor_pool)
-    : SchedulerWorkerPool(std::move(task_tracker),
-                          std::move(delegate),
-                          predecessor_pool) {}
+ThreadGroupNative::ThreadGroupNative(TrackedRef<TaskTracker> task_tracker,
+                                     TrackedRef<Delegate> delegate,
+                                     ThreadGroup* predecessor_pool)
+    : ThreadGroup(std::move(task_tracker),
+                  std::move(delegate),
+                  predecessor_pool) {}
 
-PlatformNativeWorkerPool::~PlatformNativeWorkerPool() {
+ThreadGroupNative::~ThreadGroupNative() {
 #if DCHECK_IS_ON()
   // Verify join_for_testing has been called to ensure that there is no more
   // outstanding work. Otherwise, work may try to de-reference an invalid
@@ -54,7 +53,7 @@
 #endif
 }
 
-void PlatformNativeWorkerPool::Start(WorkerEnvironment worker_environment) {
+void ThreadGroupNative::Start(WorkerEnvironment worker_environment) {
   worker_environment_ = worker_environment;
 
   StartImpl();
@@ -66,7 +65,7 @@
   EnsureEnoughWorkersLockRequired(&executor);
 }
 
-void PlatformNativeWorkerPool::JoinForTesting() {
+void ThreadGroupNative::JoinForTesting() {
   JoinImpl();
 #if DCHECK_IS_ON()
   DCHECK(!join_for_testing_returned_);
@@ -74,7 +73,7 @@
 #endif
 }
 
-void PlatformNativeWorkerPool::RunNextTaskSourceImpl() {
+void ThreadGroupNative::RunNextTaskSourceImpl() {
   scoped_refptr<TaskSource> task_source = GetWork();
 
   if (task_source) {
@@ -94,7 +93,7 @@
   }
 }
 
-scoped_refptr<TaskSource> PlatformNativeWorkerPool::GetWork() {
+scoped_refptr<TaskSource> ThreadGroupNative::GetWork() {
   CheckedAutoLock auto_lock(lock_);
   DCHECK_GT(num_pending_threadpool_work_, 0U);
   --num_pending_threadpool_work_;
@@ -110,20 +109,20 @@
   return priority_queue_.PopTaskSource();
 }
 
-void PlatformNativeWorkerPool::UpdateSortKey(
+void ThreadGroupNative::UpdateSortKey(
     TaskSourceAndTransaction task_source_and_transaction) {
   ScopedWorkersExecutor executor(this);
   UpdateSortKeyImpl(&executor, std::move(task_source_and_transaction));
 }
 
-void PlatformNativeWorkerPool::PushTaskSourceAndWakeUpWorkers(
+void ThreadGroupNative::PushTaskSourceAndWakeUpWorkers(
     TaskSourceAndTransaction task_source_and_transaction) {
   ScopedWorkersExecutor executor(this);
   PushTaskSourceAndWakeUpWorkersImpl(&executor,
                                      std::move(task_source_and_transaction));
 }
 
-void PlatformNativeWorkerPool::EnsureEnoughWorkersLockRequired(
+void ThreadGroupNative::EnsureEnoughWorkersLockRequired(
     BaseScopedWorkersExecutor* executor) {
   if (!started_)
     return;
@@ -141,8 +140,7 @@
   }
 }
 
-size_t PlatformNativeWorkerPool::GetMaxConcurrentNonBlockedTasksDeprecated()
-    const {
+size_t ThreadGroupNative::GetMaxConcurrentNonBlockedTasksDeprecated() const {
   // Native thread pools give us no control over the number of workers that are
   // active at one time. Consequently, we cannot report a true value here.
   // Instead, the values were chosen to match
@@ -151,12 +149,12 @@
   return std::max(3, num_cores - 1);
 }
 
-void PlatformNativeWorkerPool::ReportHeartbeatMetrics() const {
+void ThreadGroupNative::ReportHeartbeatMetrics() const {
   // Native thread pools do not provide the capability to determine the
   // number of worker threads created.
 }
 
-void PlatformNativeWorkerPool::DidUpdateCanRunPolicy() {
+void ThreadGroupNative::DidUpdateCanRunPolicy() {
   ScopedWorkersExecutor executor(this);
   CheckedAutoLock auto_lock(lock_);
   EnsureEnoughWorkersLockRequired(&executor);
diff --git a/base/task/thread_pool/platform_native_worker_pool.h b/base/task/thread_pool/thread_group_native.h
similarity index 74%
rename from base/task/thread_pool/platform_native_worker_pool.h
rename to base/task/thread_pool/thread_group_native.h
index 149bdff..a2a4f26 100644
--- a/base/task/thread_pool/platform_native_worker_pool.h
+++ b/base/task/thread_pool/thread_group_native.h
@@ -2,36 +2,36 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_H_
-#define BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_H_
+#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_H_
 
 #include "base/base_export.h"
 #include "base/synchronization/atomic_flag.h"
-#include "base/task/thread_pool/scheduler_worker_pool.h"
+#include "base/task/thread_pool/thread_group.h"
 
 namespace base {
 namespace internal {
 
-class BASE_EXPORT PlatformNativeWorkerPool : public SchedulerWorkerPool {
+class BASE_EXPORT ThreadGroupNative : public ThreadGroup {
  public:
-  // Destroying a PlatformNativeWorkerPool is not allowed in
+  // Destroying a ThreadGroupNative is not allowed in
   // production; it is always leaked. In tests, it can only be destroyed after
   // JoinForTesting() has returned.
-  ~PlatformNativeWorkerPool() override;
+  ~ThreadGroupNative() override;
 
   // Starts the worker pool and allows tasks to begin running.
   void Start(WorkerEnvironment worker_environment = WorkerEnvironment::NONE);
 
-  // SchedulerWorkerPool:
+  // ThreadGroup:
   void JoinForTesting() override;
   size_t GetMaxConcurrentNonBlockedTasksDeprecated() const override;
   void ReportHeartbeatMetrics() const override;
   void DidUpdateCanRunPolicy() override;
 
  protected:
-  PlatformNativeWorkerPool(TrackedRef<TaskTracker> task_tracker,
-                           TrackedRef<Delegate> delegate,
-                           SchedulerWorkerPool* predecessor_pool);
+  ThreadGroupNative(TrackedRef<TaskTracker> task_tracker,
+                    TrackedRef<Delegate> delegate,
+                    ThreadGroup* predecessor_pool);
 
   // Runs a task off the next task source on the |priority_queue_|. Called by
   // callbacks posted to platform native thread pools.
@@ -47,7 +47,7 @@
  private:
   class ScopedWorkersExecutor;
 
-  // SchedulerWorkerPool:
+  // ThreadGroup:
   void UpdateSortKey(
       TaskSourceAndTransaction task_source_and_transaction) override;
   void PushTaskSourceAndWakeUpWorkers(
@@ -71,10 +71,10 @@
   bool join_for_testing_returned_ = false;
 #endif
 
-  DISALLOW_COPY_AND_ASSIGN(PlatformNativeWorkerPool);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupNative);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_PLATFORM_NATIVE_WORKER_POOL_H_
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_H_
diff --git a/base/task/thread_pool/thread_group_native_mac.h b/base/task/thread_pool/thread_group_native_mac.h
new file mode 100644
index 0000000..74c2e43
--- /dev/null
+++ b/base/task/thread_pool/thread_group_native_mac.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_MAC_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_MAC_H_
+
+#include <dispatch/dispatch.h>
+
+#include "base/base_export.h"
+#include "base/mac/scoped_dispatch_object.h"
+#include "base/task/thread_pool/thread_group_native.h"
+
+namespace base {
+namespace internal {
+
+// A ThreadGroup implementation backed by libdispatch.
+//
+// libdispatch official documentation:
+// https://developer.apple.com/documentation/dispatch
+//
+// Guides:
+// https://apple.github.io/swift-corelibs-libdispatch/tutorial/
+// https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
+class BASE_EXPORT ThreadGroupNativeMac : public ThreadGroupNative {
+ public:
+  ThreadGroupNativeMac(TrackedRef<TaskTracker> task_tracker,
+                       TrackedRef<Delegate> delegate,
+                       ThreadGroup* predecessor_pool = nullptr);
+
+  ~ThreadGroupNativeMac() override;
+
+ private:
+  // ThreadGroupNative:
+  void JoinImpl() override;
+  void StartImpl() override;
+  void SubmitWork() override;
+
+  // Dispatch queue on which work is scheduled. Backed by a shared thread pool
+  // managed by libdispatch.
+  ScopedDispatchObject<dispatch_queue_t> queue_;
+
+  // Dispatch group to enable synchronization.
+  ScopedDispatchObject<dispatch_group_t> group_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupNativeMac);
+};
+
+using ThreadGroupNativeImpl = ThreadGroupNativeMac;
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_MAC_H_
diff --git a/base/task/thread_pool/thread_group_native_mac.mm b/base/task/thread_pool/thread_group_native_mac.mm
new file mode 100644
index 0000000..8caf65a
--- /dev/null
+++ b/base/task/thread_pool/thread_group_native_mac.mm
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/task/thread_pool/thread_group_native_mac.h"
+
+#include "base/task/thread_pool/task_tracker.h"
+
+namespace base {
+namespace internal {
+
+ThreadGroupNativeMac::ThreadGroupNativeMac(TrackedRef<TaskTracker> task_tracker,
+                                           TrackedRef<Delegate> delegate,
+                                           ThreadGroup* predecessor_pool)
+    : ThreadGroupNative(std::move(task_tracker),
+                        std::move(delegate),
+                        predecessor_pool) {}
+
+ThreadGroupNativeMac::~ThreadGroupNativeMac() {}
+
+void ThreadGroupNativeMac::StartImpl() {
+  queue_.reset(dispatch_queue_create("org.chromium.base.ThreadPool.ThreadGroup",
+                                     DISPATCH_QUEUE_CONCURRENT));
+  group_.reset(dispatch_group_create());
+}
+
+void ThreadGroupNativeMac::JoinImpl() {
+  dispatch_group_wait(group_, DISPATCH_TIME_FOREVER);
+}
+
+void ThreadGroupNativeMac::SubmitWork() {
+  // TODO(adityakeerthi): Handle priorities by having multiple dispatch queues
+  // with different qualities-of-service.
+  dispatch_group_async(group_, queue_, ^{
+    RunNextTaskSourceImpl();
+  });
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/thread_pool/platform_native_worker_pool_win.cc b/base/task/thread_pool/thread_group_native_win.cc
similarity index 69%
rename from base/task/thread_pool/platform_native_worker_pool_win.cc
rename to base/task/thread_pool/thread_group_native_win.cc
index 4595a40..f18611d 100644
--- a/base/task/thread_pool/platform_native_worker_pool_win.cc
+++ b/base/task/thread_pool/thread_group_native_win.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 "base/task/thread_pool/platform_native_worker_pool_win.h"
+#include "base/task/thread_pool/thread_group_native_win.h"
 
 #include "base/optional.h"
 #include "base/task/thread_pool/task_tracker.h"
@@ -12,7 +12,7 @@
 namespace base {
 namespace internal {
 
-class PlatformNativeWorkerPoolWin::ScopedCallbackMayRunLongObserver
+class ThreadGroupNativeWin::ScopedCallbackMayRunLongObserver
     : public BlockingObserver {
  public:
   ScopedCallbackMayRunLongObserver(PTP_CALLBACK_INSTANCE callback)
@@ -40,21 +40,20 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedCallbackMayRunLongObserver);
 };
 
-PlatformNativeWorkerPoolWin::PlatformNativeWorkerPoolWin(
-    TrackedRef<TaskTracker> task_tracker,
-    TrackedRef<Delegate> delegate,
-    SchedulerWorkerPool* predecessor_pool)
-    : PlatformNativeWorkerPool(std::move(task_tracker),
-                               std::move(delegate),
-                               predecessor_pool) {}
+ThreadGroupNativeWin::ThreadGroupNativeWin(TrackedRef<TaskTracker> task_tracker,
+                                           TrackedRef<Delegate> delegate,
+                                           ThreadGroup* predecessor_pool)
+    : ThreadGroupNative(std::move(task_tracker),
+                        std::move(delegate),
+                        predecessor_pool) {}
 
-PlatformNativeWorkerPoolWin::~PlatformNativeWorkerPoolWin() {
+ThreadGroupNativeWin::~ThreadGroupNativeWin() {
   ::DestroyThreadpoolEnvironment(&environment_);
   ::CloseThreadpoolWork(work_);
   ::CloseThreadpool(pool_);
 }
 
-void PlatformNativeWorkerPoolWin::StartImpl() {
+void ThreadGroupNativeWin::StartImpl() {
   ::InitializeThreadpoolEnvironment(&environment_);
 
   pool_ = ::CreateThreadpool(nullptr);
@@ -67,35 +66,35 @@
   ::SetThreadpoolCallbackPool(&environment_, pool_);
 }
 
-void PlatformNativeWorkerPoolWin::JoinImpl() {
+void ThreadGroupNativeWin::JoinImpl() {
   ::WaitForThreadpoolWorkCallbacks(work_, true);
 }
 
-void PlatformNativeWorkerPoolWin::SubmitWork() {
+void ThreadGroupNativeWin::SubmitWork() {
   // TODO(fdoray): Handle priorities by having different work objects and using
   // SetThreadpoolCallbackPriority().
   ::SubmitThreadpoolWork(work_);
 }
 
 // static
-void CALLBACK PlatformNativeWorkerPoolWin::RunNextTaskSource(
+void CALLBACK ThreadGroupNativeWin::RunNextTaskSource(
     PTP_CALLBACK_INSTANCE callback_instance,
-    void* scheduler_worker_pool_windows_impl,
+    void* scheduler_thread_group_windows_impl,
     PTP_WORK) {
-  auto* worker_pool = static_cast<PlatformNativeWorkerPoolWin*>(
-      scheduler_worker_pool_windows_impl);
+  auto* thread_group =
+      static_cast<ThreadGroupNativeWin*>(scheduler_thread_group_windows_impl);
 
   // Windows Thread Pool API best practices state that all resources created
   // in the callback function should be cleaned up before returning from the
   // function. This includes COM initialization.
   Optional<win::ScopedCOMInitializer> com_initializer;
-  if (worker_pool->worker_environment_ == WorkerEnvironment::COM_MTA)
+  if (thread_group->worker_environment_ == WorkerEnvironment::COM_MTA)
     com_initializer.emplace(win::ScopedCOMInitializer::kMTA);
 
   ScopedCallbackMayRunLongObserver callback_may_run_long_observer(
       callback_instance);
 
-  worker_pool->RunNextTaskSourceImpl();
+  thread_group->RunNextTaskSourceImpl();
 }
 
 }  // namespace internal
diff --git a/base/task/thread_pool/thread_group_native_win.h b/base/task/thread_pool/thread_group_native_win.h
new file mode 100644
index 0000000..1f1db7b
--- /dev/null
+++ b/base/task/thread_pool/thread_group_native_win.h
@@ -0,0 +1,69 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_WIN_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_WIN_H_
+
+#include <windows.h>
+
+#include "base/base_export.h"
+#include "base/task/thread_pool/thread_group_native.h"
+
+namespace base {
+namespace internal {
+
+// A ThreadGroup implementation backed by the Windows Thread Pool API.
+//
+// Windows Thread Pool API official documentation:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686766(v=vs.85).aspx
+//
+// Blog posts on the Windows Thread Pool API:
+// https://msdn.microsoft.com/magazine/hh335066.aspx
+// https://msdn.microsoft.com/magazine/hh394144.aspx
+// https://msdn.microsoft.com/magazine/hh456398.aspx
+// https://msdn.microsoft.com/magazine/hh547107.aspx
+// https://msdn.microsoft.com/magazine/hh580731.aspx
+class BASE_EXPORT ThreadGroupNativeWin : public ThreadGroupNative {
+ public:
+  ThreadGroupNativeWin(TrackedRef<TaskTracker> task_tracker,
+                       TrackedRef<Delegate> delegate,
+                       ThreadGroup* predecessor_pool = nullptr);
+
+  ~ThreadGroupNativeWin() override;
+
+ private:
+  class ScopedCallbackMayRunLongObserver;
+
+  // Callback that gets run by |pool_|.
+  static void CALLBACK
+  RunNextTaskSource(PTP_CALLBACK_INSTANCE callback_instance,
+                    void* scheduler_thread_group_windows_impl,
+                    PTP_WORK);
+
+  // ThreadGroupNative:
+  void JoinImpl() override;
+  void StartImpl() override;
+  void SubmitWork() override;
+
+  // Thread pool object that |work_| gets executed on.
+  PTP_POOL pool_ = nullptr;
+
+  // Callback environment. |pool_| is associated with |environment_| so that
+  // work objects using this environment run on |pool_|.
+  TP_CALLBACK_ENVIRON environment_ = {};
+
+  // Work object that executes RunNextTaskSource. It has a pointer to the
+  // current |ThreadGroupNativeWin| and a pointer to |environment_| bound
+  // to it.
+  PTP_WORK work_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupNativeWin);
+};
+
+using ThreadGroupNativeImpl = ThreadGroupNativeWin;
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_NATIVE_WIN_H_
diff --git a/base/task/thread_pool/thread_group_params.cc b/base/task/thread_pool/thread_group_params.cc
new file mode 100644
index 0000000..3ff314b9
--- /dev/null
+++ b/base/task/thread_pool/thread_group_params.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 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/task/thread_pool/thread_group_params.h"
+
+namespace base {
+
+ThreadGroupParams::ThreadGroupParams(
+    int max_tasks,
+    TimeDelta suggested_reclaim_time,
+    WorkerThreadBackwardCompatibility backward_compatibility)
+    : max_tasks_(max_tasks),
+      suggested_reclaim_time_(suggested_reclaim_time),
+      backward_compatibility_(backward_compatibility) {}
+
+ThreadGroupParams::ThreadGroupParams(const ThreadGroupParams& other) = default;
+
+ThreadGroupParams& ThreadGroupParams::operator=(
+    const ThreadGroupParams& other) = default;
+
+}  // namespace base
diff --git a/base/task/thread_pool/thread_group_params.h b/base/task/thread_pool/thread_group_params.h
new file mode 100644
index 0000000..f89408c
--- /dev/null
+++ b/base/task/thread_pool/thread_group_params.h
@@ -0,0 +1,43 @@
+// Copyright 2016 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_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_
+#define BASE_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_
+
+#include "base/task/thread_pool/worker_thread_params.h"
+#include "base/time/time.h"
+
+namespace base {
+
+class BASE_EXPORT ThreadGroupParams final {
+ public:
+  // Constructs a set of params used to initialize a pool. The pool will run
+  // concurrently at most |max_tasks| that aren't blocked (ScopedBlockingCall).
+  // |suggested_reclaim_time| sets a suggestion on when to reclaim idle threads.
+  // The pool is free to ignore this value for performance or correctness
+  // reasons. |backward_compatibility| indicates whether backward compatibility
+  // is enabled.
+  ThreadGroupParams(int max_tasks,
+                    TimeDelta suggested_reclaim_time,
+                    WorkerThreadBackwardCompatibility backward_compatibility =
+                        WorkerThreadBackwardCompatibility::DISABLED);
+
+  ThreadGroupParams(const ThreadGroupParams& other);
+  ThreadGroupParams& operator=(const ThreadGroupParams& other);
+
+  int max_tasks() const { return max_tasks_; }
+  TimeDelta suggested_reclaim_time() const { return suggested_reclaim_time_; }
+  WorkerThreadBackwardCompatibility backward_compatibility() const {
+    return backward_compatibility_;
+  }
+
+ private:
+  int max_tasks_;
+  TimeDelta suggested_reclaim_time_;
+  WorkerThreadBackwardCompatibility backward_compatibility_;
+};
+
+}  // namespace base
+
+#endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_PARAMS_H_
diff --git a/base/task/thread_pool/scheduler_worker_pool_unittest.cc b/base/task/thread_pool/thread_group_unittest.cc
similarity index 74%
rename from base/task/thread_pool/scheduler_worker_pool_unittest.cc
rename to base/task/thread_pool/thread_group_unittest.cc
index 7fd55c4..13104b80 100644
--- a/base/task/thread_pool/scheduler_worker_pool_unittest.cc
+++ b/base/task/thread_pool/thread_group_unittest.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 "base/task/thread_pool/scheduler_worker_pool.h"
+#include "base/task/thread_pool/thread_group.h"
 
 #include <memory>
 
@@ -14,12 +14,12 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/can_run_policy_test.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
-#include "base/task/thread_pool/scheduler_sequenced_task_runner.h"
-#include "base/task/thread_pool/scheduler_worker_pool_impl.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/pooled_sequenced_task_runner.h"
 #include "base/task/thread_pool/task_tracker.h"
 #include "base/task/thread_pool/test_task_factory.h"
 #include "base/task/thread_pool/test_utils.h"
+#include "base/task/thread_pool/thread_group_impl.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/task_runner.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/test_timeouts.h"
@@ -32,10 +32,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
-#include "base/task/thread_pool/platform_native_worker_pool_win.h"
+#include "base/task/thread_pool/thread_group_native_win.h"
 #include "base/win/com_init_util.h"
 #elif defined(OS_MACOSX)
-#include "base/task/thread_pool/platform_native_worker_pool_mac.h"
+#include "base/task/thread_pool/thread_group_native_mac.h"
 #endif
 
 namespace base {
@@ -44,11 +44,11 @@
 namespace {
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
-using PlatformNativeWorkerPoolType =
+using ThreadGroupNativeType =
 #if defined(OS_WIN)
-    PlatformNativeWorkerPoolWin;
+    ThreadGroupNativeWin;
 #elif defined(OS_MACOSX)
-    PlatformNativeWorkerPoolMac;
+    ThreadGroupNativeMac;
 #endif
 #endif
 
@@ -68,18 +68,18 @@
 class ThreadPostingTasks : public SimpleThread {
  public:
   // Constructs a thread that posts |num_tasks_posted_per_thread| tasks to
-  // |worker_pool| through an |execution_mode| task runner. If
+  // |thread_group| through an |execution_mode| task runner. If
   // |post_nested_task| is YES, each task posted by this thread posts another
   // task when it runs.
-  ThreadPostingTasks(test::MockSchedulerTaskRunnerDelegate*
-                         mock_scheduler_task_runner_delegate_,
-                     test::ExecutionMode execution_mode,
-                     PostNestedTask post_nested_task)
+  ThreadPostingTasks(
+      test::MockPooledTaskRunnerDelegate* mock_pooled_task_runner_delegate_,
+      test::ExecutionMode execution_mode,
+      PostNestedTask post_nested_task)
       : SimpleThread("ThreadPostingTasks"),
         post_nested_task_(post_nested_task),
         factory_(test::CreateTaskRunnerWithExecutionMode(
                      execution_mode,
-                     mock_scheduler_task_runner_delegate_),
+                     mock_pooled_task_runner_delegate_),
                  execution_mode) {}
 
   const test::TestTaskFactory* factory() const { return &factory_; }
@@ -99,68 +99,65 @@
   DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks);
 };
 
-class ThreadPoolWorkerPoolTest
-    : public testing::TestWithParam<PoolExecutionType>,
-      public SchedulerWorkerPool::Delegate {
+class ThreadGroupTest : public testing::TestWithParam<PoolExecutionType>,
+                        public ThreadGroup::Delegate {
  protected:
-  ThreadPoolWorkerPoolTest()
+  ThreadGroupTest()
       : service_thread_("ThreadPoolServiceThread"),
         tracked_ref_factory_(this) {}
 
   void SetUp() override {
     service_thread_.Start();
     delayed_task_manager_.Start(service_thread_.task_runner());
-    CreateWorkerPool();
+    CreateThreadGroup();
   }
 
   void TearDown() override {
     service_thread_.Stop();
-    if (worker_pool_)
-      worker_pool_->JoinForTesting();
-    worker_pool_.reset();
+    if (thread_group_)
+      thread_group_->JoinForTesting();
+    thread_group_.reset();
   }
 
-  void CreateWorkerPool() {
-    ASSERT_FALSE(worker_pool_);
+  void CreateThreadGroup() {
+    ASSERT_FALSE(thread_group_);
     switch (GetParam().pool_type) {
       case test::PoolType::GENERIC:
-        worker_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
-            "TestWorkerPool", "A", ThreadPriority::NORMAL,
+        thread_group_ = std::make_unique<ThreadGroupImpl>(
+            "TestThreadGroup", "A", ThreadPriority::NORMAL,
             task_tracker_.GetTrackedRef(),
             tracked_ref_factory_.GetTrackedRef());
         break;
 #if defined(OS_WIN) || defined(OS_MACOSX)
       case test::PoolType::NATIVE:
-        worker_pool_ = std::make_unique<PlatformNativeWorkerPoolType>(
+        thread_group_ = std::make_unique<ThreadGroupNativeType>(
             task_tracker_.GetTrackedRef(),
             tracked_ref_factory_.GetTrackedRef());
         break;
 #endif
     }
-    ASSERT_TRUE(worker_pool_);
+    ASSERT_TRUE(thread_group_);
 
-    mock_scheduler_task_runner_delegate_.SetWorkerPool(worker_pool_.get());
+    mock_pooled_task_runner_delegate_.SetThreadGroup(thread_group_.get());
   }
 
-  void StartWorkerPool(
-      SchedulerWorkerPool::WorkerEnvironment worker_environment =
-          SchedulerWorkerPool::WorkerEnvironment::NONE) {
-    ASSERT_TRUE(worker_pool_);
+  void StartThreadGroup(ThreadGroup::WorkerEnvironment worker_environment =
+                            ThreadGroup::WorkerEnvironment::NONE) {
+    ASSERT_TRUE(thread_group_);
     switch (GetParam().pool_type) {
       case test::PoolType::GENERIC: {
-        SchedulerWorkerPoolImpl* scheduler_worker_pool_impl =
-            static_cast<SchedulerWorkerPoolImpl*>(worker_pool_.get());
-        scheduler_worker_pool_impl->Start(
-            SchedulerWorkerPoolParams(kMaxTasks, TimeDelta::Max()),
-            kMaxBestEffortTasks, service_thread_.task_runner(), nullptr,
-            worker_environment);
+        ThreadGroupImpl* scheduler_thread_group_impl =
+            static_cast<ThreadGroupImpl*>(thread_group_.get());
+        scheduler_thread_group_impl->Start(
+            ThreadGroupParams(kMaxTasks, TimeDelta::Max()), kMaxBestEffortTasks,
+            service_thread_.task_runner(), nullptr, worker_environment);
         break;
       }
 #if defined(OS_WIN) || defined(OS_MACOSX)
       case test::PoolType::NATIVE: {
-        PlatformNativeWorkerPoolType* scheduler_worker_pool_native_impl =
-            static_cast<PlatformNativeWorkerPoolType*>(worker_pool_.get());
-        scheduler_worker_pool_native_impl->Start(worker_environment);
+        ThreadGroupNativeType* scheduler_thread_group_native_impl =
+            static_cast<ThreadGroupNativeType*>(thread_group_.get());
+        scheduler_thread_group_native_impl->Start(worker_environment);
         break;
       }
 #endif
@@ -170,28 +167,26 @@
   scoped_refptr<TaskRunner> CreateTaskRunner(
       const TaskTraits& traits = TaskTraits()) {
     return test::CreateTaskRunnerWithExecutionMode(
-        GetParam().execution_mode, &mock_scheduler_task_runner_delegate_,
-        traits);
+        GetParam().execution_mode, &mock_pooled_task_runner_delegate_, traits);
   }
 
   Thread service_thread_;
   TaskTracker task_tracker_ = {"Test"};
   DelayedTaskManager delayed_task_manager_;
-  test::MockSchedulerTaskRunnerDelegate mock_scheduler_task_runner_delegate_ = {
+  test::MockPooledTaskRunnerDelegate mock_pooled_task_runner_delegate_ = {
       task_tracker_.GetTrackedRef(), &delayed_task_manager_};
 
-  std::unique_ptr<SchedulerWorkerPool> worker_pool_;
+  std::unique_ptr<ThreadGroup> thread_group_;
 
  private:
-  // SchedulerWorkerPool::Delegate:
-  SchedulerWorkerPool* GetWorkerPoolForTraits(
-      const TaskTraits& traits) override {
-    return worker_pool_.get();
+  // ThreadGroup::Delegate:
+  ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) override {
+    return thread_group_.get();
   }
 
-  TrackedRefFactory<SchedulerWorkerPool::Delegate> tracked_ref_factory_;
+  TrackedRefFactory<ThreadGroup::Delegate> tracked_ref_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorkerPoolTest);
+  DISALLOW_COPY_AND_ASSIGN(ThreadGroupTest);
 };
 
 void ShouldNotRun() {
@@ -200,13 +195,13 @@
 
 }  // namespace
 
-TEST_P(ThreadPoolWorkerPoolTest, PostTasks) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, PostTasks) {
+  StartThreadGroup();
   // Create threads to post tasks.
   std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
   for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
     threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
-        &mock_scheduler_task_runner_delegate_, GetParam().execution_mode,
+        &mock_pooled_task_runner_delegate_, GetParam().execution_mode,
         PostNestedTask::NO));
     threads_posting_tasks.back()->Start();
   }
@@ -222,14 +217,14 @@
   task_tracker_.FlushForTesting();
 }
 
-TEST_P(ThreadPoolWorkerPoolTest, NestedPostTasks) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, NestedPostTasks) {
+  StartThreadGroup();
   // Create threads to post tasks. Each task posted by these threads will post
   // another task when it runs.
   std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
   for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
     threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
-        &mock_scheduler_task_runner_delegate_, GetParam().execution_mode,
+        &mock_pooled_task_runner_delegate_, GetParam().execution_mode,
         PostNestedTask::YES));
     threads_posting_tasks.back()->Start();
   }
@@ -246,8 +241,8 @@
 }
 
 // Verify that a Task can't be posted after shutdown.
-TEST_P(ThreadPoolWorkerPoolTest, PostTaskAfterShutdown) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, PostTaskAfterShutdown) {
+  StartThreadGroup();
   auto task_runner = CreateTaskRunner();
   test::ShutdownTaskTracker(&task_tracker_);
   EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
@@ -255,19 +250,19 @@
 
 // Verify that posting tasks after the pool was destroyed fails but doesn't
 // crash.
-TEST_P(ThreadPoolWorkerPoolTest, PostAfterDestroy) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, PostAfterDestroy) {
+  StartThreadGroup();
   auto task_runner = CreateTaskRunner();
   EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
   test::ShutdownTaskTracker(&task_tracker_);
-  worker_pool_->JoinForTesting();
-  worker_pool_.reset();
+  thread_group_->JoinForTesting();
+  thread_group_.reset();
   EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
 }
 
 // Verify that a Task runs shortly after its delay expires.
-TEST_P(ThreadPoolWorkerPoolTest, PostDelayedTask) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, PostDelayedTask) {
+  StartThreadGroup();
 
   WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC,
                          WaitableEvent::InitialState::NOT_SIGNALED);
@@ -302,11 +297,11 @@
 // Tests that use TestTaskFactory already verify that
 // RunsTasksInCurrentSequence() returns true when appropriate so this method
 // complements it to get full coverage of that method.
-TEST_P(ThreadPoolWorkerPoolTest, SequencedRunsTasksInCurrentSequence) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, SequencedRunsTasksInCurrentSequence) {
+  StartThreadGroup();
   auto task_runner = CreateTaskRunner();
   auto sequenced_task_runner = test::CreateSequencedTaskRunnerWithTraits(
-      TaskTraits(), &mock_scheduler_task_runner_delegate_);
+      TaskTraits(), &mock_pooled_task_runner_delegate_);
 
   WaitableEvent task_ran;
   task_runner->PostTask(
@@ -322,7 +317,7 @@
 }
 
 // Verify that tasks posted before Start run after Start.
-TEST_P(ThreadPoolWorkerPoolTest, PostBeforeStart) {
+TEST_P(ThreadGroupTest, PostBeforeStart) {
   WaitableEvent task_1_running;
   WaitableEvent task_2_running;
 
@@ -338,7 +333,7 @@
   EXPECT_FALSE(task_1_running.IsSignaled());
   EXPECT_FALSE(task_2_running.IsSignaled());
 
-  StartWorkerPool();
+  StartThreadGroup();
 
   // Tasks should run shortly after the pool is started.
   task_1_running.Wait();
@@ -348,30 +343,30 @@
 }
 
 // Verify that tasks only run when allowed by the CanRunPolicy.
-TEST_P(ThreadPoolWorkerPoolTest, CanRunPolicyBasic) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, CanRunPolicyBasic) {
+  StartThreadGroup();
   test::TestCanRunPolicyBasic(
-      worker_pool_.get(),
+      thread_group_.get(),
       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
       &task_tracker_);
 }
 
-TEST_P(ThreadPoolWorkerPoolTest, CanRunPolicyUpdatedBeforeRun) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, CanRunPolicyUpdatedBeforeRun) {
+  StartThreadGroup();
   // This test only works with SequencedTaskRunner become it assumes
   // ordered execution of 2 posted tasks.
   if (GetParam().execution_mode != test::ExecutionMode::SEQUENCED)
     return;
   test::TestCanRunPolicyChangedBeforeRun(
-      worker_pool_.get(),
+      thread_group_.get(),
       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
       &task_tracker_);
 }
 
-TEST_P(ThreadPoolWorkerPoolTest, CanRunPolicyLoad) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, CanRunPolicyLoad) {
+  StartThreadGroup();
   test::TestCanRunPolicyLoad(
-      worker_pool_.get(),
+      thread_group_.get(),
       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
       &task_tracker_);
 }
@@ -379,8 +374,8 @@
 // Verify that the maximum number of BEST_EFFORT tasks that can run concurrently
 // in a pool does not affect Sequences with a priority that was increased from
 // BEST_EFFORT to USER_BLOCKING.
-TEST_P(ThreadPoolWorkerPoolTest, UpdatePriorityBestEffortToUserBlocking) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, UpdatePriorityBestEffortToUserBlocking) {
+  StartThreadGroup();
 
   CheckedLock num_tasks_running_lock;
   std::unique_ptr<ConditionVariable> num_tasks_running_cv =
@@ -388,12 +383,12 @@
   size_t num_tasks_running = 0;
 
   // Post |kMaxTasks| BEST_EFFORT tasks that block until they all start running.
-  std::vector<scoped_refptr<SchedulerSequencedTaskRunner>> task_runners;
+  std::vector<scoped_refptr<PooledSequencedTaskRunner>> task_runners;
 
   for (size_t i = 0; i < kMaxTasks; ++i) {
-    task_runners.push_back(MakeRefCounted<SchedulerSequencedTaskRunner>(
+    task_runners.push_back(MakeRefCounted<PooledSequencedTaskRunner>(
         TaskTraits(TaskPriority::BEST_EFFORT),
-        &mock_scheduler_task_runner_delegate_));
+        &mock_pooled_task_runner_delegate_));
     task_runners.back()->PostTask(
         FROM_HERE, BindLambdaForTesting([&]() {
           // Increment the number of tasks running.
@@ -438,10 +433,10 @@
 }
 
 // Regression test for crbug.com/955953.
-TEST_P(ThreadPoolWorkerPoolTest, ScopedBlockingCallTwice) {
-  StartWorkerPool();
+TEST_P(ThreadGroupTest, ScopedBlockingCallTwice) {
+  StartThreadGroup();
   auto task_runner = test::CreateTaskRunnerWithExecutionMode(
-      GetParam().execution_mode, &mock_scheduler_task_runner_delegate_,
+      GetParam().execution_mode, &mock_pooled_task_runner_delegate_,
       {MayBlock()});
 
   WaitableEvent task_ran;
@@ -463,10 +458,10 @@
 }
 
 #if defined(OS_WIN)
-TEST_P(ThreadPoolWorkerPoolTest, COMMTAWorkerEnvironment) {
-  StartWorkerPool(SchedulerWorkerPool::WorkerEnvironment::COM_MTA);
+TEST_P(ThreadGroupTest, COMMTAWorkerEnvironment) {
+  StartThreadGroup(ThreadGroup::WorkerEnvironment::COM_MTA);
   auto task_runner = test::CreateTaskRunnerWithExecutionMode(
-      GetParam().execution_mode, &mock_scheduler_task_runner_delegate_);
+      GetParam().execution_mode, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent task_ran;
   task_runner->PostTask(
@@ -479,10 +474,10 @@
   task_ran.Wait();
 }
 
-TEST_P(ThreadPoolWorkerPoolTest, NoWorkerEnvironment) {
-  StartWorkerPool(SchedulerWorkerPool::WorkerEnvironment::NONE);
+TEST_P(ThreadGroupTest, NoWorkerEnvironment) {
+  StartThreadGroup(ThreadGroup::WorkerEnvironment::NONE);
   auto task_runner = test::CreateTaskRunnerWithExecutionMode(
-      GetParam().execution_mode, &mock_scheduler_task_runner_delegate_);
+      GetParam().execution_mode, &mock_pooled_task_runner_delegate_);
 
   WaitableEvent task_ran;
   task_runner->PostTask(
@@ -497,24 +492,24 @@
 #endif
 
 INSTANTIATE_TEST_SUITE_P(GenericParallel,
-                         ThreadPoolWorkerPoolTest,
+                         ThreadGroupTest,
                          ::testing::Values(PoolExecutionType{
                              test::PoolType::GENERIC,
                              test::ExecutionMode::PARALLEL}));
 INSTANTIATE_TEST_SUITE_P(GenericSequenced,
-                         ThreadPoolWorkerPoolTest,
+                         ThreadGroupTest,
                          ::testing::Values(PoolExecutionType{
                              test::PoolType::GENERIC,
                              test::ExecutionMode::SEQUENCED}));
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
 INSTANTIATE_TEST_SUITE_P(NativeParallel,
-                         ThreadPoolWorkerPoolTest,
+                         ThreadGroupTest,
                          ::testing::Values(PoolExecutionType{
                              test::PoolType::NATIVE,
                              test::ExecutionMode::PARALLEL}));
 INSTANTIATE_TEST_SUITE_P(NativeSequenced,
-                         ThreadPoolWorkerPoolTest,
+                         ThreadGroupTest,
                          ::testing::Values(PoolExecutionType{
                              test::PoolType::NATIVE,
                              test::ExecutionMode::SEQUENCED}));
diff --git a/base/task/thread_pool/thread_pool.cc b/base/task/thread_pool/thread_pool.cc
index 31d67f97..36d9103a 100644
--- a/base/task/thread_pool/thread_pool.cc
+++ b/base/task/thread_pool/thread_pool.cc
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/system/sys_info.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/task/thread_pool/thread_pool_impl.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -24,12 +24,12 @@
 }  // namespace
 
 ThreadPool::InitParams::InitParams(
-    const SchedulerWorkerPoolParams& background_worker_pool_params_in,
-    const SchedulerWorkerPoolParams& foreground_worker_pool_params_in,
-    SharedWorkerPoolEnvironment shared_worker_pool_environment_in)
-    : background_worker_pool_params(background_worker_pool_params_in),
-      foreground_worker_pool_params(foreground_worker_pool_params_in),
-      shared_worker_pool_environment(shared_worker_pool_environment_in) {}
+    const ThreadGroupParams& background_thread_group_params_in,
+    const ThreadGroupParams& foreground_thread_group_params_in,
+    CommonThreadPoolEnvironment common_thread_pool_environment_in)
+    : background_thread_group_params(background_thread_group_params_in),
+      foreground_thread_group_params(foreground_thread_group_params_in),
+      common_thread_pool_environment(common_thread_pool_environment_in) {}
 
 ThreadPool::InitParams::~InitParams() = default;
 
diff --git a/base/task/thread_pool/thread_pool.h b/base/task/thread_pool/thread_pool.h
index 7d361f93..15a71f0 100644
--- a/base/task/thread_pool/thread_pool.h
+++ b/base/task/thread_pool/thread_pool.h
@@ -18,7 +18,7 @@
 #include "base/task/single_thread_task_runner_thread_mode.h"
 #include "base/task/task_executor.h"
 #include "base/task/task_traits.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/task_runner.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -35,7 +35,7 @@
 
 namespace base {
 
-class SchedulerWorkerObserver;
+class WorkerThreadObserver;
 class ThreadPoolTestHelpers;
 
 // Interface for a thread pool and static methods to manage the instance used
@@ -52,25 +52,24 @@
 class BASE_EXPORT ThreadPool : public TaskExecutor {
  public:
   struct BASE_EXPORT InitParams {
-    enum class SharedWorkerPoolEnvironment {
+    enum class CommonThreadPoolEnvironment {
       // Use the default environment (no environment).
       DEFAULT,
 #if defined(OS_WIN)
-      // Place the worker in a COM MTA.
+      // Place the pool's workers in a COM MTA.
       COM_MTA,
 #endif  // defined(OS_WIN)
     };
 
-    InitParams(
-        const SchedulerWorkerPoolParams& background_worker_pool_params_in,
-        const SchedulerWorkerPoolParams& foreground_worker_pool_params_in,
-        SharedWorkerPoolEnvironment shared_worker_pool_environment_in =
-            SharedWorkerPoolEnvironment::DEFAULT);
+    InitParams(const ThreadGroupParams& background_thread_group_params_in,
+               const ThreadGroupParams& foreground_thread_group_params_in,
+               CommonThreadPoolEnvironment common_thread_pool_environment_in =
+                   CommonThreadPoolEnvironment::DEFAULT);
     ~InitParams();
 
-    SchedulerWorkerPoolParams background_worker_pool_params;
-    SchedulerWorkerPoolParams foreground_worker_pool_params;
-    SharedWorkerPoolEnvironment shared_worker_pool_environment;
+    ThreadGroupParams background_thread_group_params;
+    ThreadGroupParams foreground_thread_group_params;
+    CommonThreadPoolEnvironment common_thread_pool_environment;
   };
 
   // A ScopedExecutionFence prevents any new task from being scheduled in
@@ -96,14 +95,14 @@
   // Allows the thread pool to create threads and run tasks following the
   // |init_params| specification.
   //
-  // If specified, |scheduler_worker_observer| will be notified when a worker
+  // If specified, |worker_thread_observer| will be notified when a worker
   // enters and exits its main function. It must not be destroyed before
   // JoinForTesting() has returned (must never be destroyed in production).
   //
   // CHECKs on failure.
   virtual void Start(
       const InitParams& init_params,
-      SchedulerWorkerObserver* scheduler_worker_observer = nullptr) = 0;
+      WorkerThreadObserver* worker_thread_observer = nullptr) = 0;
 
   // Synchronously shuts down the thread pool. Once this is called, only tasks
   // posted with the BLOCK_SHUTDOWN behavior will be run. When this returns:
diff --git a/base/task/thread_pool/thread_pool_impl.cc b/base/task/thread_pool/thread_pool_impl.cc
index ec5fe520..c0dd277 100644
--- a/base/task/thread_pool/thread_pool_impl.cc
+++ b/base/task/thread_pool/thread_pool_impl.cc
@@ -19,23 +19,23 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task/task_features.h"
-#include "base/task/thread_pool/scheduler_parallel_task_runner.h"
-#include "base/task/thread_pool/scheduler_sequenced_task_runner.h"
-#include "base/task/thread_pool/scheduler_worker_pool_impl.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/pooled_parallel_task_runner.h"
+#include "base/task/thread_pool/pooled_sequenced_task_runner.h"
 #include "base/task/thread_pool/sequence_sort_key.h"
 #include "base/task/thread_pool/service_thread.h"
 #include "base/task/thread_pool/task.h"
 #include "base/task/thread_pool/task_source.h"
+#include "base/task/thread_pool/thread_group_impl.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 
 #if defined(OS_WIN)
-#include "base/task/thread_pool/platform_native_worker_pool_win.h"
+#include "base/task/thread_pool/thread_group_native_win.h"
 #endif
 
 #if defined(OS_MACOSX)
-#include "base/task/thread_pool/platform_native_worker_pool_mac.h"
+#include "base/task/thread_pool/thread_group_native_mac.h"
 #endif
 
 namespace base {
@@ -77,15 +77,15 @@
       tracked_ref_factory_(this) {
   DCHECK(!histogram_label.empty());
 
-  foreground_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
+  foreground_pool_ = std::make_unique<ThreadGroupImpl>(
       JoinString(
           {histogram_label, kForegroundPoolEnvironmentParams.name_suffix}, "."),
       kForegroundPoolEnvironmentParams.name_suffix,
       kForegroundPoolEnvironmentParams.priority_hint,
       task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef());
 
-  if (CanUseBackgroundPriorityForSchedulerWorker()) {
-    background_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
+  if (CanUseBackgroundPriorityForWorkerThread()) {
+    background_pool_ = std::make_unique<ThreadGroupImpl>(
         JoinString(
             {histogram_label, kBackgroundPoolEnvironmentParams.name_suffix},
             "."),
@@ -106,7 +106,7 @@
 }
 
 void ThreadPoolImpl::Start(const ThreadPool::InitParams& init_params,
-                           SchedulerWorkerObserver* scheduler_worker_observer) {
+                           WorkerThreadObserver* worker_thread_observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!started_);
 
@@ -119,8 +119,8 @@
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
   if (FeatureList::IsEnabled(kUseNativeThreadPool)) {
-    std::unique_ptr<SchedulerWorkerPool> pool = std::move(foreground_pool_);
-    foreground_pool_ = std::make_unique<PlatformNativeWorkerPoolImpl>(
+    std::unique_ptr<ThreadGroup> pool = std::move(foreground_pool_);
+    foreground_pool_ = std::make_unique<ThreadGroupNativeImpl>(
         task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef(),
         pool.get());
     pool->InvalidateAndHandoffAllTaskSourcesToOtherPool(foreground_pool_.get());
@@ -151,21 +151,21 @@
       service_thread_->task_runner();
   delayed_task_manager_.Start(service_thread_task_runner);
 
-  single_thread_task_runner_manager_.Start(scheduler_worker_observer);
+  single_thread_task_runner_manager_.Start(worker_thread_observer);
 
-  const SchedulerWorkerPool::WorkerEnvironment worker_environment =
+  const ThreadGroup::WorkerEnvironment worker_environment =
 #if defined(OS_WIN)
-      init_params.shared_worker_pool_environment ==
-              InitParams::SharedWorkerPoolEnvironment::COM_MTA
-          ? SchedulerWorkerPool::WorkerEnvironment::COM_MTA
-          : SchedulerWorkerPool::WorkerEnvironment::NONE;
+      init_params.common_thread_pool_environment ==
+              InitParams::CommonThreadPoolEnvironment::COM_MTA
+          ? ThreadGroup::WorkerEnvironment::COM_MTA
+          : ThreadGroup::WorkerEnvironment::NONE;
 #else
-      SchedulerWorkerPool::WorkerEnvironment::NONE;
+      ThreadGroup::WorkerEnvironment::NONE;
 #endif
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
   if (FeatureList::IsEnabled(kUseNativeThreadPool)) {
-    static_cast<PlatformNativeWorkerPool*>(foreground_pool_.get())
+    static_cast<ThreadGroupNative*>(foreground_pool_.get())
         ->Start(worker_environment);
   } else
 #endif
@@ -177,21 +177,21 @@
     // of best-effort tasks.
 
     const int max_best_effort_tasks_in_foreground_pool = std::max(
-        1, std::min(init_params.background_worker_pool_params.max_tasks(),
-                    init_params.foreground_worker_pool_params.max_tasks() / 2));
-    static_cast<SchedulerWorkerPoolImpl*>(foreground_pool_.get())
-        ->Start(init_params.foreground_worker_pool_params,
+        1,
+        std::min(init_params.background_thread_group_params.max_tasks(),
+                 init_params.foreground_thread_group_params.max_tasks() / 2));
+    static_cast<ThreadGroupImpl*>(foreground_pool_.get())
+        ->Start(init_params.foreground_thread_group_params,
                 max_best_effort_tasks_in_foreground_pool,
-                service_thread_task_runner, scheduler_worker_observer,
+                service_thread_task_runner, worker_thread_observer,
                 worker_environment);
   }
 
   if (background_pool_) {
     background_pool_->Start(
-        init_params.background_worker_pool_params,
-        init_params.background_worker_pool_params.max_tasks(),
-        service_thread_task_runner, scheduler_worker_observer,
-        worker_environment);
+        init_params.background_thread_group_params,
+        init_params.background_thread_group_params.max_tasks(),
+        service_thread_task_runner, worker_thread_observer, worker_environment);
   }
 
   started_ = true;
@@ -212,13 +212,13 @@
 scoped_refptr<TaskRunner> ThreadPoolImpl::CreateTaskRunnerWithTraits(
     const TaskTraits& traits) {
   const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
-  return MakeRefCounted<SchedulerParallelTaskRunner>(new_traits, this);
+  return MakeRefCounted<PooledParallelTaskRunner>(new_traits, this);
 }
 
 scoped_refptr<SequencedTaskRunner>
 ThreadPoolImpl::CreateSequencedTaskRunnerWithTraits(const TaskTraits& traits) {
   const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
-  return MakeRefCounted<SchedulerSequencedTaskRunner>(new_traits, this);
+  return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this);
 }
 
 scoped_refptr<SingleThreadTaskRunner>
@@ -244,7 +244,7 @@
 ThreadPoolImpl::CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
     const TaskTraits& traits) {
   const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
-  return MakeRefCounted<SchedulerSequencedTaskRunner>(new_traits, this);
+  return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this);
 }
 
 int ThreadPoolImpl::GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
@@ -252,7 +252,7 @@
   // This method does not support getting the maximum number of BEST_EFFORT
   // tasks that can run concurrently in a pool.
   DCHECK_NE(traits.priority(), TaskPriority::BEST_EFFORT);
-  return GetWorkerPoolForTraits(traits)
+  return GetThreadGroupForTraits(traits)
       ->GetMaxConcurrentNonBlockedTasksDeprecated();
 }
 
@@ -325,7 +325,7 @@
     auto sequence_and_transaction =
         SequenceAndTransaction::FromSequence(std::move(sequence));
     const TaskTraits traits = sequence_and_transaction.transaction.traits();
-    GetWorkerPoolForTraits(traits)->PostTaskWithSequenceNow(
+    GetThreadGroupForTraits(traits)->PostTaskWithSequenceNow(
         std::move(task), std::move(sequence_and_transaction));
   } else {
     // It's safe to take a ref on this pointer since the caller must have a ref
@@ -340,7 +340,7 @@
                   SequenceAndTransaction::FromSequence(std::move(sequence));
               const TaskTraits traits =
                   sequence_and_transaction.transaction.traits();
-              thread_pool_impl->GetWorkerPoolForTraits(traits)
+              thread_pool_impl->GetThreadGroupForTraits(traits)
                   ->PostTaskWithSequenceNow(
                       std::move(task), std::move(sequence_and_transaction));
             },
@@ -352,7 +352,7 @@
 }
 
 bool ThreadPoolImpl::IsRunningPoolWithTraits(const TaskTraits& traits) const {
-  return GetWorkerPoolForTraits(traits)->IsBoundToCurrentThread();
+  return GetThreadGroupForTraits(traits)->IsBoundToCurrentThread();
 }
 
 void ThreadPoolImpl::UpdatePriority(scoped_refptr<TaskSource> task_source,
@@ -360,35 +360,34 @@
   auto task_source_and_transaction =
       TaskSourceAndTransaction::FromTaskSource(std::move(task_source));
 
-  SchedulerWorkerPool* const current_worker_pool =
-      GetWorkerPoolForTraits(task_source_and_transaction.transaction.traits());
+  ThreadGroup* const current_thread_group =
+      GetThreadGroupForTraits(task_source_and_transaction.transaction.traits());
   task_source_and_transaction.transaction.UpdatePriority(priority);
-  SchedulerWorkerPool* const new_worker_pool =
-      GetWorkerPoolForTraits(task_source_and_transaction.transaction.traits());
+  ThreadGroup* const new_thread_group =
+      GetThreadGroupForTraits(task_source_and_transaction.transaction.traits());
 
-  if (new_worker_pool == current_worker_pool) {
+  if (new_thread_group == current_thread_group) {
     // |task_source|'s position needs to be updated within its current pool.
-    current_worker_pool->UpdateSortKey(std::move(task_source_and_transaction));
+    current_thread_group->UpdateSortKey(std::move(task_source_and_transaction));
   } else {
     // |task_source| is changing pools; remove it from its current pool and
     // reenqueue it.
-    const bool task_source_was_found = current_worker_pool->RemoveTaskSource(
+    const bool task_source_was_found = current_thread_group->RemoveTaskSource(
         task_source_and_transaction.task_source);
     if (task_source_was_found) {
       DCHECK(task_source_and_transaction.task_source);
-      new_worker_pool->PushTaskSourceAndWakeUpWorkers(
+      new_thread_group->PushTaskSourceAndWakeUpWorkers(
           std::move(task_source_and_transaction));
     }
   }
 }
 
-const SchedulerWorkerPool* ThreadPoolImpl::GetWorkerPoolForTraits(
+const ThreadGroup* ThreadPoolImpl::GetThreadGroupForTraits(
     const TaskTraits& traits) const {
-  return const_cast<ThreadPoolImpl*>(this)->GetWorkerPoolForTraits(traits);
+  return const_cast<ThreadPoolImpl*>(this)->GetThreadGroupForTraits(traits);
 }
 
-SchedulerWorkerPool* ThreadPoolImpl::GetWorkerPoolForTraits(
-    const TaskTraits& traits) {
+ThreadGroup* ThreadPoolImpl::GetThreadGroupForTraits(const TaskTraits& traits) {
   if (traits.priority() == TaskPriority::BEST_EFFORT && background_pool_) {
     return background_pool_.get();
   }
diff --git a/base/task/thread_pool/thread_pool_impl.h b/base/task/thread_pool/thread_pool_impl.h
index a6e272c..3bbd027 100644
--- a/base/task/thread_pool/thread_pool_impl.h
+++ b/base/task/thread_pool/thread_pool_impl.h
@@ -21,11 +21,11 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/delayed_task_manager.h"
 #include "base/task/thread_pool/environment_config.h"
-#include "base/task/thread_pool/scheduler_single_thread_task_runner_manager.h"
-#include "base/task/thread_pool/scheduler_task_runner_delegate.h"
-#include "base/task/thread_pool/scheduler_worker_pool.h"
-#include "base/task/thread_pool/scheduler_worker_pool_impl.h"
+#include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h"
+#include "base/task/thread_pool/pooled_task_runner_delegate.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/thread_group.h"
+#include "base/task/thread_pool/thread_group_impl.h"
 #include "base/task/thread_pool/thread_pool.h"
 #include "base/updateable_sequenced_task_runner.h"
 #include "build/build_config.h"
@@ -46,8 +46,8 @@
 
 // Default ThreadPool implementation. This class is thread-safe.
 class BASE_EXPORT ThreadPoolImpl : public ThreadPool,
-                                   public SchedulerWorkerPool::Delegate,
-                                   public SchedulerTaskRunnerDelegate {
+                                   public ThreadGroup::Delegate,
+                                   public PooledTaskRunnerDelegate {
  public:
   using TaskTrackerImpl =
 #if defined(OS_POSIX) && !defined(OS_NACL_SFI)
@@ -68,7 +68,7 @@
 
   // ThreadPool:
   void Start(const ThreadPool::InitParams& init_params,
-             SchedulerWorkerObserver* scheduler_worker_observer) override;
+             WorkerThreadObserver* worker_thread_observer) override;
   int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
       const TaskTraits& traits) const override;
   void Shutdown() override;
@@ -110,14 +110,12 @@
 
   void ReportHeartbeatMetrics() const;
 
-  const SchedulerWorkerPool* GetWorkerPoolForTraits(
-      const TaskTraits& traits) const;
+  const ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) const;
 
-  // SchedulerWorkerPool::Delegate:
-  SchedulerWorkerPool* GetWorkerPoolForTraits(
-      const TaskTraits& traits) override;
+  // ThreadGroup::Delegate:
+  ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) override;
 
-  // SchedulerTaskRunnerDelegate:
+  // PooledTaskRunnerDelegate:
   bool PostTaskWithSequence(Task task,
                             scoped_refptr<Sequence> sequence) override;
   bool IsRunningPoolWithTraits(const TaskTraits& traits) const override;
@@ -127,7 +125,7 @@
   const std::unique_ptr<TaskTrackerImpl> task_tracker_;
   std::unique_ptr<Thread> service_thread_;
   DelayedTaskManager delayed_task_manager_;
-  SchedulerSingleThreadTaskRunnerManager single_thread_task_runner_manager_;
+  PooledSingleThreadTaskRunnerManager single_thread_task_runner_manager_;
 
   // Indicates that all tasks are handled as if they had been posted with
   // TaskPriority::USER_BLOCKING. Since this is set in Start(), it doesn't apply
@@ -137,8 +135,8 @@
   // TODO(fdoray): Remove after experiment. https://crbug.com/757022
   AtomicFlag all_tasks_user_blocking_;
 
-  std::unique_ptr<SchedulerWorkerPool> foreground_pool_;
-  std::unique_ptr<SchedulerWorkerPoolImpl> background_pool_;
+  std::unique_ptr<ThreadGroup> foreground_pool_;
+  std::unique_ptr<ThreadGroupImpl> background_pool_;
 
   // Whether this TaskScheduler was started. Access controlled by
   // |sequence_checker_|.
@@ -162,7 +160,7 @@
   // Asserts that operations occur in sequence with Start().
   SEQUENCE_CHECKER(sequence_checker_);
 
-  TrackedRefFactory<SchedulerWorkerPool::Delegate> tracked_ref_factory_;
+  TrackedRefFactory<ThreadGroup::Delegate> tracked_ref_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ThreadPoolImpl);
 };
diff --git a/base/task/thread_pool/thread_pool_impl_unittest.cc b/base/task/thread_pool/thread_pool_impl_unittest.cc
index d3b7dd6..50fee5f 100644
--- a/base/task/thread_pool/thread_pool_impl_unittest.cc
+++ b/base/task/thread_pool/thread_pool_impl_unittest.cc
@@ -23,10 +23,10 @@
 #include "base/task/task_features.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool/environment_config.h"
-#include "base/task/thread_pool/scheduler_worker_observer.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
 #include "base/task/thread_pool/test_task_factory.h"
 #include "base/task/thread_pool/test_utils.h"
+#include "base/task/thread_pool/thread_group_params.h"
+#include "base/task/thread_pool/worker_thread_observer.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/gtest_util.h"
 #include "base/test/scoped_feature_list.h"
@@ -83,7 +83,7 @@
 // to run a Task with |traits|.
 // Note: ExecutionMode is verified inside TestTaskFactory.
 void VerifyTaskEnvironment(const TaskTraits& traits, test::PoolType pool_type) {
-  EXPECT_EQ(CanUseBackgroundPriorityForSchedulerWorker() &&
+  EXPECT_EQ(CanUseBackgroundPriorityForWorkerThread() &&
                     traits.priority() == TaskPriority::BEST_EFFORT
                 ? ThreadPriority::BACKGROUND
                 : ThreadPriority::NORMAL,
@@ -125,7 +125,7 @@
   } else {
     EXPECT_NE(std::string::npos,
               current_thread_name.find(
-                  CanUseBackgroundPriorityForSchedulerWorker() && is_best_effort
+                  CanUseBackgroundPriorityForWorkerThread() && is_best_effort
                       ? "Background"
                       : "Foreground"));
 
@@ -261,9 +261,9 @@
     should_enable_all_tasks_user_blocking_ = true;
   }
 
-  void set_scheduler_worker_observer(
-      SchedulerWorkerObserver* scheduler_worker_observer) {
-    scheduler_worker_observer_ = scheduler_worker_observer;
+  void set_worker_thread_observer(
+      WorkerThreadObserver* worker_thread_observer) {
+    worker_thread_observer_ = worker_thread_observer;
   }
 
   void StartThreadPool(TimeDelta reclaim_time = TimeDelta::FromSeconds(30)) {
@@ -274,7 +274,7 @@
 
     thread_pool_.Start({{kMaxNumBackgroundThreads, reclaim_time},
                         {kMaxNumForegroundThreads, reclaim_time}},
-                       scheduler_worker_observer_);
+                       worker_thread_observer_);
   }
 
   void TearDown() override {
@@ -305,7 +305,7 @@
   }
 
   base::test::ScopedFeatureList feature_list_;
-  SchedulerWorkerObserver* scheduler_worker_observer_ = nullptr;
+  WorkerThreadObserver* worker_thread_observer_ = nullptr;
   bool did_tear_down_ = false;
   bool should_enable_all_tasks_user_blocking_ = false;
 
@@ -564,7 +564,7 @@
   did_run.Wait();
 }
 
-INSTANTIATE_TEST_SUITE_P(OneThreadPoolImplTestParams,
+INSTANTIATE_TEST_SUITE_P(,
                          ThreadPoolImplTest,
                          ::testing::ValuesIn(GetThreadPoolImplTestParams()));
 
@@ -804,7 +804,7 @@
   const std::string stack = debug::StackTrace().ToString();
   SCOPED_TRACE(stack);
   const bool stack_has_symbols =
-      stack.find("SchedulerWorker") != std::string::npos;
+      stack.find("WorkerThread") != std::string::npos;
   if (!stack_has_symbols)
     return;
 
@@ -910,9 +910,9 @@
   thread_pool_.FlushForTesting();
 }
 
-TEST_P(ThreadPoolImplTest, SchedulerWorkerObserver) {
+TEST_P(ThreadPoolImplTest, WorkerThreadObserver) {
 #if defined(OS_WIN) || defined(OS_MACOSX)
-  // SchedulerWorkers are not created (and hence not observed) when using the
+  // WorkerThreads are not created (and hence not observed) when using the
   // native thread pools. We still start the ThreadPool in this case since
   // JoinForTesting is always called on TearDown, and DCHECKs that all worker
   // pools are started.
@@ -922,13 +922,13 @@
   }
 #endif
 
-  testing::StrictMock<test::MockSchedulerWorkerObserver> observer;
-  set_scheduler_worker_observer(&observer);
+  testing::StrictMock<test::MockWorkerThreadObserver> observer;
+  set_worker_thread_observer(&observer);
 
   // A worker should be created for each pool. After that, 4 threads should be
   // created for each SingleThreadTaskRunnerThreadMode (8 on Windows).
   const int kExpectedNumPoolWorkers =
-      CanUseBackgroundPriorityForSchedulerWorker() ? 2 : 1;
+      CanUseBackgroundPriorityForWorkerThread() ? 2 : 1;
 #if defined(OS_WIN)
   const int kExpectedNumSingleThreadedWorkersPerMode = 8;
 #else
@@ -936,13 +936,13 @@
 #endif
   constexpr int kNumSingleThreadTaskRunnerThreadModes = 2;
 
-  EXPECT_CALL(observer, OnSchedulerWorkerMainEntry())
+  EXPECT_CALL(observer, OnWorkerThreadMainEntry())
       .Times(kExpectedNumPoolWorkers +
              kNumSingleThreadTaskRunnerThreadModes *
                  kExpectedNumSingleThreadedWorkersPerMode);
 
   // Infinite detach time to prevent workers from invoking
-  // OnSchedulerWorkerMainExit() earlier than expected.
+  // OnWorkerThreadMainExit() earlier than expected.
   StartThreadPool(TimeDelta::Max());
 
   std::vector<scoped_refptr<SingleThreadTaskRunner>> task_runners;
@@ -1001,13 +1001,13 @@
     task_runner->PostTask(FROM_HERE, DoNothing());
 
   // Release single-threaded workers. This should cause dedicated workers to
-  // invoke OnSchedulerWorkerMainExit().
+  // invoke OnWorkerThreadMainExit().
   observer.AllowCallsOnMainExit(kExpectedNumSingleThreadedWorkersPerMode);
   task_runners.clear();
   observer.WaitCallsOnMainExit();
 
   // Join all remaining workers. This should cause shared single-threaded
-  // workers and pool workers to invoke OnSchedulerWorkerMainExit().
+  // workers and pool workers to invoke OnWorkerThreadMainExit().
   observer.AllowCallsOnMainExit(kExpectedNumPoolWorkers +
                                 kExpectedNumSingleThreadedWorkersPerMode);
   TearDown();
@@ -1118,7 +1118,7 @@
         thread_pool_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
             TaskTraits({TaskPriority::USER_BLOCKING})),
         TaskPriority::BEST_EFFORT,
-        CanUseBackgroundPriorityForSchedulerWorker()
+        CanUseBackgroundPriorityForWorkerThread()
             ? nullptr
             : &task_runners_and_events_.back()->task_ran));
   }
@@ -1149,7 +1149,7 @@
 
   pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
       TaskTraits({TaskPriority::USER_BLOCKING})));
-  if (CanUseBackgroundPriorityForSchedulerWorker()) {
+  if (CanUseBackgroundPriorityForWorkerThread()) {
     pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
         TaskTraits({TaskPriority::BEST_EFFORT})));
   }
@@ -1257,7 +1257,7 @@
   }
 }
 
-INSTANTIATE_TEST_SUITE_P(OneThreadPoolPriorityUpdateTestParams,
+INSTANTIATE_TEST_SUITE_P(,
                          ThreadPoolPriorityUpdateTest,
                          ::testing::ValuesIn(GetThreadPoolImplTestParams()));
 
diff --git a/base/task/thread_pool/tracked_ref.h b/base/task/thread_pool/tracked_ref.h
index 4fc29faf..89c397f 100644
--- a/base/task/thread_pool/tracked_ref.h
+++ b/base/task/thread_pool/tracked_ref.h
@@ -43,7 +43,7 @@
 // however we must JoinForTesting(). At that point, all the raw back T* refs
 // used by the worker threads are problematic because they can result in use-
 // after-frees if a worker outlives the deletion of its corresponding
-// ThreadPool/TaskTracker/SchedulerWorkerPool/etc.
+// ThreadPool/TaskTracker/ThreadGroup/etc.
 //
 // JoinForTesting() isn't so hard when all workers are managed. But with cleanup
 // semantics (reclaiming a worker who's been idle for too long) it becomes
diff --git a/base/task/thread_pool/scheduler_worker.cc b/base/task/thread_pool/worker_thread.cc
similarity index 73%
rename from base/task/thread_pool/scheduler_worker.cc
rename to base/task/thread_pool/worker_thread.cc
index 83309f747..b860645b 100644
--- a/base/task/thread_pool/scheduler_worker.cc
+++ b/base/task/thread_pool/worker_thread.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 "base/task/thread_pool/scheduler_worker.h"
+#include "base/task/thread_pool/worker_thread.h"
 
 #include <stddef.h>
 
@@ -12,8 +12,8 @@
 #include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/task/thread_pool/environment_config.h"
-#include "base/task/thread_pool/scheduler_worker_observer.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/worker_thread_observer.h"
 #include "base/trace_event/trace_event.h"
 
 #if defined(OS_MACOSX)
@@ -26,7 +26,7 @@
 namespace base {
 namespace internal {
 
-void SchedulerWorker::Delegate::WaitForWork(WaitableEvent* wake_up_event) {
+void WorkerThread::Delegate::WaitForWork(WaitableEvent* wake_up_event) {
   DCHECK(wake_up_event);
   const TimeDelta sleep_time = GetSleepTimeout();
   if (sleep_time.is_max()) {
@@ -38,12 +38,12 @@
   }
 }
 
-SchedulerWorker::SchedulerWorker(
+WorkerThread::WorkerThread(
     ThreadPriority priority_hint,
     std::unique_ptr<Delegate> delegate,
     TrackedRef<TaskTracker> task_tracker,
     const CheckedLock* predecessor_lock,
-    SchedulerBackwardCompatibility backward_compatibility)
+    WorkerThreadBackwardCompatibility backward_compatibility)
     : thread_lock_(predecessor_lock),
       delegate_(std::move(delegate)),
       task_tracker_(std::move(task_tracker)),
@@ -56,13 +56,12 @@
 {
   DCHECK(delegate_);
   DCHECK(task_tracker_);
-  DCHECK(CanUseBackgroundPriorityForSchedulerWorker() ||
+  DCHECK(CanUseBackgroundPriorityForWorkerThread() ||
          priority_hint_ != ThreadPriority::BACKGROUND);
   wake_up_event_.declare_only_used_while_idle();
 }
 
-bool SchedulerWorker::Start(
-    SchedulerWorkerObserver* scheduler_worker_observer) {
+bool WorkerThread::Start(WorkerThreadObserver* worker_thread_observer) {
   CheckedLock::AssertNoLockHeldOnCurrentThread();
   CheckedAutoLock auto_lock(thread_lock_);
   DCHECK(thread_handle_.is_null());
@@ -70,8 +69,8 @@
   if (should_exit_.IsSet() || join_called_for_testing_.IsSet())
     return true;
 
-  DCHECK(!scheduler_worker_observer_);
-  scheduler_worker_observer_ = scheduler_worker_observer;
+  DCHECK(!worker_thread_observer_);
+  worker_thread_observer_ = worker_thread_observer;
 
   self_ = this;
 
@@ -87,19 +86,19 @@
   return true;
 }
 
-void SchedulerWorker::WakeUp() {
+void WorkerThread::WakeUp() {
   // Signalling an event can deschedule the current thread. Since being
   // descheduled while holding a lock is undesirable (https://crbug.com/890978),
   // assert that no lock is held by the current thread.
   CheckedLock::AssertNoLockHeldOnCurrentThread();
   // Calling WakeUp() after Cleanup() or Join() is wrong because the
-  // SchedulerWorker cannot run more tasks.
+  // WorkerThread cannot run more tasks.
   DCHECK(!join_called_for_testing_.IsSet());
   DCHECK(!should_exit_.IsSet());
   wake_up_event_.Signal();
 }
 
-void SchedulerWorker::JoinForTesting() {
+void WorkerThread::JoinForTesting() {
   DCHECK(!join_called_for_testing_.IsSet());
   join_called_for_testing_.Set();
   wake_up_event_.Signal();
@@ -120,12 +119,12 @@
   PlatformThread::Join(thread_handle);
 }
 
-bool SchedulerWorker::ThreadAliveForTesting() const {
+bool WorkerThread::ThreadAliveForTesting() const {
   CheckedAutoLock auto_lock(thread_lock_);
   return !thread_handle_.is_null();
 }
 
-SchedulerWorker::~SchedulerWorker() {
+WorkerThread::~WorkerThread() {
   CheckedAutoLock auto_lock(thread_lock_);
 
   // If |thread_handle_| wasn't joined, detach it.
@@ -135,39 +134,39 @@
   }
 }
 
-void SchedulerWorker::Cleanup() {
+void WorkerThread::Cleanup() {
   DCHECK(!should_exit_.IsSet());
   should_exit_.Set();
   wake_up_event_.Signal();
 }
 
-void SchedulerWorker::BeginUnusedPeriod() {
+void WorkerThread::BeginUnusedPeriod() {
   CheckedAutoLock auto_lock(thread_lock_);
   DCHECK(last_used_time_.is_null());
   last_used_time_ = TimeTicks::Now();
 }
 
-void SchedulerWorker::EndUnusedPeriod() {
+void WorkerThread::EndUnusedPeriod() {
   CheckedAutoLock auto_lock(thread_lock_);
   DCHECK(!last_used_time_.is_null());
   last_used_time_ = TimeTicks();
 }
 
-TimeTicks SchedulerWorker::GetLastUsedTime() const {
+TimeTicks WorkerThread::GetLastUsedTime() const {
   CheckedAutoLock auto_lock(thread_lock_);
   return last_used_time_;
 }
 
-bool SchedulerWorker::ShouldExit() const {
-  // The ordering of the checks is important below. This SchedulerWorker may be
+bool WorkerThread::ShouldExit() const {
+  // The ordering of the checks is important below. This WorkerThread may be
   // released and outlive |task_tracker_| in unit tests. However, when the
-  // SchedulerWorker is released, |should_exit_| will be set, so check that
+  // WorkerThread is released, |should_exit_| will be set, so check that
   // first.
   return should_exit_.IsSet() || join_called_for_testing_.IsSet() ||
          task_tracker_->IsShutdownComplete();
 }
 
-ThreadPriority SchedulerWorker::GetDesiredThreadPriority() const {
+ThreadPriority WorkerThread::GetDesiredThreadPriority() const {
   // To avoid shutdown hangs, disallow a priority below NORMAL during shutdown
   if (task_tracker_->HasShutdownStarted())
     return ThreadPriority::NORMAL;
@@ -175,7 +174,7 @@
   return priority_hint_;
 }
 
-void SchedulerWorker::UpdateThreadPriority(
+void WorkerThread::UpdateThreadPriority(
     ThreadPriority desired_thread_priority) {
   if (desired_thread_priority == current_thread_priority_)
     return;
@@ -184,7 +183,7 @@
   current_thread_priority_ = desired_thread_priority;
 }
 
-void SchedulerWorker::ThreadMain() {
+void WorkerThread::ThreadMain() {
   if (priority_hint_ == ThreadPriority::BACKGROUND) {
     switch (delegate_->GetThreadLabel()) {
       case ThreadLabel::POOLED:
@@ -228,92 +227,93 @@
   }
 }
 
-NOINLINE void SchedulerWorker::RunPooledWorker() {
+NOINLINE void WorkerThread::RunPooledWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunBackgroundPooledWorker() {
+NOINLINE void WorkerThread::RunBackgroundPooledWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunSharedWorker() {
+NOINLINE void WorkerThread::RunSharedWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunBackgroundSharedWorker() {
+NOINLINE void WorkerThread::RunBackgroundSharedWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunDedicatedWorker() {
+NOINLINE void WorkerThread::RunDedicatedWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunBackgroundDedicatedWorker() {
+NOINLINE void WorkerThread::RunBackgroundDedicatedWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
 #if defined(OS_WIN)
-NOINLINE void SchedulerWorker::RunSharedCOMWorker() {
+NOINLINE void WorkerThread::RunSharedCOMWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunBackgroundSharedCOMWorker() {
+NOINLINE void WorkerThread::RunBackgroundSharedCOMWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunDedicatedCOMWorker() {
+NOINLINE void WorkerThread::RunDedicatedCOMWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 
-NOINLINE void SchedulerWorker::RunBackgroundDedicatedCOMWorker() {
+NOINLINE void WorkerThread::RunBackgroundDedicatedCOMWorker() {
   const int line_number = __LINE__;
   RunWorker();
   base::debug::Alias(&line_number);
 }
 #endif  // defined(OS_WIN)
 
-void SchedulerWorker::RunWorker() {
+void WorkerThread::RunWorker() {
   DCHECK_EQ(self_, this);
-  TRACE_EVENT_INSTANT0("thread_pool", "SchedulerWorkerThread born",
+  TRACE_EVENT_INSTANT0("thread_pool", "WorkerThreadThread born",
                        TRACE_EVENT_SCOPE_THREAD);
-  TRACE_EVENT_BEGIN0("thread_pool", "SchedulerWorkerThread active");
+  TRACE_EVENT_BEGIN0("thread_pool", "WorkerThreadThread active");
 
-  if (scheduler_worker_observer_)
-    scheduler_worker_observer_->OnSchedulerWorkerMainEntry();
+  if (worker_thread_observer_)
+    worker_thread_observer_->OnWorkerThreadMainEntry();
 
   delegate_->OnMainEntry(this);
 
-  // A SchedulerWorker starts out waiting for work.
+  // A WorkerThread starts out waiting for work.
   {
-    TRACE_EVENT_END0("thread_pool", "SchedulerWorkerThread active");
+    TRACE_EVENT_END0("thread_pool", "WorkerThreadThread active");
     delegate_->WaitForWork(&wake_up_event_);
-    TRACE_EVENT_BEGIN0("thread_pool", "SchedulerWorkerThread active");
+    TRACE_EVENT_BEGIN0("thread_pool", "WorkerThreadThread active");
   }
 
 // When defined(COM_INIT_CHECK_HOOK_ENABLED), ignore
-// SchedulerBackwardCompatibility::INIT_COM_STA to find incorrect uses of
+// WorkerThreadBackwardCompatibility::INIT_COM_STA to find incorrect uses of
 // COM that should be running in a COM STA Task Runner.
 #if defined(OS_WIN) && !defined(COM_INIT_CHECK_HOOK_ENABLED)
   std::unique_ptr<win::ScopedCOMInitializer> com_initializer;
-  if (backward_compatibility_ == SchedulerBackwardCompatibility::INIT_COM_STA)
+  if (backward_compatibility_ ==
+      WorkerThreadBackwardCompatibility::INIT_COM_STA)
     com_initializer = std::make_unique<win::ScopedCOMInitializer>();
 #endif
 
@@ -331,9 +331,9 @@
       if (ShouldExit())
         break;
 
-      TRACE_EVENT_END0("thread_pool", "SchedulerWorkerThread active");
+      TRACE_EVENT_END0("thread_pool", "WorkerThreadThread active");
       delegate_->WaitForWork(&wake_up_event_);
-      TRACE_EVENT_BEGIN0("thread_pool", "SchedulerWorkerThread active");
+      TRACE_EVENT_BEGIN0("thread_pool", "WorkerThreadThread active");
       continue;
     }
 
@@ -341,11 +341,11 @@
 
     delegate_->DidRunTask(std::move(task_source));
 
-    // Calling WakeUp() guarantees that this SchedulerWorker will run Tasks from
+    // Calling WakeUp() guarantees that this WorkerThread will run Tasks from
     // TaskSources returned by the GetWork() method of |delegate_| until it
     // returns nullptr. Resetting |wake_up_event_| here doesn't break this
     // invariant and avoids a useless loop iteration before going to sleep if
-    // WakeUp() is called while this SchedulerWorker is awake.
+    // WakeUp() is called while this WorkerThread is awake.
     wake_up_event_.Reset();
   }
 
@@ -354,15 +354,15 @@
 
   delegate_->OnMainExit(this);
 
-  if (scheduler_worker_observer_)
-    scheduler_worker_observer_->OnSchedulerWorkerMainExit();
+  if (worker_thread_observer_)
+    worker_thread_observer_->OnWorkerThreadMainExit();
 
   // Release the self-reference to |this|. This can result in deleting |this|
   // and as such no more member accesses should be made after this point.
   self_ = nullptr;
 
-  TRACE_EVENT_END0("thread_pool", "SchedulerWorkerThread active");
-  TRACE_EVENT_INSTANT0("thread_pool", "SchedulerWorkerThread dead",
+  TRACE_EVENT_END0("thread_pool", "WorkerThreadThread active");
+  TRACE_EVENT_INSTANT0("thread_pool", "WorkerThreadThread dead",
                        TRACE_EVENT_SCOPE_THREAD);
 }
 
diff --git a/base/task/thread_pool/scheduler_worker.h b/base/task/thread_pool/worker_thread.h
similarity index 70%
rename from base/task/thread_pool/scheduler_worker.h
rename to base/task/thread_pool/worker_thread.h
index f85e8583..f7dbd8e 100644
--- a/base/task/thread_pool/scheduler_worker.h
+++ b/base/task/thread_pool/worker_thread.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 BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_H_
+#ifndef BASE_TASK_THREAD_POOL_WORKER_THREAD_H_
+#define BASE_TASK_THREAD_POOL_WORKER_THREAD_H_
 
 #include <memory>
 
@@ -13,9 +13,9 @@
 #include "base/synchronization/atomic_flag.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/common/checked_lock.h"
-#include "base/task/thread_pool/scheduler_worker_params.h"
 #include "base/task/thread_pool/task_source.h"
 #include "base/task/thread_pool/tracked_ref.h"
+#include "base/task/thread_pool/worker_thread_params.h"
 #include "base/thread_annotations.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -27,7 +27,7 @@
 
 namespace base {
 
-class SchedulerWorkerObserver;
+class WorkerThreadObserver;
 
 namespace internal {
 
@@ -36,18 +36,17 @@
 // A worker that manages a single thread to run Tasks from TaskSources returned
 // by a delegate.
 //
-// A SchedulerWorker starts out sleeping. It is woken up by a call to WakeUp().
-// After a wake-up, a SchedulerWorker runs Tasks from TaskSources returned by
+// A WorkerThread starts out sleeping. It is woken up by a call to WakeUp().
+// After a wake-up, a WorkerThread runs Tasks from TaskSources returned by
 // the GetWork() method of its delegate as long as it doesn't return nullptr. It
 // also periodically checks with its TaskTracker whether shutdown has completed
 // and exits when it has.
 //
 // This class is thread-safe.
-class BASE_EXPORT SchedulerWorker
-    : public RefCountedThreadSafe<SchedulerWorker>,
-      public PlatformThread::Delegate {
+class BASE_EXPORT WorkerThread : public RefCountedThreadSafe<WorkerThread>,
+                                 public PlatformThread::Delegate {
  public:
-  // Labels this SchedulerWorker's association. This doesn't affect any logic
+  // Labels this WorkerThread's association. This doesn't affect any logic
   // but will add a stack frame labeling this thread for ease of stack trace
   // identification.
   enum class ThreadLabel {
@@ -60,23 +59,23 @@
 #endif  // defined(OS_WIN)
   };
 
-  // Delegate interface for SchedulerWorker. All methods are called from the
-  // thread managed by the SchedulerWorker instance.
+  // Delegate interface for WorkerThread. All methods are called from the
+  // thread managed by the WorkerThread instance.
   class BASE_EXPORT Delegate {
    public:
     virtual ~Delegate() = default;
 
-    // Returns the ThreadLabel the Delegate wants its SchedulerWorkers' stacks
+    // Returns the ThreadLabel the Delegate wants its WorkerThreads' stacks
     // to be labeled with.
     virtual ThreadLabel GetThreadLabel() const = 0;
 
     // Called by |worker|'s thread when it enters its main function.
-    virtual void OnMainEntry(const SchedulerWorker* worker) = 0;
+    virtual void OnMainEntry(const WorkerThread* worker) = 0;
 
     // Called by |worker|'s thread to get a TaskSource from which to run a Task.
-    virtual scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) = 0;
+    virtual scoped_refptr<TaskSource> GetWork(WorkerThread* worker) = 0;
 
-    // Called by the SchedulerWorker after it ran a Task. If the Task's
+    // Called by the WorkerThread after it ran a Task. If the Task's
     // TaskSource should be reenqueued, it is passed to |task_source|.
     // Otherwise, |task_source| is nullptr.
     virtual void DidRunTask(scoped_refptr<TaskSource> task_source) = 0;
@@ -86,53 +85,53 @@
     // WakeUp() method is called.
     virtual TimeDelta GetSleepTimeout() = 0;
 
-    // Called by the SchedulerWorker's thread to wait for work. Override this
+    // Called by the WorkerThread's thread to wait for work. Override this
     // method if the thread in question needs special handling to go to sleep.
     // |wake_up_event| is a manually resettable event and is signaled on
-    // SchedulerWorker::WakeUp()
+    // WorkerThread::WakeUp()
     virtual void WaitForWork(WaitableEvent* wake_up_event);
 
     // Called by |worker|'s thread right before the main function exits. The
     // Delegate is free to release any associated resources in this call. It is
-    // guaranteed that SchedulerWorker won't access the Delegate or the
+    // guaranteed that WorkerThread won't access the Delegate or the
     // TaskTracker after calling OnMainExit() on the Delegate.
-    virtual void OnMainExit(SchedulerWorker* worker) {}
+    virtual void OnMainExit(WorkerThread* worker) {}
   };
 
-  // Creates a SchedulerWorker that runs Tasks from TaskSources returned by
-  // |delegate|. No actual thread will be created for this SchedulerWorker
+  // Creates a WorkerThread that runs Tasks from TaskSources returned by
+  // |delegate|. No actual thread will be created for this WorkerThread
   // before Start() is called. |priority_hint| is the preferred thread priority;
   // the actual thread priority depends on shutdown state and platform
   // capabilities. |task_tracker| is used to handle shutdown behavior of Tasks.
   // |predecessor_lock| is a lock that is allowed to be held when calling
-  // methods on this SchedulerWorker. |backward_compatibility| indicates
+  // methods on this WorkerThread. |backward_compatibility| indicates
   // whether backward compatibility is enabled. Either JoinForTesting() or
   // Cleanup() must be called before releasing the last external reference.
-  SchedulerWorker(ThreadPriority priority_hint,
-                  std::unique_ptr<Delegate> delegate,
-                  TrackedRef<TaskTracker> task_tracker,
-                  const CheckedLock* predecessor_lock = nullptr,
-                  SchedulerBackwardCompatibility backward_compatibility =
-                      SchedulerBackwardCompatibility::DISABLED);
+  WorkerThread(ThreadPriority priority_hint,
+               std::unique_ptr<Delegate> delegate,
+               TrackedRef<TaskTracker> task_tracker,
+               const CheckedLock* predecessor_lock = nullptr,
+               WorkerThreadBackwardCompatibility backward_compatibility =
+                   WorkerThreadBackwardCompatibility::DISABLED);
 
-  // Creates a thread to back the SchedulerWorker. The thread will be in a wait
+  // Creates a thread to back the WorkerThread. The thread will be in a wait
   // state pending a WakeUp() call. No thread will be created if Cleanup() was
-  // called. If specified, |scheduler_worker_observer| will be notified when the
+  // called. If specified, |worker_thread_observer| will be notified when the
   // worker enters and exits its main function. It must not be destroyed before
   // JoinForTesting() has returned (must never be destroyed in production).
   // Returns true on success.
-  bool Start(SchedulerWorkerObserver* scheduler_worker_observer = nullptr);
+  bool Start(WorkerThreadObserver* worker_thread_observer = nullptr);
 
-  // Wakes up this SchedulerWorker if it wasn't already awake. After this is
-  // called, this SchedulerWorker will run Tasks from TaskSources returned by
+  // Wakes up this WorkerThread if it wasn't already awake. After this is
+  // called, this WorkerThread will run Tasks from TaskSources returned by
   // the GetWork() method of its delegate until it returns nullptr. No-op if
   // Start() wasn't called. DCHECKs if called after Start() has failed or after
   // Cleanup() has been called.
   void WakeUp();
 
-  SchedulerWorker::Delegate* delegate() { return delegate_.get(); }
+  WorkerThread::Delegate* delegate() { return delegate_.get(); }
 
-  // Joins this SchedulerWorker. If a Task is already running, it will be
+  // Joins this WorkerThread. If a Task is already running, it will be
   // allowed to complete its execution. This can only be called once.
   //
   // Note: A thread that detaches before JoinForTesting() is called may still be
@@ -149,24 +148,24 @@
   // undefined.
   //
   // Expected Usage:
-  //   scoped_refptr<SchedulerWorker> worker_ = /* Existing Worker */
+  //   scoped_refptr<WorkerThread> worker_ = /* Existing Worker */
   //   worker_->Cleanup();
   //   worker_ = nullptr;
   void Cleanup();
 
-  // Informs this SchedulerWorker about periods during which it is not being
+  // Informs this WorkerThread about periods during which it is not being
   // used. Thread-safe.
   void BeginUnusedPeriod();
   void EndUnusedPeriod();
-  // Returns the last time this SchedulerWorker was used. Returns a null time if
-  // this SchedulerWorker is currently in-use. Thread-safe.
+  // Returns the last time this WorkerThread was used. Returns a null time if
+  // this WorkerThread is currently in-use. Thread-safe.
   TimeTicks GetLastUsedTime() const;
 
  private:
-  friend class RefCountedThreadSafe<SchedulerWorker>;
+  friend class RefCountedThreadSafe<WorkerThread>;
   class Thread;
 
-  ~SchedulerWorker() override;
+  ~WorkerThread() override;
 
   bool ShouldExit() const;
 
@@ -206,7 +205,7 @@
   // Set in Start() before creating the thread. Reset in ThreadMain() before the
   // thread exits. No lock required because the first access occurs before the
   // thread is created and the second access occurs on the thread.
-  scoped_refptr<SchedulerWorker> self_;
+  scoped_refptr<WorkerThread> self_;
 
   mutable CheckedLock thread_lock_;
 
@@ -229,7 +228,7 @@
 
   // Optional observer notified when a worker enters and exits its main
   // function. Set in Start() and never modified afterwards.
-  SchedulerWorkerObserver* scheduler_worker_observer_ = nullptr;
+  WorkerThreadObserver* worker_thread_observer_ = nullptr;
 
   // Desired thread priority.
   const ThreadPriority priority_hint_;
@@ -240,16 +239,16 @@
   ThreadPriority current_thread_priority_;
 
 #if defined(OS_WIN) && !defined(COM_INIT_CHECK_HOOK_ENABLED)
-  const SchedulerBackwardCompatibility backward_compatibility_;
+  const WorkerThreadBackwardCompatibility backward_compatibility_;
 #endif
 
   // Set once JoinForTesting() has been called.
   AtomicFlag join_called_for_testing_;
 
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorker);
+  DISALLOW_COPY_AND_ASSIGN(WorkerThread);
 };
 
 }  // namespace internal
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_H_
+#endif  // BASE_TASK_THREAD_POOL_WORKER_THREAD_H_
diff --git a/base/task/thread_pool/worker_thread_observer.h b/base/task/thread_pool/worker_thread_observer.h
new file mode 100644
index 0000000..d2bc95d
--- /dev/null
+++ b/base/task/thread_pool/worker_thread_observer.h
@@ -0,0 +1,27 @@
+// Copyright 2018 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_TASK_THREAD_POOL_WORKER_THREAD_OBSERVER_H_
+#define BASE_TASK_THREAD_POOL_WORKER_THREAD_OBSERVER_H_
+
+namespace base {
+
+// Interface to observe entry and exit of the main function of a ThreadPool
+// worker.
+class WorkerThreadObserver {
+ public:
+  virtual ~WorkerThreadObserver() = default;
+
+  // Invoked at the beginning of the main function of a ThreadPool worker,
+  // before any task runs.
+  virtual void OnWorkerThreadMainEntry() = 0;
+
+  // Invoked at the end of the main function of a ThreadPool worker, when it
+  // can no longer run tasks.
+  virtual void OnWorkerThreadMainExit() = 0;
+};
+
+}  // namespace base
+
+#endif  // BASE_TASK_THREAD_POOL_WORKER_THREAD_OBSERVER_H_
diff --git a/base/task/thread_pool/scheduler_worker_params.h b/base/task/thread_pool/worker_thread_params.h
similarity index 72%
rename from base/task/thread_pool/scheduler_worker_params.h
rename to base/task/thread_pool/worker_thread_params.h
index 4929e8f..d864ce9 100644
--- a/base/task/thread_pool/scheduler_worker_params.h
+++ b/base/task/thread_pool/worker_thread_params.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_PARAMS_H_
-#define BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_PARAMS_H_
+#ifndef BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_
+#define BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_
 
 namespace base {
 
-enum class SchedulerBackwardCompatibility {
+enum class WorkerThreadBackwardCompatibility {
   // No backward compatibility.
   DISABLED,
 
@@ -21,4 +21,4 @@
 
 }  // namespace base
 
-#endif  // BASE_TASK_THREAD_POOL_SCHEDULER_WORKER_PARAMS_H_
+#endif  // BASE_TASK_THREAD_POOL_WORKER_THREAD_PARAMS_H_
diff --git a/base/task/thread_pool/worker_thread_stack.cc b/base/task/thread_pool/worker_thread_stack.cc
new file mode 100644
index 0000000..f6f2610
--- /dev/null
+++ b/base/task/thread_pool/worker_thread_stack.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 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/task/thread_pool/worker_thread_stack.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/task/thread_pool/worker_thread.h"
+
+namespace base {
+namespace internal {
+
+WorkerThreadStack::WorkerThreadStack() = default;
+
+WorkerThreadStack::~WorkerThreadStack() = default;
+
+void WorkerThreadStack::Push(WorkerThread* worker) {
+  DCHECK(!Contains(worker)) << "WorkerThread already on stack";
+  if (!IsEmpty())
+    stack_.back()->BeginUnusedPeriod();
+  stack_.push_back(worker);
+}
+
+WorkerThread* WorkerThreadStack::Pop() {
+  if (IsEmpty())
+    return nullptr;
+  WorkerThread* const worker = stack_.back();
+  stack_.pop_back();
+  if (!IsEmpty())
+    stack_.back()->EndUnusedPeriod();
+  return worker;
+}
+
+WorkerThread* WorkerThreadStack::Peek() const {
+  if (IsEmpty())
+    return nullptr;
+  return stack_.back();
+}
+
+bool WorkerThreadStack::Contains(const WorkerThread* worker) const {
+  return ContainsValue(stack_, worker);
+}
+
+void WorkerThreadStack::Remove(const WorkerThread* worker) {
+  DCHECK(!IsEmpty());
+  DCHECK_NE(worker, stack_.back());
+  auto it = std::find(stack_.begin(), stack_.end(), worker);
+  DCHECK(it != stack_.end());
+  DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime());
+  stack_.erase(it);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/thread_pool/worker_thread_stack.h b/base/task/thread_pool/worker_thread_stack.h
new file mode 100644
index 0000000..aeb550d7
--- /dev/null
+++ b/base/task/thread_pool/worker_thread_stack.h
@@ -0,0 +1,67 @@
+// Copyright 2016 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_TASK_THREAD_POOL_WORKER_THREAD_STACK_H_
+#define BASE_TASK_THREAD_POOL_WORKER_THREAD_STACK_H_
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace internal {
+
+class WorkerThread;
+
+// A stack of WorkerThreads which has custom logic to treat the worker on top
+// of the stack as being "in-use" (so its time in that position doesn't count
+// towards being inactive / reclaimable). Supports removal of arbitrary
+// WorkerThreads. DCHECKs when a WorkerThread is inserted multiple times.
+// WorkerThreads are not owned by the stack. Push() is amortized O(1). Pop(),
+// Peek(), Size() and Empty() are O(1). Contains() and Remove() are O(n). This
+// class is NOT thread-safe.
+class BASE_EXPORT WorkerThreadStack {
+ public:
+  WorkerThreadStack();
+  ~WorkerThreadStack();
+
+  // Inserts |worker| at the top of the stack. |worker| must not already be on
+  // the stack. Flags the WorkerThread previously on top of the stack, if
+  // any, as unused.
+  void Push(WorkerThread* worker);
+
+  // Removes the top WorkerThread from the stack and returns it. Returns
+  // nullptr if the stack is empty. Flags the WorkerThread now on top of the
+  // stack, if any, as being in-use.
+  WorkerThread* Pop();
+
+  // Returns the top WorkerThread from the stack, nullptr if empty.
+  WorkerThread* Peek() const;
+
+  // Returns true if |worker| is already on the stack.
+  bool Contains(const WorkerThread* worker) const;
+
+  // Removes |worker| from the stack. Must not be invoked for the first worker
+  // on the stack.
+  void Remove(const WorkerThread* worker);
+
+  // Returns the number of WorkerThreads on the stack.
+  size_t Size() const { return stack_.size(); }
+
+  // Returns true if the stack is empty.
+  bool IsEmpty() const { return stack_.empty(); }
+
+ private:
+  std::vector<WorkerThread*> stack_;
+
+  DISALLOW_COPY_AND_ASSIGN(WorkerThreadStack);
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_TASK_THREAD_POOL_WORKER_THREAD_STACK_H_
diff --git a/base/task/thread_pool/scheduler_worker_stack_unittest.cc b/base/task/thread_pool/worker_thread_stack_unittest.cc
similarity index 84%
rename from base/task/thread_pool/scheduler_worker_stack_unittest.cc
rename to base/task/thread_pool/worker_thread_stack_unittest.cc
index a9f6625..33cd89f7 100644
--- a/base/task/thread_pool/scheduler_worker_stack_unittest.cc
+++ b/base/task/thread_pool/worker_thread_stack_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/task/thread_pool/scheduler_worker_stack.h"
+#include "base/task/thread_pool/worker_thread_stack.h"
 
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/task/thread_pool/scheduler_worker.h"
 #include "base/task/thread_pool/task_source.h"
 #include "base/task/thread_pool/task_tracker.h"
+#include "base/task/thread_pool/worker_thread.h"
 #include "base/test/gtest_util.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -19,13 +19,13 @@
 
 namespace {
 
-class MockSchedulerWorkerDelegate : public SchedulerWorker::Delegate {
+class MockWorkerThreadDelegate : public WorkerThread::Delegate {
  public:
-  SchedulerWorker::ThreadLabel GetThreadLabel() const override {
-    return SchedulerWorker::ThreadLabel::DEDICATED;
+  WorkerThread::ThreadLabel GetThreadLabel() const override {
+    return WorkerThread::ThreadLabel::DEDICATED;
   }
-  void OnMainEntry(const SchedulerWorker* worker) override {}
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  void OnMainEntry(const WorkerThread* worker) override {}
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     return nullptr;
   }
   void DidRunTask(scoped_refptr<TaskSource> task_source) override {
@@ -37,16 +37,16 @@
 class ThreadPoolWorkerStackTest : public testing::Test {
  protected:
   void SetUp() override {
-    worker_a_ = MakeRefCounted<SchedulerWorker>(
-        ThreadPriority::NORMAL, std::make_unique<MockSchedulerWorkerDelegate>(),
+    worker_a_ = MakeRefCounted<WorkerThread>(
+        ThreadPriority::NORMAL, std::make_unique<MockWorkerThreadDelegate>(),
         task_tracker_.GetTrackedRef());
     ASSERT_TRUE(worker_a_);
-    worker_b_ = MakeRefCounted<SchedulerWorker>(
-        ThreadPriority::NORMAL, std::make_unique<MockSchedulerWorkerDelegate>(),
+    worker_b_ = MakeRefCounted<WorkerThread>(
+        ThreadPriority::NORMAL, std::make_unique<MockWorkerThreadDelegate>(),
         task_tracker_.GetTrackedRef());
     ASSERT_TRUE(worker_b_);
-    worker_c_ = MakeRefCounted<SchedulerWorker>(
-        ThreadPriority::NORMAL, std::make_unique<MockSchedulerWorkerDelegate>(),
+    worker_c_ = MakeRefCounted<WorkerThread>(
+        ThreadPriority::NORMAL, std::make_unique<MockWorkerThreadDelegate>(),
         task_tracker_.GetTrackedRef());
     ASSERT_TRUE(worker_c_);
   }
@@ -55,16 +55,16 @@
   TaskTracker task_tracker_ = {"Test"};
 
  protected:
-  scoped_refptr<SchedulerWorker> worker_a_;
-  scoped_refptr<SchedulerWorker> worker_b_;
-  scoped_refptr<SchedulerWorker> worker_c_;
+  scoped_refptr<WorkerThread> worker_a_;
+  scoped_refptr<WorkerThread> worker_b_;
+  scoped_refptr<WorkerThread> worker_c_;
 };
 
 }  // namespace
 
 // Verify that Push() and Pop() add/remove values in FIFO order.
 TEST_F(ThreadPoolWorkerStackTest, PushPop) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   EXPECT_EQ(nullptr, stack.Pop());
 
   EXPECT_TRUE(stack.IsEmpty());
@@ -107,7 +107,7 @@
 
 // Verify that Peek() returns the correct values in FIFO order.
 TEST_F(ThreadPoolWorkerStackTest, PeekPop) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   EXPECT_EQ(nullptr, stack.Peek());
 
   EXPECT_TRUE(stack.IsEmpty());
@@ -147,7 +147,7 @@
 
 // Verify that Contains() returns true for workers on the stack.
 TEST_F(ThreadPoolWorkerStackTest, Contains) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   EXPECT_FALSE(stack.Contains(worker_a_.get()));
   EXPECT_FALSE(stack.Contains(worker_b_.get()));
   EXPECT_FALSE(stack.Contains(worker_c_.get()));
@@ -185,7 +185,7 @@
 
 // Verify that a value can be removed by Remove().
 TEST_F(ThreadPoolWorkerStackTest, Remove) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   EXPECT_TRUE(stack.IsEmpty());
   EXPECT_EQ(0U, stack.Size());
 
@@ -216,7 +216,7 @@
 
 // Verify that a value can be pushed again after it has been removed.
 TEST_F(ThreadPoolWorkerStackTest, PushAfterRemove) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   EXPECT_EQ(0U, stack.Size());
 
   stack.Push(worker_a_.get());
@@ -236,7 +236,7 @@
 
 // Verify that Push() DCHECKs when a value is inserted twice.
 TEST_F(ThreadPoolWorkerStackTest, PushTwice) {
-  SchedulerWorkerStack stack;
+  WorkerThreadStack stack;
   stack.Push(worker_a_.get());
   EXPECT_DCHECK_DEATH({ stack.Push(worker_a_.get()); });
 }
diff --git a/base/task/thread_pool/scheduler_worker_unittest.cc b/base/task/thread_pool/worker_thread_unittest.cc
similarity index 82%
rename from base/task/thread_pool/scheduler_worker_unittest.cc
rename to base/task/thread_pool/worker_thread_unittest.cc
index 4882fbd5..0611af5 100644
--- a/base/task/thread_pool/scheduler_worker_unittest.cc
+++ b/base/task/thread_pool/worker_thread_unittest.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 "base/task/thread_pool/scheduler_worker.h"
+#include "base/task/thread_pool/worker_thread.h"
 
 #include <stddef.h>
 
@@ -18,11 +18,11 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/task/common/checked_lock.h"
 #include "base/task/thread_pool/environment_config.h"
-#include "base/task/thread_pool/scheduler_worker_observer.h"
 #include "base/task/thread_pool/sequence.h"
 #include "base/task/thread_pool/task.h"
 #include "base/task/thread_pool/task_tracker.h"
 #include "base/task/thread_pool/test_utils.h"
+#include "base/task/thread_pool/worker_thread_observer.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/simple_thread.h"
@@ -48,16 +48,16 @@
 
 const size_t kNumSequencesPerTest = 150;
 
-class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate {
+class WorkerThreadDefaultDelegate : public WorkerThread::Delegate {
  public:
-  SchedulerWorkerDefaultDelegate() = default;
+  WorkerThreadDefaultDelegate() = default;
 
-  // SchedulerWorker::Delegate:
-  SchedulerWorker::ThreadLabel GetThreadLabel() const override {
-    return SchedulerWorker::ThreadLabel::DEDICATED;
+  // WorkerThread::Delegate:
+  WorkerThread::ThreadLabel GetThreadLabel() const override {
+    return WorkerThread::ThreadLabel::DEDICATED;
   }
-  void OnMainEntry(const SchedulerWorker* worker) override {}
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  void OnMainEntry(const WorkerThread* worker) override {}
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     return nullptr;
   }
   void DidRunTask(scoped_refptr<TaskSource> sequence) override {
@@ -66,7 +66,7 @@
   TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate);
+  DISALLOW_COPY_AND_ASSIGN(WorkerThreadDefaultDelegate);
 };
 
 // The test parameter is the number of Tasks per Sequence returned by GetWork().
@@ -75,9 +75,9 @@
   ThreadPoolWorkerTest() : num_get_work_cv_(lock_.CreateConditionVariable()) {}
 
   void SetUp() override {
-    worker_ = MakeRefCounted<SchedulerWorker>(
+    worker_ = MakeRefCounted<WorkerThread>(
         ThreadPriority::NORMAL,
-        std::make_unique<TestSchedulerWorkerDelegate>(this),
+        std::make_unique<TestWorkerThreadDelegate>(this),
         task_tracker_.GetTrackedRef());
     ASSERT_TRUE(worker_);
     worker_->Start();
@@ -127,19 +127,19 @@
     return did_run_task_sequences_;
   }
 
-  scoped_refptr<SchedulerWorker> worker_;
+  scoped_refptr<WorkerThread> worker_;
 
  private:
-  class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate {
+  class TestWorkerThreadDelegate : public WorkerThreadDefaultDelegate {
    public:
-    TestSchedulerWorkerDelegate(ThreadPoolWorkerTest* outer) : outer_(outer) {}
+    TestWorkerThreadDelegate(ThreadPoolWorkerTest* outer) : outer_(outer) {}
 
-    ~TestSchedulerWorkerDelegate() override {
+    ~TestWorkerThreadDelegate() override {
       EXPECT_FALSE(IsCallToDidRunTaskExpected());
     }
 
-    // SchedulerWorker::Delegate:
-    void OnMainEntry(const SchedulerWorker* worker) override {
+    // WorkerThread::Delegate:
+    void OnMainEntry(const WorkerThread* worker) override {
       outer_->worker_set_.Wait();
       EXPECT_EQ(outer_->worker_.get(), worker);
       EXPECT_FALSE(IsCallToDidRunTaskExpected());
@@ -151,7 +151,7 @@
       outer_->main_entry_called_.Signal();
     }
 
-    scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+    scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
       EXPECT_FALSE(IsCallToDidRunTaskExpected());
       EXPECT_EQ(outer_->worker_.get(), worker);
 
@@ -251,7 +251,7 @@
     // Whether the next method called on this delegate should be DidRunTask().
     bool expect_did_run_task_ = false;
 
-    DISALLOW_COPY_AND_ASSIGN(TestSchedulerWorkerDelegate);
+    DISALLOW_COPY_AND_ASSIGN(TestWorkerThreadDelegate);
   };
 
   void RunTaskCallback() {
@@ -299,7 +299,7 @@
 }  // namespace
 
 // Verify that when GetWork() continuously returns Sequences, all Tasks in these
-// Sequences run successfully. The test wakes up the SchedulerWorker once.
+// Sequences run successfully. The test wakes up the WorkerThread once.
 TEST_P(ThreadPoolWorkerTest, ContinuousWork) {
   // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to
   // return nullptr.
@@ -329,7 +329,7 @@
 
 // Verify that when GetWork() alternates between returning a Sequence and
 // returning nullptr, all Tasks in the returned Sequences run successfully. The
-// test wakes up the SchedulerWorker once for each Sequence.
+// test wakes up the WorkerThread once for each Sequence.
 TEST_P(ThreadPoolWorkerTest, IntermittentWork) {
   for (size_t i = 0; i < kNumSequencesPerTest; ++i) {
     // Set GetWork() to return 1 Sequence before starting to return
@@ -368,7 +368,7 @@
 
 namespace {
 
-class ControllableCleanupDelegate : public SchedulerWorkerDefaultDelegate {
+class ControllableCleanupDelegate : public WorkerThreadDefaultDelegate {
  public:
   class Controls : public RefCountedThreadSafe<Controls> {
    public:
@@ -424,7 +424,7 @@
 
   ~ControllableCleanupDelegate() override { controls_->destroyed_.Signal(); }
 
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     EXPECT_TRUE(controls_->expect_get_work_);
 
     // Sends one item of work to signal |work_processed_|. On subsequent calls,
@@ -461,11 +461,11 @@
 
   void DidRunTask(scoped_refptr<TaskSource>) override {}
 
-  void OnMainExit(SchedulerWorker* worker) override {
+  void OnMainExit(WorkerThread* worker) override {
     controls_->exited_.Signal();
   }
 
-  bool CanCleanup(SchedulerWorker* worker) {
+  bool CanCleanup(WorkerThread* worker) {
     // Saving |can_cleanup_| now so that callers waiting on |cleanup_requested_|
     // have the thread go to sleep and then allow timing out.
     bool can_cleanup = controls_->can_cleanup_;
@@ -495,8 +495,8 @@
       : ControllableCleanupDelegate(task_tracker) {}
   ~MockedControllableCleanupDelegate() override = default;
 
-  // SchedulerWorker::Delegate:
-  MOCK_METHOD1(OnMainEntry, void(const SchedulerWorker* worker));
+  // WorkerThread::Delegate:
+  MOCK_METHOD1(OnMainEntry, void(const WorkerThread* worker));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockedControllableCleanupDelegate);
@@ -504,20 +504,20 @@
 
 }  // namespace
 
-// Verify that calling SchedulerWorker::Cleanup() from GetWork() causes
-// the SchedulerWorker's thread to exit.
+// Verify that calling WorkerThread::Cleanup() from GetWork() causes
+// the WorkerThread's thread to exit.
 TEST(ThreadPoolWorkerTest, WorkerCleanupFromGetWork) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   MockedControllableCleanupDelegate* delegate =
       new StrictMock<MockedControllableCleanupDelegate>(&task_tracker);
   scoped_refptr<ControllableCleanupDelegate::Controls> controls =
       delegate->controls();
   controls->set_can_cleanup(true);
   EXPECT_CALL(*delegate, OnMainEntry(_));
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                WrapUnique(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, WrapUnique(delegate),
+                                   task_tracker.GetTrackedRef());
   worker->Start();
   worker->WakeUp();
   controls->WaitForWorkToRun();
@@ -527,7 +527,7 @@
 
 TEST(ThreadPoolWorkerTest, WorkerCleanupDuringWork) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   // No mock here as that's reasonably covered by other tests and the delegate
   // may destroy on a different thread. Mocks aren't designed with that in mind.
   std::unique_ptr<ControllableCleanupDelegate> delegate =
@@ -537,9 +537,9 @@
 
   controls->HaveWorkBlock();
 
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate),
+                                   task_tracker.GetTrackedRef());
   worker->Start();
   worker->WakeUp();
 
@@ -552,7 +552,7 @@
 
 TEST(ThreadPoolWorkerTest, WorkerCleanupDuringWait) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   // No mock here as that's reasonably covered by other tests and the delegate
   // may destroy on a different thread. Mocks aren't designed with that in mind.
   std::unique_ptr<ControllableCleanupDelegate> delegate =
@@ -560,9 +560,9 @@
   scoped_refptr<ControllableCleanupDelegate::Controls> controls =
       delegate->controls();
 
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate),
+                                   task_tracker.GetTrackedRef());
   worker->Start();
   worker->WakeUp();
 
@@ -574,7 +574,7 @@
 
 TEST(ThreadPoolWorkerTest, WorkerCleanupDuringShutdown) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   // No mock here as that's reasonably covered by other tests and the delegate
   // may destroy on a different thread. Mocks aren't designed with that in mind.
   std::unique_ptr<ControllableCleanupDelegate> delegate =
@@ -584,9 +584,9 @@
 
   controls->HaveWorkBlock();
 
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate),
+                                   task_tracker.GetTrackedRef());
   worker->Start();
   worker->WakeUp();
 
@@ -601,7 +601,7 @@
 // Verify that Start() is a no-op after Cleanup().
 TEST(ThreadPoolWorkerTest, CleanupBeforeStart) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   // No mock here as that's reasonably covered by other tests and the delegate
   // may destroy on a different thread. Mocks aren't designed with that in mind.
   std::unique_ptr<ControllableCleanupDelegate> delegate =
@@ -610,9 +610,9 @@
       delegate->controls();
   controls->set_expect_get_work(false);
 
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate),
+                                   task_tracker.GetTrackedRef());
 
   worker->Cleanup();
   worker->Start();
@@ -624,8 +624,8 @@
 
 class CallJoinFromDifferentThread : public SimpleThread {
  public:
-  CallJoinFromDifferentThread(SchedulerWorker* worker_to_join)
-      : SimpleThread("SchedulerWorkerJoinThread"),
+  CallJoinFromDifferentThread(WorkerThread* worker_to_join)
+      : SimpleThread("WorkerThreadJoinThread"),
         worker_to_join_(worker_to_join) {}
 
   ~CallJoinFromDifferentThread() override = default;
@@ -638,7 +638,7 @@
   void WaitForRunToStart() { run_started_event_.Wait(); }
 
  private:
-  SchedulerWorker* const worker_to_join_;
+  WorkerThread* const worker_to_join_;
   WaitableEvent run_started_event_;
   DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
 };
@@ -647,7 +647,7 @@
 
 TEST(ThreadPoolWorkerTest, WorkerCleanupDuringJoin) {
   TaskTracker task_tracker("Test");
-  // Will be owned by SchedulerWorker.
+  // Will be owned by WorkerThread.
   // No mock here as that's reasonably covered by other tests and the
   // delegate may destroy on a different thread. Mocks aren't designed with that
   // in mind.
@@ -658,9 +658,9 @@
 
   controls->HaveWorkBlock();
 
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker =
+      MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate),
+                                   task_tracker.GetTrackedRef());
   worker->Start();
   worker->WakeUp();
 
@@ -682,7 +682,7 @@
 
 namespace {
 
-class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate {
+class ExpectThreadPriorityDelegate : public WorkerThreadDefaultDelegate {
  public:
   ExpectThreadPriorityDelegate()
       : priority_verified_in_get_work_event_(
@@ -698,11 +698,11 @@
     priority_verified_in_get_work_event_.Wait();
   }
 
-  // SchedulerWorker::Delegate:
-  void OnMainEntry(const SchedulerWorker* worker) override {
+  // WorkerThread::Delegate:
+  void OnMainEntry(const WorkerThread* worker) override {
     VerifyThreadPriority();
   }
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     VerifyThreadPriority();
     priority_verified_in_get_work_event_.Signal();
     return nullptr;
@@ -730,7 +730,7 @@
 }  // namespace
 
 TEST(ThreadPoolWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) {
-  if (!CanUseBackgroundPriorityForSchedulerWorker())
+  if (!CanUseBackgroundPriorityForWorkerThread())
     return;
 
   TaskTracker task_tracker("Test");
@@ -744,9 +744,9 @@
       new ExpectThreadPriorityDelegate);
   ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
   delegate_raw->SetExpectedThreadPriority(ThreadPriority::BACKGROUND);
-  auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::BACKGROUND,
-                                                std::move(delegate),
-                                                task_tracker.GetTrackedRef());
+  auto worker = MakeRefCounted<WorkerThread>(ThreadPriority::BACKGROUND,
+                                             std::move(delegate),
+                                             task_tracker.GetTrackedRef());
   worker->Start();
 
   // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread
@@ -765,22 +765,22 @@
 
 namespace {
 
-class VerifyCallsToObserverDelegate : public SchedulerWorkerDefaultDelegate {
+class VerifyCallsToObserverDelegate : public WorkerThreadDefaultDelegate {
  public:
-  VerifyCallsToObserverDelegate(test::MockSchedulerWorkerObserver* observer)
+  VerifyCallsToObserverDelegate(test::MockWorkerThreadObserver* observer)
       : observer_(observer) {}
 
-  // SchedulerWorker::Delegate:
-  void OnMainEntry(const SchedulerWorker* worker) override {
+  // WorkerThread::Delegate:
+  void OnMainEntry(const WorkerThread* worker) override {
     Mock::VerifyAndClear(observer_);
   }
 
-  void OnMainExit(SchedulerWorker* worker) override {
+  void OnMainExit(WorkerThread* worker) override {
     observer_->AllowCallsOnMainExit(1);
   }
 
  private:
-  test::MockSchedulerWorkerObserver* const observer_;
+  test::MockWorkerThreadObserver* const observer_;
 
   DISALLOW_COPY_AND_ASSIGN(VerifyCallsToObserverDelegate);
 };
@@ -789,23 +789,23 @@
 
 // Flaky: crbug.com/846121
 #if defined(OS_LINUX) && defined(ADDRESS_SANITIZER)
-#define MAYBE_SchedulerWorkerObserver DISABLED_SchedulerWorkerObserver
+#define MAYBE_WorkerThreadObserver DISABLED_WorkerThreadObserver
 #else
-#define MAYBE_SchedulerWorkerObserver SchedulerWorkerObserver
+#define MAYBE_WorkerThreadObserver WorkerThreadObserver
 #endif
 
-// Verify that the SchedulerWorkerObserver is notified when the worker enters
+// Verify that the WorkerThreadObserver is notified when the worker enters
 // and exits its main function.
-TEST(ThreadPoolWorkerTest, MAYBE_SchedulerWorkerObserver) {
-  StrictMock<test::MockSchedulerWorkerObserver> observer;
+TEST(ThreadPoolWorkerTest, MAYBE_WorkerThreadObserver) {
+  StrictMock<test::MockWorkerThreadObserver> observer;
   {
     TaskTracker task_tracker("Test");
     auto delegate = std::make_unique<VerifyCallsToObserverDelegate>(&observer);
-    auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
-                                                  std::move(delegate),
-                                                  task_tracker.GetTrackedRef());
+    auto worker = MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL,
+                                               std::move(delegate),
+                                               task_tracker.GetTrackedRef());
 
-    EXPECT_CALL(observer, OnSchedulerWorkerMainEntry());
+    EXPECT_CALL(observer, OnWorkerThreadMainEntry());
     worker->Start(&observer);
     worker->Cleanup();
     worker = nullptr;
@@ -817,11 +817,11 @@
 
 namespace {
 
-class CoInitializeDelegate : public SchedulerWorkerDefaultDelegate {
+class CoInitializeDelegate : public WorkerThreadDefaultDelegate {
  public:
   CoInitializeDelegate() = default;
 
-  scoped_refptr<TaskSource> GetWork(SchedulerWorker* worker) override {
+  scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override {
     EXPECT_FALSE(get_work_returned_.IsSignaled());
     EXPECT_EQ(E_UNEXPECTED, coinitialize_hresult_);
 
@@ -853,16 +853,16 @@
 
   // Create a worker with backward compatibility ENABLED. Wake it up and wait
   // until GetWork() returns.
-  auto worker = MakeRefCounted<SchedulerWorker>(
+  auto worker = MakeRefCounted<WorkerThread>(
       ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(),
-      nullptr, SchedulerBackwardCompatibility::INIT_COM_STA);
+      nullptr, WorkerThreadBackwardCompatibility::INIT_COM_STA);
   worker->Start();
   worker->WakeUp();
   delegate_raw->WaitUntilGetWorkReturned();
 
 // The call to CoInitializeEx() should have returned S_FALSE to indicate that
 // the COM library was already initialized on the thread.
-// See SchedulerWorker::Thread::ThreadMain for why we expect two different
+// See WorkerThread::Thread::ThreadMain for why we expect two different
 // results here.
 #if defined(COM_INIT_CHECK_HOOK_ENABLED)
   EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult());
@@ -880,9 +880,9 @@
 
   // Create a worker with backward compatibility DISABLED. Wake it up and wait
   // until GetWork() returns.
-  auto worker = MakeRefCounted<SchedulerWorker>(
+  auto worker = MakeRefCounted<WorkerThread>(
       ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(),
-      nullptr, SchedulerBackwardCompatibility::DISABLED);
+      nullptr, WorkerThreadBackwardCompatibility::DISABLED);
   worker->Start();
   worker->WakeUp();
   delegate_raw->WaitUntilGetWorkReturned();
diff --git a/base/task_runner.cc b/base/task_runner.cc
index aae9f9ec..73130163 100644
--- a/base/task_runner.cc
+++ b/base/task_runner.cc
@@ -15,7 +15,7 @@
 namespace {
 
 // TODO(akalin): There's only one other implementation of
-// PostTaskAndReplyImpl in WorkerPool.  Investigate whether it'll be
+// PostTaskAndReplyImpl in post_task.cc.  Investigate whether it'll be
 // possible to merge the two.
 class PostTaskAndReplyTaskRunner : public internal::PostTaskAndReplyImpl {
  public:
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java b/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
index 9f58a83..94e51f0d 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
@@ -31,6 +31,9 @@
         public boolean isBound() {
             return mBound;
         }
+
+        @Override
+        public void updateGroupImportance(int group, int importanceInGroup) {}
     }
 
     private int mPid;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java b/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java
index c8117f7..f850f1e 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java
@@ -7,8 +7,6 @@
 import android.content.ComponentCallbacks;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.SharedPreferences;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 
@@ -18,13 +16,9 @@
 /**
  * ContextWrapper that adds functionality for SharedPreferences and a way to set and retrieve flags.
  */
-public class AdvancedMockContext extends ContextWrapper {
-
+public class AdvancedMockContext extends InMemorySharedPreferencesContext {
     private final MockContentResolver mMockContentResolver = new MockContentResolver();
 
-    private final Map<String, SharedPreferences> mSharedPreferences =
-            new HashMap<String, SharedPreferences>();
-
     private final Map<String, Boolean> mFlags = new HashMap<String, Boolean>();
 
     public AdvancedMockContext(Context base) {
@@ -55,17 +49,6 @@
     }
 
     @Override
-    public SharedPreferences getSharedPreferences(String name, int mode) {
-        synchronized (mSharedPreferences) {
-            if (!mSharedPreferences.containsKey(name)) {
-                // Auto-create shared preferences to mimic Android Context behavior
-                mSharedPreferences.put(name, new InMemorySharedPreferences());
-            }
-            return mSharedPreferences.get(name);
-        }
-    }
-
-    @Override
     public void registerComponentCallbacks(ComponentCallbacks callback) {
         getBaseContext().registerComponentCallbacks(callback);
     }
@@ -92,27 +75,4 @@
     public boolean isFlagSet(String key) {
         return mFlags.containsKey(key) && mFlags.get(key);
     }
-
-    /**
-     * Builder for maps of type Map<String, Object> to be used with
-     * {@link #addSharedPreferences(String, java.util.Map)}.
-     */
-    public static class MapBuilder {
-
-        private final Map<String, Object> mData = new HashMap<String, Object>();
-
-        public static MapBuilder create() {
-            return new MapBuilder();
-        }
-
-        public MapBuilder add(String key, Object value) {
-            mData.put(key, value);
-            return this;
-        }
-
-        public Map<String, Object> build() {
-            return mData;
-        }
-
-    }
 }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java b/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java
index 2587d72..f538088f 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java
@@ -6,9 +6,12 @@
 
 import android.content.SharedPreferences;
 
-import java.util.Collections;
+import org.chromium.base.ObserverList;
+
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -20,6 +23,8 @@
 
     // Guarded on its own monitor.
     private final Map<String, Object> mData;
+    private final ObserverList<OnSharedPreferenceChangeListener> mObservers =
+            new ObserverList<OnSharedPreferenceChangeListener>();
 
     public InMemorySharedPreferences() {
         mData = new HashMap<String, Object>();
@@ -32,69 +37,57 @@
     @Override
     public Map<String, ?> getAll() {
         synchronized (mData) {
-            return Collections.unmodifiableMap(mData);
+            return new HashMap<>(mData);
         }
     }
 
     @Override
     public String getString(String key, String defValue) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return (String) mData.get(key);
-            }
+            String ret = (String) mData.get(key);
+            return ret != null ? ret : defValue;
         }
-        return defValue;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public Set<String> getStringSet(String key, Set<String> defValues) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return Collections.unmodifiableSet((Set<String>) mData.get(key));
-            }
+            Set<String> ret = (Set<String>) mData.get(key);
+            return ret != null ? ret : defValues;
         }
-        return defValues;
     }
 
     @Override
     public int getInt(String key, int defValue) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return (Integer) mData.get(key);
-            }
+            Integer ret = (Integer) mData.get(key);
+            return ret != null ? ret : defValue;
         }
-        return defValue;
     }
 
     @Override
     public long getLong(String key, long defValue) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return (Long) mData.get(key);
-            }
+            Long ret = (Long) mData.get(key);
+            return ret != null ? ret : defValue;
         }
-        return defValue;
     }
 
     @Override
     public float getFloat(String key, float defValue) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return (Float) mData.get(key);
-            }
+            Float ret = (Float) mData.get(key);
+            return ret != null ? ret : defValue;
         }
-        return defValue;
     }
 
     @Override
     public boolean getBoolean(String key, boolean defValue) {
         synchronized (mData) {
-            if (mData.containsKey(key)) {
-                return (Boolean) mData.get(key);
-            }
+            Boolean ret = (Boolean) mData.get(key);
+            return ret != null ? ret : defValue;
         }
-        return defValue;
     }
 
     @Override
@@ -113,26 +106,28 @@
     public void registerOnSharedPreferenceChangeListener(
             SharedPreferences.OnSharedPreferenceChangeListener
                     listener) {
-        throw new UnsupportedOperationException();
+        synchronized (mObservers) {
+            mObservers.addObserver(listener);
+        }
     }
 
     @Override
     public void unregisterOnSharedPreferenceChangeListener(
             SharedPreferences.OnSharedPreferenceChangeListener listener) {
-        throw new UnsupportedOperationException();
+        synchronized (mObservers) {
+            mObservers.removeObserver(listener);
+        }
     }
 
     private class InMemoryEditor implements SharedPreferences.Editor {
 
         // All guarded by |mChanges|
         private boolean mClearCalled;
-        private volatile boolean mApplyCalled;
         private final Map<String, Object> mChanges = new HashMap<String, Object>();
 
         @Override
         public SharedPreferences.Editor putString(String key, String value) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, value);
                 return this;
             }
@@ -141,7 +136,6 @@
         @Override
         public SharedPreferences.Editor putStringSet(String key, Set<String> values) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, values);
                 return this;
             }
@@ -150,7 +144,6 @@
         @Override
         public SharedPreferences.Editor putInt(String key, int value) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, value);
                 return this;
             }
@@ -159,7 +152,6 @@
         @Override
         public SharedPreferences.Editor putLong(String key, long value) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, value);
                 return this;
             }
@@ -168,7 +160,6 @@
         @Override
         public SharedPreferences.Editor putFloat(String key, float value) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, value);
                 return this;
             }
@@ -177,7 +168,6 @@
         @Override
         public SharedPreferences.Editor putBoolean(String key, boolean value) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mChanges.put(key, value);
                 return this;
             }
@@ -186,7 +176,6 @@
         @Override
         public SharedPreferences.Editor remove(String key) {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 // Magic value for removes
                 mChanges.put(key, this);
                 return this;
@@ -196,8 +185,8 @@
         @Override
         public SharedPreferences.Editor clear() {
             synchronized (mChanges) {
-                if (mApplyCalled) throw new IllegalStateException();
                 mClearCalled = true;
+                mChanges.clear();
                 return this;
             }
         }
@@ -210,26 +199,41 @@
 
         @Override
         public void apply() {
+            Set<String> changedKeys = new HashSet<>();
             synchronized (mData) {
                 synchronized (mChanges) {
-                    if (mApplyCalled) throw new IllegalStateException();
                     if (mClearCalled) {
+                        changedKeys.addAll(mData.keySet());
                         mData.clear();
+                        mClearCalled = false;
                     }
                     for (Map.Entry<String, Object> entry : mChanges.entrySet()) {
                         String key = entry.getKey();
                         Object value = entry.getValue();
                         if (value == this) {
+                            if (mData.containsKey(key)) {
+                                changedKeys.add(key);
+                            }
                             // Special value for removal
                             mData.remove(key);
+
                         } else {
+                            Object oldValue = mData.get(key);
+                            if (!Objects.equals(oldValue, value)) {
+                                changedKeys.add(key);
+                            }
+
                             mData.put(key, value);
                         }
                     }
-                    // The real shared prefs clears out the temporaries allowing the caller to
-                    // reuse the Editor instance, however this is undocumented behavior and subtle
-                    // to read, so instead we just ban any future use of this instance.
-                    mApplyCalled = true;
+                    mChanges.clear();
+                }
+            }
+            synchronized (mObservers) {
+                for (OnSharedPreferenceChangeListener observer : mObservers) {
+                    for (String key : changedKeys) {
+                        observer.onSharedPreferenceChanged(InMemorySharedPreferences.this, key);
+                    }
                 }
             }
         }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferencesContext.java b/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferencesContext.java
new file mode 100644
index 0000000..433f992
--- /dev/null
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferencesContext.java
@@ -0,0 +1,73 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.test.util;
+
+import android.content.ComponentCallbacks;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.SharedPreferences;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ContextWrapper that causes SharedPreferences to not persist to disk.
+ */
+public class InMemorySharedPreferencesContext extends ContextWrapper {
+    protected final Map<String, SharedPreferences> mSharedPreferences =
+            new HashMap<String, SharedPreferences>();
+
+    public InMemorySharedPreferencesContext(Context base) {
+        super(base);
+    }
+
+    @Override
+    public SharedPreferences getSharedPreferences(String name, int mode) {
+        // Pass through multidex prefs to avoid excessive multidex extraction on KitKat.
+        if (name.endsWith("multidex.version")) {
+            return getBaseContext().getSharedPreferences(name, mode);
+        }
+        synchronized (mSharedPreferences) {
+            if (!mSharedPreferences.containsKey(name)) {
+                mSharedPreferences.put(name, new InMemorySharedPreferences());
+            }
+            return mSharedPreferences.get(name);
+        }
+    }
+
+    @Override
+    public Context getApplicationContext() {
+        // Play services calls .getApplicationContext() on the Context we give them. In order to
+        // not have them circumvent this wrapper, hardcode getApplicationContext() to no-op.
+        return this;
+    }
+
+    @Override
+    public void registerComponentCallbacks(ComponentCallbacks callback) {
+        // Base implmementation calls getApplicationContext, so need to explicitly circumvent our
+        // no-op'ing getApplicationContext().
+        getBaseContext().registerComponentCallbacks(callback);
+    }
+
+    @Override
+    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
+        // Base implmementation calls getApplicationContext, so need to explicitly circumvent our
+        // no-op'ing getApplicationContext().
+        getBaseContext().unregisterComponentCallbacks(callback);
+    }
+
+    /**
+     * Calls .clear() on all SharedPreferences.
+     */
+    public void clearSharedPreferences() {
+        synchronized (mSharedPreferences) {
+            // Clear each instance rather than the map in case there are any registered listeners
+            // or cached references to them.
+            for (SharedPreferences prefs : mSharedPreferences.values()) {
+                prefs.edit().clear().apply();
+            }
+        }
+    }
+}
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc
index 9a13ee3..720cee2 100644
--- a/base/test/scoped_task_environment.cc
+++ b/base/test/scoped_task_environment.cc
@@ -387,15 +387,15 @@
   // data races.
   constexpr int kMaxThreads = 4;
   const TimeDelta kSuggestedReclaimTime = TimeDelta::Max();
-  const SchedulerWorkerPoolParams worker_pool_params(kMaxThreads,
-                                                     kSuggestedReclaimTime);
+  const ThreadGroupParams thread_group_params(kMaxThreads,
+                                              kSuggestedReclaimTime);
   auto task_tracker = std::make_unique<TestTaskTracker>();
   task_tracker_ = task_tracker.get();
   ThreadPool::SetInstance(std::make_unique<internal::ThreadPoolImpl>(
       "ScopedTaskEnvironment", std::move(task_tracker)));
   thread_pool_ = ThreadPool::GetInstance();
   ThreadPool::GetInstance()->Start({
-    worker_pool_params, worker_pool_params
+    thread_group_params, thread_group_params
 #if defined(OS_WIN)
         ,
         // Enable the MTA in unit tests to match the browser process'
@@ -409,7 +409,7 @@
         // I/O, waits, etc. Such misuse will still be caught in later phases
         // (and COM usage should already be pretty much inexistent in sandboxed
         // processes).
-        ThreadPool::InitParams::SharedWorkerPoolEnvironment::COM_MTA
+        ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA
 #endif
   });
 }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index c94e9627..9c19665 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -3895,6 +3895,7 @@
   #   ignore_assets: Whether to ignore assets found in the .aar.
   #   ignore_native_libraries: Whether to ignore .so files found in the .aar.
   #       See also extract_native_libraries.
+  #   ignore_proguard_configs = Whether to ignore proguard configs.
   #   extract_native_libraries: Whether to extract .so files found in the .aar.
   #       If the file contains .so, either extract_native_libraries or
   #       ignore_native_libraries must be set.
@@ -3922,6 +3923,8 @@
     _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets
     _ignore_native_libraries = defined(invoker.ignore_native_libraries) &&
                                invoker.ignore_native_libraries
+    _ignore_proguard_configs = defined(invoker.ignore_proguard_configs) &&
+                               invoker.ignore_proguard_configs
     _extract_native_libraries = defined(invoker.extract_native_libraries) &&
                                 invoker.extract_native_libraries
 
@@ -3999,7 +4002,7 @@
       outputs +=
           get_path_info(rebase_path(_scanned_files.subjars, "", _output_path),
                         "abspath")
-      if (_scanned_files.has_proguard_flags) {
+      if (!_ignore_proguard_configs && _scanned_files.has_proguard_flags) {
         outputs += [ "${_output_path}/proguard.txt" ]
       }
 
diff --git a/build/config/c++/c++.gni b/build/config/c++/c++.gni
index 4deaf03..40177f9 100644
--- a/build/config/c++/c++.gni
+++ b/build/config/c++/c++.gni
@@ -11,7 +11,7 @@
   # Don't check in changes that set this to false for more platforms; doing so
   # is not supported.
   use_custom_libcxx =
-      is_fuchsia || is_android || is_mac || is_ios ||
+      is_fuchsia || is_android || is_mac || (is_ios && !use_xcode_clang) ||
       (is_linux &&
        (!is_chromeos || default_toolchain != "//build/toolchain/cros:target"))
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 2ec7a7dd..416bcb5 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8914736426186138320
\ No newline at end of file
+8914675421772048816
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 4a60987..8c8fa8f4 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8914845448229350400
\ No newline at end of file
+8914678376428897744
\ No newline at end of file
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 39e438b6f..e35f5b85 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -44,16 +44,8 @@
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/gpu_in_process_thread_service.h"
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
-#include "gpu/ipc/service/gpu_watchdog_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gl/init/gl_factory.h"
-
-#if BUILDFLAG(ENABLE_VULKAN)
-#include "gpu/vulkan/init/vulkan_factory.h"
-#include "gpu/vulkan/vulkan_implementation.h"
-#endif
 
 namespace cc {
 namespace {
@@ -280,91 +272,23 @@
   renderer_->SetVisible(true);
 }
 
-void PixelTest::SetUpGpuServiceOnGpuThread(base::WaitableEvent* event) {
-  ASSERT_TRUE(gpu_thread_->task_runner()->BelongsToCurrentThread());
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  gpu::GpuPreferences gpu_preferences =
-      gpu::gles2::ParseGpuPreferences(command_line);
-  if (gpu_preferences.enable_vulkan) {
-#if BUILDFLAG(ENABLE_VULKAN)
-    vulkan_implementation_ = gpu::CreateVulkanImplementation();
-    if (!vulkan_implementation_ ||
-        !vulkan_implementation_->InitializeVulkanInstance(
-            !gpu_preferences.disable_vulkan_surface)) {
-      LOG(FATAL) << "Failed to create and initialize Vulkan implementation.";
-    }
-#else
-    NOTREACHED();
-#endif
-  }
-  gpu::GpuFeatureInfo gpu_feature_info;
-  // To test SkiaRenderer with DDL, we need enable OOP-R.
-  gpu_feature_info.status_values[gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION] =
-      gpu::kGpuFeatureStatusEnabled;
-  gpu_service_ = std::make_unique<viz::GpuServiceImpl>(
-      gpu::GPUInfo(), nullptr /* watchdog_thread */, io_thread_->task_runner(),
-      gpu_feature_info, gpu_preferences,
-      gpu::GPUInfo() /* gpu_info_for_hardware_gpu */,
-      gpu::GpuFeatureInfo() /* gpu_feature_info_for_hardware_gpu */,
-#if BUILDFLAG(ENABLE_VULKAN)
-      vulkan_implementation_.get(),
-#else
-      nullptr /* vulkan_implementation */,
-#endif
-      base::DoNothing() /* exit_callback */);
-
-  // Uses a null gpu_host here, because we don't want to receive any message.
-  std::unique_ptr<viz::mojom::GpuHost> gpu_host;
-  viz::mojom::GpuHostPtr gpu_host_proxy;
-  mojo::MakeStrongBinding(std::move(gpu_host),
-                          mojo::MakeRequest(&gpu_host_proxy));
-  gpu_service_->InitializeWithHost(
-      std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
-      gl::init::CreateOffscreenGLSurface(gfx::Size()),
-      nullptr /* sync_point_manager */, nullptr /* shared_image_manager */,
-      nullptr /* shutdown_event */);
-  task_executor_ = std::make_unique<gpu::GpuInProcessThreadService>(
-      gpu_thread_->task_runner(), gpu_service_->scheduler(),
-      gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
-      gpu_service_->share_group(),
-      gpu_service_->gpu_channel_manager()
-          ->default_offscreen_surface()
-          ->GetFormat(),
-      gpu_service_->gpu_feature_info(),
-      gpu_service_->gpu_channel_manager()->gpu_preferences(),
-      gpu_service_->shared_image_manager(),
-      gpu_service_->gpu_channel_manager()->program_cache());
-  event->Signal();
-}
-
 void PixelTest::SetUpSkiaRenderer(bool flipped_output_surface) {
   // Set up the GPU service.
   const char enable_features[] = "VizDisplayCompositor,UseSkiaRenderer";
   const char disable_features[] = "";
   scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list_->InitFromCommandLine(enable_features, disable_features);
-
-  gpu_thread_ = std::make_unique<base::Thread>("GPUMainThread");
-  ASSERT_TRUE(gpu_thread_->Start());
-  io_thread_ = std::make_unique<base::Thread>("GPUIOThread");
-  ASSERT_TRUE(io_thread_->Start());
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  gpu_thread_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&PixelTest::SetUpGpuServiceOnGpuThread,
-                                base::Unretained(this), &event));
-  event.Wait();
+  gpu_service_holder_ = std::make_unique<viz::TestGpuServiceHolder>();
 
   // Set up the skia renderer.
   output_surface_ = std::make_unique<PixelTestSkiaOutputSurfaceImpl>(
-      gpu_service_.get(), gpu::kNullSurfaceHandle, renderer_settings_,
+      gpu_service(), gpu::kNullSurfaceHandle, renderer_settings_,
       flipped_output_surface);
   output_surface_->BindToClient(output_surface_client_.get());
   resource_provider_ = std::make_unique<viz::DisplayResourceProvider>(
       viz::DisplayResourceProvider::kGpu,
-      nullptr /* compositor_context_provider */,
-      nullptr /* shared_bitmap_manager */);
+      /*compositor_context_provider=*/nullptr,
+      /*shared_bitmap_manager=*/nullptr);
   renderer_ = std::make_unique<viz::SkiaRenderer>(
       &renderer_settings_, output_surface_.get(), resource_provider_.get(),
       static_cast<viz::SkiaOutputSurface*>(output_surface_.get()),
@@ -375,11 +299,11 @@
   // Set up the client side context provider, etc
   gpu_memory_buffer_manager_ =
       std::make_unique<viz::InProcessGpuMemoryBufferManager>(
-          gpu_service_->gpu_memory_buffer_factory(),
-          gpu_service_->sync_point_manager());
-  gpu::ImageFactory* image_factory = gpu_service_->gpu_image_factory();
+          gpu_service()->gpu_memory_buffer_factory(),
+          gpu_service()->sync_point_manager());
+  gpu::ImageFactory* image_factory = gpu_service()->gpu_image_factory();
   auto* gpu_channel_manager_delegate =
-      gpu_service_->gpu_channel_manager()->delegate();
+      gpu_service()->gpu_channel_manager()->delegate();
   viz::RendererSettings renderer_settings;
   renderer_settings.requires_alpha_channel = false;
 #if defined(OS_ANDROID)
@@ -389,7 +313,7 @@
 #endif
   child_context_provider_ =
       base::MakeRefCounted<viz::VizProcessContextProvider>(
-          task_executor_.get(), gpu::kNullSurfaceHandle,
+          task_executor(), gpu::kNullSurfaceHandle,
           gpu_memory_buffer_manager_.get(), image_factory,
           gpu_channel_manager_delegate, renderer_settings);
   child_context_provider_->BindToCurrentThread();
@@ -398,36 +322,19 @@
       std::make_unique<viz::ClientResourceProvider>(sync_token_verification);
 }
 
-void PixelTest::TearDownGpuServiceOnGpuThread(base::WaitableEvent* event) {
-  task_executor_ = nullptr;
-  gpu_service_ = nullptr;
-  event->Signal();
-}
-
 void PixelTest::TearDown() {
   // Tear down the client side context provider, etc.
   child_resource_provider_->ShutdownAndReleaseAllResources();
-  child_resource_provider_ = nullptr;
-  child_context_provider_ = nullptr;
-  gpu_memory_buffer_manager_ = nullptr;
+  child_resource_provider_.reset();
+  child_context_provider_.reset();
+  gpu_memory_buffer_manager_.reset();
 
   // Tear down the skia renderer.
-  renderer_ = nullptr;
-  resource_provider_ = nullptr;
-  output_surface_ = nullptr;
-
-  if (task_executor_) {
-    // Tear down the GPU service.
-    base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                              base::WaitableEvent::InitialState::NOT_SIGNALED);
-    gpu_thread_->task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&PixelTest::TearDownGpuServiceOnGpuThread,
-                                  base::Unretained(this), &event));
-    event.Wait();
-  }
-  io_thread_ = nullptr;
-  gpu_thread_ = nullptr;
-  scoped_feature_list_ = nullptr;
+  renderer_.reset();
+  resource_provider_.reset();
+  output_surface_.reset();
+  gpu_service_holder_.reset();
+  scoped_feature_list_.reset();
 }
 
 void PixelTest::EnableExternalStencilTest() {
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 1fd8073..3fdb4f20 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -16,26 +16,18 @@
 #include "components/viz/service/display/output_surface.h"
 #include "components/viz/service/display/skia_renderer.h"
 #include "components/viz/service/display/software_renderer.h"
+#include "components/viz/test/test_gpu_service_holder.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "gpu/ipc/in_process_command_buffer.h"
-#include "gpu/vulkan/buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_implementation.h"
 
 namespace base {
-class Thread;
 namespace test {
 class ScopedFeatureList;
 }
 }
 
-#if BUILDFLAG(ENABLE_VULKAN)
-namespace gpu {
-class VulkanImplementation;
-}
-#endif
-
 namespace viz {
 class CopyOutputResult;
 class DirectRenderer;
@@ -77,6 +69,14 @@
     return output_surface_->context_provider();
   }
 
+  viz::GpuServiceImpl* gpu_service() {
+    return gpu_service_holder_->gpu_service();
+  }
+
+  gpu::CommandBufferTaskExecutor* task_executor() {
+    return gpu_service_holder_->task_executor();
+  }
+
   // Allocates a SharedMemory bitmap and registers it with the display
   // compositor's SharedBitmapManager.
   std::unique_ptr<base::SharedMemory> AllocateSharedBitmapMemory(
@@ -89,11 +89,8 @@
                                                   const SkBitmap& source);
 
   // For SkiaRenderer.
-  std::unique_ptr<base::Thread> gpu_thread_;
-  std::unique_ptr<base::Thread> io_thread_;
-  std::unique_ptr<viz::GpuServiceImpl> gpu_service_;
+  std::unique_ptr<viz::TestGpuServiceHolder> gpu_service_holder_;
   std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_;
-  std::unique_ptr<gpu::CommandBufferTaskExecutor> task_executor_;
 
   viz::RendererSettings renderer_settings_;
   gfx::Size device_viewport_size_;
@@ -123,15 +120,9 @@
 
   bool PixelsMatchReference(const base::FilePath& ref_file,
                             const PixelComparator& comparator);
-  void SetUpGpuServiceOnGpuThread(base::WaitableEvent* event);
-  void TearDownGpuServiceOnGpuThread(base::WaitableEvent* event);
 
   std::unique_ptr<gl::DisableNullDrawGLBindings> enable_pixel_output_;
   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
-
-#if BUILDFLAG(ENABLE_VULKAN)
-  std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation_;
-#endif
 };
 
 template<typename RendererType>
diff --git a/chrome/VERSION b/chrome/VERSION
index 3af9c3d..3d0ccd8a 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=76
 MINOR=0
-BUILD=3782
+BUILD=3783
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index fa153c8..d4a8d4e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -420,7 +420,6 @@
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity8.java",
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity9.java",
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskManagedCustomTabActivity.java",
-  "java/src/org/chromium/chrome/browser/customtabs/TabObserverRegistrar.java",
   "java/src/org/chromium/chrome/browser/customtabs/TranslucentCustomTabActivity.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityInitialPageLoader.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java",
@@ -1491,6 +1490,7 @@
   "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java",
   "java/src/org/chromium/chrome/browser/tab/TabHelpers.java",
   "java/src/org/chromium/chrome/browser/tab/TabObserver.java",
+  "java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java",
   "java/src/org/chromium/chrome/browser/tab/TabParentIntent.java",
   "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java",
   "java/src/org/chromium/chrome/browser/tab/TabState.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
index fe176af9..ae8dfae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
@@ -31,6 +30,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.content_public.browser.NavigationHandle;
 
 import java.lang.annotation.Retention;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
index 546ba20..384f158 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
@@ -25,13 +25,13 @@
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.TranslucentCustomTabActivity;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index d96e5ea..833bcee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -75,6 +75,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabAssociatedApp;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
index 203a2600..01c485bf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.customtabs.FirstMeaningfulPaintObserver;
 import org.chromium.chrome.browser.customtabs.PageLoadMetricsObserver;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
@@ -40,6 +39,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabAssociatedApp;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParams;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
index 89cd2b5..abbe913 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
@@ -10,7 +10,6 @@
 import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
 import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityInitialPageLoader;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
@@ -21,6 +20,7 @@
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 
 import dagger.Subcomponent;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
index 4036c59..2246704b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
@@ -43,6 +42,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java
index 9626cdf..5307cb0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.metrics;
 
-import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.webapps.SplashscreenObserver;
 
 /**
@@ -12,15 +11,10 @@
  * shell.
  */
 public class WebApkSplashscreenMetrics implements SplashscreenObserver {
-    private long mShellApkLaunchTimeMs = -1;
+    private final long mShellApkLaunchTimeMs;
     private long mSplashScreenShownTimeMs = -1;
 
-    /**
-     * Marks that splashscreen metrics should be tracked (if the {@param shellApkLaunchTimeMs} is
-     * not -1, otherwise it is ignored). Must only be called on the UI thread.
-     */
-    public void trackSplashscreenMetrics(long shellApkLaunchTimeMs) {
-        ThreadUtils.assertOnUiThread();
+    public WebApkSplashscreenMetrics(long shellApkLaunchTimeMs) {
         mShellApkLaunchTimeMs = shellApkLaunchTimeMs;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
index 5ec78012..7d227d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
@@ -68,6 +68,13 @@
     }
 
     /**
+     * Wipes all data for this profile.
+     */
+    public void wipe() {
+        nativeWipe(mNativeProfileAndroid);
+    }
+
+    /**
      * @return Whether or not the native side profile exists.
      */
     @VisibleForTesting
@@ -101,4 +108,5 @@
     private native boolean nativeHasOffTheRecordProfile(long nativeProfileAndroid);
     private native boolean nativeIsOffTheRecord(long nativeProfileAndroid);
     private native boolean nativeIsChild(long nativeProfileAndroid);
+    private native void nativeWipe(long nativeProfileAndroid);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/TabObserverRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java
similarity index 95%
rename from chrome/android/java/src/org/chromium/chrome/browser/customtabs/TabObserverRegistrar.java
rename to chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java
index 04d372a..b48cff7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/TabObserverRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.customtabs;
+package org.chromium.chrome.browser.tab;
 
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 
 import java.util.HashSet;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
index 3a5951b..334647e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -263,8 +263,9 @@
             return mIsIncognito ? mIncognitoPrimaryBgColor : mStandardPrimaryBgColor;
         }
 
-        // Return status bar color in standard NewTabPage.
-        if (isStandardNTP()) {
+        // Return status bar color in standard NewTabPage. If location bar is not shown in NTP, we
+        // use the tab theme color regardless of the URL expansion percentage.
+        if (isLocationBarShownInNTP()) {
             return ColorUtils.getColorWithOverlay(
                     TabThemeColorHelper.getBackgroundColor(mCurrentTab),
                     TabThemeColorHelper.getColor(mCurrentTab), mToolbarUrlExpansionPercentage);
@@ -322,6 +323,15 @@
      * @return Whether or not the current tab is a new tab page in standard mode.
      */
     private boolean isStandardNTP() {
-        return mCurrentTab != null && NewTabPage.isNTPUrl(mCurrentTab.getUrl()) && !mIsIncognito;
+        return mCurrentTab != null && mCurrentTab.getNativePage() instanceof NewTabPage;
+    }
+
+    /**
+     * @return Whether or not the fake location bar is shown on the current NTP.
+     */
+    private boolean isLocationBarShownInNTP() {
+        if (!isStandardNTP()) return false;
+        final NewTabPage newTabPage = (NewTabPage) mCurrentTab.getNativePage();
+        return newTabPage != null && newTabPage.isLocationBarShownInNTP();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java
index f1609070..0d0acf89 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SameActivityWebappSplashDelegate.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.webapps;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -17,8 +18,11 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.TraceEvent;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
 import org.chromium.chrome.browser.metrics.SameActivityWebappUmaCache;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.webapk.lib.common.splash.SplashLayout;
 
@@ -26,7 +30,11 @@
  * Delegate for when splash screen is shown by Chrome (as opposed to by external non-Chrome
  * activity).
  */
-public class SameActivityWebappSplashDelegate implements SplashDelegate {
+public class SameActivityWebappSplashDelegate implements SplashDelegate, NativeInitObserver {
+    private Activity mActivity;
+    private ActivityLifecycleDispatcher mLifecycleDispatcher;
+    private TabObserverRegistrar mTabObserverRegistrar;
+
     /** View to which the splash screen is added. */
     private ViewGroup mParentView;
 
@@ -38,8 +46,6 @@
     /** Whether native was loaded. Native must be loaded in order to record metrics. */
     private boolean mNativeLoaded;
 
-    private Tab mTab;
-
     private WebappInfo mWebappInfo;
 
     private SameActivityWebappUmaCache mUmaCache;
@@ -71,12 +77,28 @@
         }
     };
 
+    public SameActivityWebappSplashDelegate(Activity activity,
+            ActivityLifecycleDispatcher lifecycleDispatcher,
+            TabObserverRegistrar tabObserverRegistrar) {
+        mActivity = activity;
+        mLifecycleDispatcher = lifecycleDispatcher;
+        mTabObserverRegistrar = tabObserverRegistrar;
+
+        mLifecycleDispatcher.register(this);
+    }
+
     @Override
     public void showSplash(ViewGroup parentView, WebappInfo webappInfo) {
         mParentView = parentView;
         mWebappInfo = webappInfo;
         mIsSplashVisible = true;
 
+        if (mWebappInfo.isForWebApk()) {
+            mWebApkNetworkErrorObserver =
+                    new WebApkSplashNetworkErrorObserver(mActivity, mWebappInfo.name());
+            mTabObserverRegistrar.registerTabObserver(mWebApkNetworkErrorObserver);
+        }
+
         Context context = ContextUtils.getApplicationContext();
         final int backgroundColor = ColorUtils.getOpaqueColor(webappInfo.backgroundColor(
                 ApiCompatibilityUtils.getColor(context.getResources(), R.color.webapp_default_bg)));
@@ -107,19 +129,13 @@
     }
 
     @Override
-    public void showSplashWithNative(Tab tab) {
+    public void onFinishNativeInitialization() {
         mNativeLoaded = true;
-        mTab = tab;
-        if (mWebappInfo.isForWebApk()) {
-            mWebApkNetworkErrorObserver =
-                    new WebApkSplashNetworkErrorObserver(tab.getActivity(), mWebappInfo.name());
-            mTab.addObserver(mWebApkNetworkErrorObserver);
-        }
         if (mUmaCache != null) mUmaCache.commitMetrics();
     }
 
     @Override
-    public void hideSplash(final Runnable finishedHidingCallback) {
+    public void hideSplash(Tab tab, final Runnable finishedHidingCallback) {
         assert mIsSplashVisible;
 
         mIsSplashVisible = false;
@@ -129,12 +145,14 @@
             public void run() {
                 mParentView.removeView(mSplashScreen);
                 if (mWebApkNetworkErrorObserver != null) {
-                    mTab.removeObserver(mWebApkNetworkErrorObserver);
+                    mTabObserverRegistrar.unregisterTabObserver(mWebApkNetworkErrorObserver);
+                    tab.removeObserver(mWebApkNetworkErrorObserver);
                     mWebApkNetworkErrorObserver = null;
                 }
+                mLifecycleDispatcher.unregister(SameActivityWebappSplashDelegate.this);
 
                 recordTraceEventsFinishedHidingSplash();
-                mTab = null;
+                mActivity = null;
                 mSplashScreen = null;
                 finishedHidingCallback.run();
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
index 07311c7f..e6300ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
@@ -12,9 +12,10 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.WarmupManager;
-import org.chromium.chrome.browser.compositor.CompositorViewHolder;
+import org.chromium.chrome.browser.compositor.CompositorView;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -36,10 +37,9 @@
     public static final String HISTOGRAM_SPLASHSCREEN_DURATION = "Webapp.Splashscreen.Duration";
     public static final String HISTOGRAM_SPLASHSCREEN_HIDES = "Webapp.Splashscreen.Hides";
 
-    private SplashDelegate mDelegate;
+    private final TabObserverRegistrar mTabObserverRegistrar;
 
-    /** Used to schedule splash screen hiding. */
-    private CompositorViewHolder mCompositorViewHolder;
+    private SplashDelegate mDelegate;
 
     /** View to which the splash screen is added. */
     private ViewGroup mParentView;
@@ -49,16 +49,19 @@
 
     private ObserverList<SplashscreenObserver> mObservers;
 
-    public SplashController() {
+    public SplashController(TabObserverRegistrar tabObserverRegistrar) {
+        mTabObserverRegistrar = tabObserverRegistrar;
+        mTabObserverRegistrar.registerTabObserver(this);
         mObservers = new ObserverList<>();
     }
 
     /** Shows the splash screen. */
-    public void showSplash(ViewGroup parentView, final WebappInfo webappInfo) {
+    public void showSplash(
+            SplashDelegate delegate, ViewGroup parentView, final WebappInfo webappInfo) {
+        mDelegate = delegate;
         mParentView = parentView;
         mSplashShownTimestamp = SystemClock.elapsedRealtime();
 
-        mDelegate = new SameActivityWebappSplashDelegate();
         mDelegate.showSplash(parentView, webappInfo);
 
         notifySplashscreenVisible(mSplashShownTimestamp);
@@ -76,13 +79,6 @@
         }
     }
 
-    /** Should be called once native has loaded and after {@link #showSplash()}. */
-    public void showSplashWithNative(Tab tab, CompositorViewHolder compositorViewHolder) {
-        mCompositorViewHolder = compositorViewHolder;
-        tab.addObserver(this);
-        mDelegate.showSplashWithNative(tab);
-    }
-
     @VisibleForTesting
     ViewGroup getSplashScreenForTests() {
         if (mDelegate == null) return null;
@@ -126,8 +122,8 @@
         final Runnable onHiddenCallback = new Runnable() {
             @Override
             public void run() {
+                mTabObserverRegistrar.unregisterTabObserver(SplashController.this);
                 tab.removeObserver(SplashController.this);
-                mCompositorViewHolder = null;
                 mDelegate = null;
 
                 long splashHiddenTimestamp = SystemClock.elapsedRealtime();
@@ -137,15 +133,17 @@
             }
         };
         if (reason == SplashHidesReason.LOAD_FAILED || reason == SplashHidesReason.CRASH) {
-            mDelegate.hideSplash(onHiddenCallback);
+            mDelegate.hideSplash(tab, onHiddenCallback);
             return;
         }
         // Delay hiding the splash screen till the compositor has finished drawing the next frame.
         // Without this callback we were seeing a short flash of white between the splash screen and
         // the web content (crbug.com/734500).
-        mCompositorViewHolder.getCompositorView().surfaceRedrawNeededAsync(() -> {
+        CompositorView compositorView =
+                tab.getActivity().getCompositorViewHolder().getCompositorView();
+        compositorView.surfaceRedrawNeededAsync(() -> {
             if (mDelegate == null || !mDelegate.isSplashVisible()) return;
-            mDelegate.hideSplash(onHiddenCallback);
+            mDelegate.hideSplash(tab, onHiddenCallback);
         });
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java
index d7dc7a4a..cc98721 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashDelegate.java
@@ -13,11 +13,8 @@
     /** Shows the splash screen. */
     void showSplash(ViewGroup parentView, WebappInfo webappInfo);
 
-    /** Called once native has been loaded and after {@link #showSplash()}. */
-    void showSplashWithNative(Tab tab);
-
     /** Hides the splash screen. Runs the callback once the splash screen is hidden. */
-    void hideSplash(Runnable finishedHidingCallback);
+    void hideSplash(Tab tab, Runnable finishedHidingCallback);
 
     /** Returns whether the splash screen is visible and not in the process of hiding. */
     boolean isSplashVisible();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index 63f2367..3f2709f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -29,8 +29,6 @@
     /** The start time that the activity becomes focused. */
     private long mStartTime;
 
-    private WebApkSplashscreenMetrics mWebApkSplashscreenMetrics;
-
     private static final String TAG = "cr_WebApkActivity";
 
     @VisibleForTesting
@@ -120,9 +118,6 @@
         if (mUpdateManager != null) {
             mUpdateManager.destroy();
         }
-        if (mWebApkSplashscreenMetrics != null) {
-            mWebApkSplashscreenMetrics = null;
-        }
 
         // The common case is to be connected to just one WebAPK's services. For the sake of
         // simplicity disconnect from the services of all WebAPKs.
@@ -150,7 +145,14 @@
     }
 
     @Override
-    public void performPreInflationStartup() {
+    protected boolean loadUrlIfPostShareTarget(WebappInfo webappInfo) {
+        WebApkInfo webApkInfo = (WebApkInfo) webappInfo;
+        return WebApkPostShareTargetNavigator.navigateIfPostShareTarget(
+                webApkInfo, getActivityTab().getWebContents());
+    }
+
+    @Override
+    protected void showSplash() {
         // Decide whether to record startup UMA histograms. This is a similar check to the one done
         // in ChromeTabbedActivity.performPreInflationStartup refer to the comment there for why.
         if (!LibraryLoader.getInstance().isInitialized()) {
@@ -160,23 +162,11 @@
             if (getSavedInstanceState() == null) {
                 long shellLaunchTimestampMs =
                         IntentHandler.getWebApkShellLaunchTimestampFromIntent(getIntent());
-                mWebApkSplashscreenMetrics.trackSplashscreenMetrics(shellLaunchTimestampMs);
+                // Splash observers are removed once the splash screen is hidden.
+                addSplashscreenObserver(new WebApkSplashscreenMetrics(shellLaunchTimestampMs));
             }
         }
-        super.performPreInflationStartup();
-    }
 
-    @Override
-    protected void initializeStartupMetrics() {
-        super.initializeStartupMetrics();
-        mWebApkSplashscreenMetrics = new WebApkSplashscreenMetrics();
-        addSplashscreenObserver(mWebApkSplashscreenMetrics);
-    }
-
-    @Override
-    protected boolean loadUrlIfPostShareTarget(WebappInfo webappInfo) {
-        WebApkInfo webApkInfo = (WebApkInfo) webappInfo;
-        return WebApkPostShareTargetNavigator.navigateIfPostShareTarget(
-                webApkInfo, getActivityTab().getWebContents());
+        super.showSplash();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
index 9f14cef3..1f234cb5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
@@ -17,7 +17,7 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.webapk.lib.client.DexOptimizer;
 import org.chromium.webapk.lib.client.WebApkVersion;
-import org.chromium.webapk.lib.common.WebApkVersionUtils;
+import org.chromium.webapk.lib.common.WebApkCommonUtils;
 
 import java.io.File;
 
@@ -70,7 +70,7 @@
         dexDir = context.getDir("dex", Context.MODE_PRIVATE);
 
         String dexName =
-                WebApkVersionUtils.getRuntimeDexName(WebApkVersion.CURRENT_RUNTIME_DEX_VERSION);
+                WebApkCommonUtils.getRuntimeDexName(WebApkVersion.CURRENT_RUNTIME_DEX_VERSION);
         File dexFile = new File(dexDir, dexName);
         if (!FileUtils.extractAsset(context, dexName, dexFile)) {
             return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 2d93e89..5b55ad9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -50,6 +50,7 @@
 import org.chromium.chrome.browser.tab.TabBrowserControlsState;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
@@ -92,6 +93,8 @@
 
     private WebappInfo mWebappInfo;
 
+    private TabObserverRegistrar mTabObserverRegistrar;
+
     private SplashController mSplashController;
 
     private WebappDisclosureSnackbarController mDisclosureSnackbarController;
@@ -135,7 +138,8 @@
     public WebappActivity() {
         mWebappInfo = createWebappInfo(null);
         mDirectoryManager = new WebappDirectoryManager();
-        mSplashController = new SplashController();
+        mTabObserverRegistrar = new TabObserverRegistrar(getLifecycleDispatcher());
+        mSplashController = new SplashController(mTabObserverRegistrar);
         mDisclosureSnackbarController = new WebappDisclosureSnackbarController();
     }
 
@@ -189,6 +193,7 @@
     @Override
     public void initializeState() {
         super.initializeState();
+        mTabObserverRegistrar.addObserversForTab(getActivityTab());
         initializeUI(getSavedInstanceState());
     }
 
@@ -305,10 +310,8 @@
         if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) {
             enterImmersiveMode();
         }
-        try (TraceEvent te = TraceEvent.scoped("WebappActivity.showSplash")) {
-            ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
-            mSplashController.showSplash(contentView, mWebappInfo);
-        }
+
+        showSplash();
     }
 
     @Override
@@ -324,7 +327,6 @@
         getToolbarManager().setCloseButtonDrawable(null); // Hides close button.
 
         getFullscreenManager().setTab(getActivityTab());
-        mSplashController.showSplashWithNative(getActivityTab(), getCompositorViewHolder());
         super.finishNativeInitialization();
         mIsInitialized = true;
     }
@@ -883,6 +885,16 @@
         return false;
     }
 
+    /** Shows the splash screen. */
+    protected void showSplash() {
+        try (TraceEvent te = TraceEvent.scoped("WebappActivity.showSplash")) {
+            ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
+            SplashDelegate delegate = new SameActivityWebappSplashDelegate(
+                    this, getLifecycleDispatcher(), mTabObserverRegistrar);
+            mSplashController.showSplash(delegate, contentView, mWebappInfo);
+        }
+    }
+
     /**
      * Register an observer to the splashscreen hidden/visible events for this activity.
      */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java
index 00d140f..f4f486ca 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifierTest.java
@@ -37,11 +37,11 @@
 import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityVerifier.VerificationStatus;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
index ab544b65..80c5aa5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -41,12 +41,12 @@
 import org.chromium.chrome.browser.customtabs.CustomTabObserver;
 import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.shadows.ShadowExternalNavigationDelegateImpl;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl;
diff --git a/chrome/android/webapk/libs/common/BUILD.gn b/chrome/android/webapk/libs/common/BUILD.gn
index da53ae3..dc353c13 100644
--- a/chrome/android/webapk/libs/common/BUILD.gn
+++ b/chrome/android/webapk/libs/common/BUILD.gn
@@ -6,10 +6,10 @@
 
 android_library("common_java") {
   java_files = [
+    "src/org/chromium/webapk/lib/common/WebApkCommonUtils.java",
     "src/org/chromium/webapk/lib/common/WebApkConstants.java",
     "src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java",
     "src/org/chromium/webapk/lib/common/WebApkMetaDataUtils.java",
-    "src/org/chromium/webapk/lib/common/WebApkVersionUtils.java",
   ]
   srcjar_deps = [ "//chrome/android/webapk/libs/common:identity_service_aidl" ]
 }
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkVersionUtils.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkCommonUtils.java
similarity index 80%
rename from chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkVersionUtils.java
rename to chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkCommonUtils.java
index c9838b2..20397322 100644
--- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkVersionUtils.java
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkCommonUtils.java
@@ -4,10 +4,8 @@
 
 package org.chromium.webapk.lib.common;
 
-/**
- * Contains versioning utility methods.
- */
-public class WebApkVersionUtils {
+/** Contains utility methods which are used both by ShellAPK and by Chrome. */
+public class WebApkCommonUtils {
     /**
      * Returns name of "Runtime Dex" asset in Chrome APK based on version.
      * @param version
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java
index 3a63e0c..4438857 100644
--- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java
+++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java
@@ -19,7 +19,7 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.testing.local.LocalRobolectricTestRunner;
-import org.chromium.webapk.lib.common.WebApkVersionUtils;
+import org.chromium.webapk.lib.common.WebApkCommonUtils;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -75,7 +75,7 @@
     public void testNewRuntimeDexVersion() {
         HostBrowserClassLoader.createClassLoader(mContext, mRemoteContext, mMockDexLoader, null);
 
-        String expectedDexName = WebApkVersionUtils.getRuntimeDexName(REMOTE_DEX_VERSION);
+        String expectedDexName = WebApkCommonUtils.getRuntimeDexName(REMOTE_DEX_VERSION);
         verifyDexLoaderLoadCall(expectedDexName);
         Mockito.reset(mMockDexLoader);
 
@@ -83,7 +83,7 @@
         setRemoteDexVersion(REMOTE_DEX_VERSION + 1);
         HostBrowserClassLoader.createClassLoader(mContext, mRemoteContext, mMockDexLoader, null);
 
-        expectedDexName = WebApkVersionUtils.getRuntimeDexName(REMOTE_DEX_VERSION + 1);
+        expectedDexName = WebApkCommonUtils.getRuntimeDexName(REMOTE_DEX_VERSION + 1);
         verifyDexLoaderLoadCall(expectedDexName);
     }
 
@@ -93,7 +93,7 @@
      */
     @Test
     public void testCreateClassLoaderTwiceSameCachedData() {
-        String expectedDexName = WebApkVersionUtils.getRuntimeDexName(REMOTE_DEX_VERSION);
+        String expectedDexName = WebApkCommonUtils.getRuntimeDexName(REMOTE_DEX_VERSION);
         HostBrowserClassLoader.createClassLoader(mContext, mRemoteContext, mMockDexLoader, null);
         verifyDexLoaderLoadCall(expectedDexName);
         Mockito.reset(mMockDexLoader);
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
index 15a6b45..2277354 100644
--- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
+++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java
@@ -10,7 +10,7 @@
 import android.os.Looper;
 import android.util.Log;
 
-import org.chromium.webapk.lib.common.WebApkVersionUtils;
+import org.chromium.webapk.lib.common.WebApkCommonUtils;
 
 import java.io.File;
 import java.util.Scanner;
@@ -77,7 +77,7 @@
             dexLoader.deleteCachedDexes(localDexDir);
         }
 
-        String dexAssetName = WebApkVersionUtils.getRuntimeDexName(newRuntimeDexVersion);
+        String dexAssetName = WebApkCommonUtils.getRuntimeDexName(newRuntimeDexVersion);
         File remoteDexFile =
                 new File(remoteContext.getDir(DEX_DIR_NAME, Context.MODE_PRIVATE), dexAssetName);
         return dexLoader.load(
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 7349f03..9663be8 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2002,6 +2002,9 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(net::features::kEnforceTLS13Downgrade,
                                     kEnforceTLS13DowngradeFeatureVariations,
                                     "EnforceTLS13Downgrade")},
+    {"enable-tls13-early-data", flag_descriptions::kEnableTLS13EarlyDataName,
+     flag_descriptions::kEnableTLS13EarlyDataDescription, kOsAll,
+     FEATURE_VALUE_TYPE(net::features::kEnableTLS13EarlyData)},
     {"enable-scroll-anchor-serialization",
      flag_descriptions::kEnableScrollAnchorSerializationName,
      flag_descriptions::kEnableScrollAnchorSerializationDescription, kOsAll,
@@ -3888,6 +3891,18 @@
      kOsDesktop,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillDoNotMigrateUnsupportedLocalCards)},
+    {"enable-unsafe-webgpu", flag_descriptions::kUnsafeWebGPUName,
+     flag_descriptions::kUnsafeWebGPUDescription, kOsMac,
+     SINGLE_VALUE_TYPE(switches::kEnableUnsafeWebGPU)},
+
+#if defined(OS_ANDROID)
+    {"autofill-use-mobile-label-disambiguation",
+     flag_descriptions::kAutofillUseMobileLabelDisambiguationName,
+     flag_descriptions::kAutofillUseMobileLabelDisambiguationDescription,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(
+         autofill::features::kAutofillUseMobileLabelDisambiguation)},
+#endif  // defined(OS_ANDROID)
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
diff --git a/chrome/browser/apps/app_service/app_service_proxy_impl.cc b/chrome/browser/apps/app_service/app_service_proxy_impl.cc
index 12dae356..0a7eaad 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_impl.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_impl.cc
@@ -89,23 +89,25 @@
   connector->BindInterface(apps::mojom::kServiceName,
                            mojo::MakeRequest(&app_service_));
 
-  // The AppServiceProxyImpl is a subscriber: something that wants to be able
-  // to list all known apps.
-  apps::mojom::SubscriberPtr subscriber;
-  bindings_.AddBinding(this, mojo::MakeRequest(&subscriber));
-  app_service_->RegisterSubscriber(std::move(subscriber), nullptr);
+  if (app_service_.is_bound()) {
+    // The AppServiceProxyImpl is a subscriber: something that wants to be able
+    // to list all known apps.
+    apps::mojom::SubscriberPtr subscriber;
+    bindings_.AddBinding(this, mojo::MakeRequest(&subscriber));
+    app_service_->RegisterSubscriber(std::move(subscriber), nullptr);
 
 #if defined(OS_CHROMEOS)
-  // The AppServiceProxyImpl is also a publisher, of a variety of app types.
-  // That responsibility isn't intrinsically part of the AppServiceProxyImpl,
-  // but doing that here, for each such app type, is as good a place as any.
-  built_in_chrome_os_apps_.Initialize(app_service_, profile);
-  crostini_apps_.Initialize(app_service_, profile);
-  extension_apps_.Initialize(app_service_, profile,
-                             apps::mojom::AppType::kExtension);
-  extension_web_apps_.Initialize(app_service_, profile,
-                                 apps::mojom::AppType::kWeb);
+    // The AppServiceProxyImpl is also a publisher, of a variety of app types.
+    // That responsibility isn't intrinsically part of the AppServiceProxyImpl,
+    // but doing that here, for each such app type, is as good a place as any.
+    built_in_chrome_os_apps_.Initialize(app_service_, profile);
+    crostini_apps_.Initialize(app_service_, profile);
+    extension_apps_.Initialize(app_service_, profile,
+                               apps::mojom::AppType::kExtension);
+    extension_web_apps_.Initialize(app_service_, profile,
+                                   apps::mojom::AppType::kWeb);
 #endif  // OS_CHROMEOS
+  }
 }
 
 AppServiceProxyImpl::~AppServiceProxyImpl() = default;
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index 3324eb0..776a6214 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -166,6 +166,12 @@
     return;
   }
 
+  apps::mojom::AppServicePtr& app_service =
+      apps::AppServiceProxyFactory::GetForProfile(profile)->AppService();
+  if (!app_service.is_bound()) {
+    return;
+  }
+
   prefs_ = ArcAppListPrefs::Get(profile);
   if (!prefs_) {
     return;
@@ -175,9 +181,8 @@
 
   apps::mojom::PublisherPtr publisher;
   binding_.Bind(mojo::MakeRequest(&publisher));
-  apps::AppServiceProxyFactory::GetForProfile(profile)
-      ->AppService()
-      ->RegisterPublisher(std::move(publisher), apps::mojom::AppType::kArc);
+  app_service->RegisterPublisher(std::move(publisher),
+                                 apps::mojom::AppType::kArc);
 }
 
 ArcApps::~ArcApps() {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index a07b7e50..8b487cf 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -128,8 +128,6 @@
     "//chromeos/services/multidevice_setup/public/cpp:auth_token_validator",
     "//chromeos/services/multidevice_setup/public/cpp:oobe_completion_tracker",
     "//chromeos/services/multidevice_setup/public/cpp:prefs",
-    "//chromeos/services/power/public/cpp:client",
-    "//chromeos/services/power/public/mojom",
     "//chromeos/services/secure_channel/public/cpp/client",
     "//chromeos/settings",
     "//chromeos/system",
diff --git a/chrome/browser/chromeos/app_mode/app_session.cc b/chrome/browser/chromeos/app_mode/app_session.cc
index 5f37e50a..535b67ae 100644
--- a/chrome/browser/chromeos/app_mode/app_session.cc
+++ b/chrome/browser/chromeos/app_mode/app_session.cc
@@ -29,9 +29,9 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
@@ -61,7 +61,7 @@
 }
 
 void RebootDevice() {
-  PowerManagerMojoClient::Get()->RequestRestart(
+  PowerManagerClient::Get()->RequestRestart(
       power_manager::REQUEST_RESTART_OTHER, "kiosk app session");
 }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.cc b/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.cc
index a6738928..0dcd3b3 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.cc
@@ -11,8 +11,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "components/user_manager/user_manager.h"
 #include "extensions/browser/extension_system.h"
 #include "ui/base/user_activity/user_activity_detector.h"
@@ -64,7 +63,7 @@
   if (user_activity_detector && user_activity_detector->HasObserver(this))
     user_activity_detector->RemoveObserver(this);
 
-  auto* power_manager = chromeos::PowerManagerMojoClient::Get();
+  auto* power_manager = chromeos::PowerManagerClient::Get();
   if (power_manager && power_manager->HasObserver(this))
     power_manager->RemoveObserver(this);
 }
@@ -110,7 +109,7 @@
 void KioskModeIdleAppNameNotification::Start() {
   if (!ui::UserActivityDetector::Get()->HasObserver(this)) {
     ui::UserActivityDetector::Get()->AddObserver(this);
-    chromeos::PowerManagerMojoClient::Get()->AddObserver(this);
+    chromeos::PowerManagerClient::Get()->AddObserver(this);
   }
   ResetTimer();
 }
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 16117c26..9b64a40b 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -148,7 +148,6 @@
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/portal_detector/network_portal_detector_stub.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
 #include "chromeos/system/statistics_provider.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "chromeos/tpm/tpm_token_loader.h"
@@ -569,9 +568,6 @@
   // DBus is initialized in ChromeMainDelegate::PostEarlyInitialization().
   CHECK(DBusThreadManager::IsInitialized());
 
-  if (base::FeatureList::IsEnabled(features::kMojoDBusRelay))
-    power_manager_mojo_client_ = std::make_unique<PowerManagerMojoClient>();
-
   if (!base::SysInfo::IsRunningOnChromeOS() &&
       parsed_command_line().HasSwitch(
           switches::kFakeDriveFsLauncherChrootPath) &&
@@ -611,17 +607,6 @@
   ChromeBrowserMainPartsLinux::PostMainMessageLoopStart();
 }
 
-void ChromeBrowserMainPartsChromeos::ServiceManagerConnectionStarted(
-    content::ServiceManagerConnection* connection) {
-  if (base::FeatureList::IsEnabled(features::kMojoDBusRelay)) {
-    connection->GetConnector()->BindInterface(
-        ash::mojom::kServiceName, power_manager_mojo_client_->interface_ptr());
-    power_manager_mojo_client_->InitAfterInterfaceBound();
-  }
-
-  ChromeBrowserMainPartsLinux::ServiceManagerConnectionStarted(connection);
-}
-
 // Threads are initialized between MainMessageLoopStart and MainMessageLoopRun.
 // about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads.
 void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index 811ba060..c68e257 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -49,7 +49,6 @@
 class NetworkChangeManagerClient;
 class NetworkPrefStateObserver;
 class NetworkThrottlingObserver;
-class PowerManagerMojoClient;
 class PowerMetricsReporter;
 class RendererFreezer;
 class SchedulerConfigurationManager;
@@ -94,8 +93,6 @@
   int PreEarlyInitialization() override;
   void PreMainMessageLoopStart() override;
   void PostMainMessageLoopStart() override;
-  void ServiceManagerConnectionStarted(
-      content::ServiceManagerConnection* connection) override;
   void PreMainMessageLoopRun() override;
 
   // Stages called from PreMainMessageLoopRun.
@@ -166,8 +163,6 @@
   std::unique_ptr<SchedulerConfigurationManager>
       scheduler_configuration_manager_;
 
-  std::unique_ptr<chromeos::PowerManagerMojoClient> power_manager_mojo_client_;
-
   std::unique_ptr<CrosUsbDetector> cros_usb_detector_;
   std::unique_ptr<DiagnosticsdManager> diagnosticsd_manager_;
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc
index 5170b88..91527e4 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
 #include "components/prefs/pref_service.h"
 
 namespace chromeos {
@@ -99,7 +99,7 @@
 
 void Adapter::Init() {
   // Deferred to Init() because it can result in a virtual method being called.
-  power_manager_client_observer_.Add(PowerManagerMojoClient::Get());
+  power_manager_client_observer_.Add(PowerManagerClient::Get());
 }
 
 void Adapter::OnAmbientLightUpdated(int lux) {
@@ -604,7 +604,7 @@
   request.set_transition(
       power_manager::SetBacklightBrightnessRequest_Transition_GRADUAL);
   request.set_cause(power_manager::SetBacklightBrightnessRequest_Cause_MODEL);
-  PowerManagerMojoClient::Get()->SetScreenBrightness(request);
+  PowerManagerClient::Get()->SetScreenBrightness(request);
 
   const base::TimeTicks brightness_change_time = tick_clock_->NowTicks();
   if (!latest_model_brightness_change_time_.is_null()) {
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.cc b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.cc
index 169d35f..c444a678 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl.cc
@@ -14,9 +14,8 @@
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/utils.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
 
 namespace chromeos {
 namespace power {
@@ -37,7 +36,7 @@
           ? kBrightnessSampleDelay
           : base::TimeDelta::FromSeconds(brightness_sample_delay_seconds);
 
-  power_manager_client_observer_.Add(PowerManagerMojoClient::Get());
+  power_manager_client_observer_.Add(PowerManagerClient::Get());
 }
 
 void BrightnessMonitorImpl::AddObserver(
@@ -63,7 +62,7 @@
     OnInitializationComplete();
     return;
   }
-  PowerManagerMojoClient::Get()->GetScreenBrightnessPercent(
+  PowerManagerClient::Get()->GetScreenBrightnessPercent(
       base::BindOnce(&BrightnessMonitorImpl::OnReceiveInitialBrightnessPercent,
                      weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 67b0397b..c95018233 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -289,6 +289,11 @@
     "expiry_milestone": 77
   },
   {
+    "name": "autofill-use-mobile-label-disambiguation",
+    "owners": [ "ftirelo", "tmartino" ],
+    "expiry_milestone": 79
+  },
+  {
     "name": "automatic-password-generation",
     "owners": [ "ioanap", "fhorschig" ],
     "expiry_milestone": 76
@@ -1726,6 +1731,11 @@
     "expiry_milestone": 77
   },
   {
+    "name": "enable-tls13-early-data",
+    "owners": [ "svaldez" ],
+    "expiry_milestone": 83
+  },
+  {
     "name": "enable-touch-drag-drop",
     "owners": [ "eirage", "input-dev" ],
     "expiry_milestone": 78
@@ -1738,6 +1748,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "enable-unsafe-webgpu",
+    "owners": [ "//third_party/blink/renderer/modules/webgpu/OWNERS" ],
+    "expiry_milestone": 82
+  },
+  {
     "name": "enable-ui-devtools",
     "owners": [ "//components/ui_devtools/OWNERS" ],
     // Convenience debugging flag for non-stable ChromeOS Builds.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8fe50b4..d8197e9 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -125,6 +125,24 @@
     "When enabled, Autofill data related icon will be shown in the status "
     "chip next to the profile avatar icon in the toolbar.";
 
+const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[] =
+    "Autofill Enforce Min Required Fields For Heuristics";
+const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[] =
+    "When enabled, autofill will generally require a form to have at least 3 "
+    "fields before allowing heuristic field-type prediction to occur.";
+
+const char kAutofillEnforceMinRequiredFieldsForQueryName[] =
+    "Autofill Enforce Min Required Fields For Query";
+const char kAutofillEnforceMinRequiredFieldsForQueryDescription[] =
+    "When enabled, autofill will generally require a form to have at least 3 "
+    "fields before querying the autofill server for field-type predictions.";
+
+const char kAutofillEnforceMinRequiredFieldsForUploadName[] =
+    "Autofill Enforce Min Required Fields For Upload";
+const char kAutofillEnforceMinRequiredFieldsForUploadDescription[] =
+    "When enabled, autofill will generally require a form to have at least 3 "
+    "fillable fields before uploading field-type votes for that form.";
+
 const char kAutofillNoLocalSaveOnUnmaskSuccessName[] =
     "Remove the option to save local copies of unmasked server cards";
 const char kAutofillNoLocalSaveOnUnmaskSuccessDescription[] =
@@ -159,30 +177,6 @@
     "Autofill rejects using non-verified company names that are in the "
     "format of a birthyear.";
 
-const char kAutofillUseImprovedLabelDisambiguationName[] =
-    "Autofill Uses Improved Label Disambiguation";
-const char kAutofillUseImprovedLabelDisambiguationDescription[] =
-    "When enabled, the Autofill dropdown's suggestions' labels are displayed "
-    "using the improved disambiguation format.";
-
-const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[] =
-    "Autofill Enforce Min Required Fields For Heuristics";
-const char kAutofillEnforceMinRequiredFieldsForHeuristicsDescription[] =
-    "When enabled, autofill will generally require a form to have at least 3 "
-    "fields before allowing heuristic field-type prediction to occur.";
-
-const char kAutofillEnforceMinRequiredFieldsForQueryName[] =
-    "Autofill Enforce Min Required Fields For Query";
-const char kAutofillEnforceMinRequiredFieldsForQueryDescription[] =
-    "When enabled, autofill will generally require a form to have at least 3 "
-    "fields before querying the autofill server for field-type predictions.";
-
-const char kAutofillEnforceMinRequiredFieldsForUploadName[] =
-    "Autofill Enforce Min Required Fields For Upload";
-const char kAutofillEnforceMinRequiredFieldsForUploadDescription[] =
-    "When enabled, autofill will generally require a form to have at least 3 "
-    "fillable fields before uploading field-type votes for that form.";
-
 const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[] =
     "Restrict formless form extraction";
 const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[] =
@@ -200,6 +194,12 @@
     "When enabled, the cards in the payments settings will be split into two "
     "lists based on where they are stored.";
 
+const char kAutofillUseImprovedLabelDisambiguationName[] =
+    "Autofill Uses Improved Label Disambiguation";
+const char kAutofillUseImprovedLabelDisambiguationDescription[] =
+    "When enabled, the Autofill dropdown's suggestions' labels are displayed "
+    "using the improved disambiguation format.";
+
 const char kAutoplayPolicyName[] = "Autoplay policy";
 const char kAutoplayPolicyDescription[] =
     "Policy used when deciding if audio or video is allowed to autoplay.";
@@ -603,6 +603,12 @@
     "this is enabled do not implement TLS 1.0 through 1.2 correctly or "
     "securely. They must be fixed by vendors.";
 
+const char kEnableTLS13EarlyDataName[] = "TLS 1.3 Early Data";
+const char kEnableTLS13EarlyDataDescription[] =
+    "This option enables TLS 1.3 Early Data, allowing GET requests to be sent "
+    "during the handshake when resuming a connection to a compatible TLS 1.3 "
+    "server.";
+
 const char kEnableGenericSensorName[] = "Generic Sensor";
 const char kEnableGenericSensorDescription[] =
     "Enables motion sensor classes based on Generic Sensor API, i.e. "
@@ -1942,6 +1948,12 @@
     "features. This includes new confirmation screens and improved settings "
     "pages.";
 
+const char kUnsafeWebGPUName[] = "Unsafe WebGPU";
+const char kUnsafeWebGPUDescription[] =
+    "Enables access to the experimental WebGPU API. Warning: As GPU sanboxing "
+    "isn't implemented yet for the WebGPU API, it is possible to read GPU data "
+    "for other processes.";
+
 const char kUiPartialSwapName[] = "Partial swap";
 const char kUiPartialSwapDescription[] = "Sets partial swap behavior.";
 
@@ -2120,6 +2132,12 @@
     "Shows Autofill suggestions on top of the keyboard rather than in a "
     "dropdown.";
 
+const char kAutofillUseMobileLabelDisambiguationName[] =
+    "Autofill Uses Mobile Label Disambiguation";
+const char kAutofillUseMobileLabelDisambiguationDescription[] =
+    "When enabled, Autofill suggestions' labels are displayed using a "
+    "mobile-friendly format.";
+
 const char kBackgroundTaskComponentUpdateName[] =
     "Background Task Component Updates";
 const char kBackgroundTaskComponentUpdateDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 6866933..84c8694 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -94,9 +94,6 @@
 extern const char kAutofillEnableCompanyNameName[];
 extern const char kAutofillEnableCompanyNameDescription[];
 
-extern const char kAutofillRejectCompanyBirthyearName[];
-extern const char kAutofillRejectCompanyBirthyearDescription[];
-
 extern const char kAutofillEnableLocalCardMigrationForNonSyncUserName[];
 extern const char kAutofillEnableLocalCardMigrationForNonSyncUserDescription[];
 
@@ -126,8 +123,8 @@
 extern const char kAutofillProfileServerValidationName[];
 extern const char kAutofillProfileServerValidationDescription[];
 
-extern const char kAutofillUseImprovedLabelDisambiguationName[];
-extern const char kAutofillUseImprovedLabelDisambiguationDescription[];
+extern const char kAutofillRejectCompanyBirthyearName[];
+extern const char kAutofillRejectCompanyBirthyearDescription[];
 
 extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[];
 extern const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[];
@@ -138,6 +135,9 @@
 extern const char kAutofillSettingsSplitByCardTypeName[];
 extern const char kAutofillSettingsSplitByCardTypeDescription[];
 
+extern const char kAutofillUseImprovedLabelDisambiguationName[];
+extern const char kAutofillUseImprovedLabelDisambiguationDescription[];
+
 extern const char kAutoplayPolicyName[];
 extern const char kAutoplayPolicyDescription[];
 
@@ -382,6 +382,9 @@
 extern const char kEnforceTLS13DowngradeName[];
 extern const char kEnforceTLS13DowngradeDescription[];
 
+extern const char kEnableTLS13EarlyDataName[];
+extern const char kEnableTLS13EarlyDataDescription[];
+
 extern const char kEnableGenericSensorName[];
 extern const char kEnableGenericSensorDescription[];
 
@@ -1158,6 +1161,9 @@
 extern const char kUnifiedConsentName[];
 extern const char kUnifiedConsentDescription[];
 
+extern const char kUnsafeWebGPUName[];
+extern const char kUnsafeWebGPUDescription[];
+
 extern const char kUiPartialSwapName[];
 extern const char kUiPartialSwapDescription[];
 
@@ -1272,6 +1278,9 @@
 extern const char kAutofillAccessoryViewName[];
 extern const char kAutofillAccessoryViewDescription[];
 
+extern const char kAutofillUseMobileLabelDisambiguationName[];
+extern const char kAutofillUseMobileLabelDisambiguationDescription[];
+
 extern const char kBackgroundTaskComponentUpdateName[];
 extern const char kBackgroundTaskComponentUpdateDescription[];
 
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index 757722fb..ea80faa 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -8,6 +8,7 @@
 
 #include "base/path_service.h"
 #include "build/build_config.h"
+#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/net/profile_network_context_service.h"
@@ -328,3 +329,10 @@
       ->GetDefaultZoomLevel();
 }
 #endif  // !defined(OS_ANDROID)
+
+void Profile::Wipe() {
+  content::BrowserContext::GetBrowsingDataRemover(this)->Remove(
+      base::Time(), base::Time::Max(),
+      ChromeBrowsingDataRemoverDelegate::WIPE_PROFILE,
+      ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES);
+}
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 19f29aa4..89eb6a2 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -375,6 +375,9 @@
   double GetDefaultZoomLevelForProfile();
 #endif
 
+  // Wipes all data for this profile.
+  void Wipe();
+
  protected:
   void set_is_guest_profile(bool is_guest_profile) {
     is_guest_profile_ = is_guest_profile;
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc
index fadeb838..1496841 100644
--- a/chrome/browser/profiles/profile_android.cc
+++ b/chrome/browser/profiles/profile_android.cc
@@ -105,6 +105,10 @@
   return profile_->IsChild();
 }
 
+void ProfileAndroid::Wipe(JNIEnv* env, const JavaParamRef<jobject>& obj) {
+  profile_->Wipe();
+}
+
 // static
 ScopedJavaLocalRef<jobject> JNI_Profile_GetLastUsedProfile(JNIEnv* env) {
   return ProfileAndroid::GetLastUsedProfile(env);
diff --git a/chrome/browser/profiles/profile_android.h b/chrome/browser/profiles/profile_android.h
index 3648144..847ddea 100644
--- a/chrome/browser/profiles/profile_android.h
+++ b/chrome/browser/profiles/profile_android.h
@@ -55,6 +55,8 @@
   jboolean IsChild(JNIEnv* env,
                    const base::android::JavaParamRef<jobject>& obj);
 
+  void Wipe(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
   explicit ProfileAndroid(Profile* profile);
   ~ProfileAndroid() override;
 
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc
index 80fbfd8..6f10709e 100644
--- a/chrome/browser/profiles/profiles_state.cc
+++ b/chrome/browser/profiles/profiles_state.cc
@@ -223,10 +223,7 @@
   if (profile->IsGuestSession())
     profile = profile->GetOffTheRecordProfile();
 
-  content::BrowserContext::GetBrowsingDataRemover(profile)->Remove(
-      base::Time(), base::Time::Max(),
-      ChromeBrowsingDataRemoverDelegate::WIPE_PROFILE,
-      ChromeBrowsingDataRemoverDelegate::ALL_ORIGIN_TYPES);
+  profile->Wipe();
 }
 
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
index e451244..a712199 100644
--- a/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
+++ b/chrome/browser/sync/send_tab_to_self_sync_service_factory.cc
@@ -9,10 +9,12 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
+#include "chrome/browser/sync/device_info_sync_service_factory.h"
 #include "chrome/browser/sync/model_type_store_service_factory.h"
 #include "chrome/common/channel_info.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
+#include "components/sync/device_info/device_info_sync_service.h"
 #include "components/sync/model/model_type_store_service.h"
 
 // static
@@ -34,6 +36,7 @@
           BrowserContextDependencyManager::GetInstance()) {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
   DependsOn(HistoryServiceFactory::GetInstance());
+  DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
 }
 
 SendTabToSelfSyncServiceFactory::~SendTabToSelfSyncServiceFactory() {}
@@ -51,6 +54,11 @@
       HistoryServiceFactory::GetForProfile(profile,
                                            ServiceAccessType::EXPLICIT_ACCESS);
 
+  syncer::DeviceInfoTracker* device_info_tracker =
+      DeviceInfoSyncServiceFactory::GetForProfile(profile)
+          ->GetDeviceInfoTracker();
+
   return new send_tab_to_self::SendTabToSelfSyncService(
-      chrome::GetChannel(), std::move(store_factory), history_service);
+      chrome::GetChannel(), std::move(store_factory), history_service,
+      device_info_tracker);
 }
diff --git a/chrome/browser/ui/browser_finder.cc b/chrome/browser/ui/browser_finder.cc
index 441237597..cef348d 100644
--- a/chrome/browser/ui/browser_finder.cc
+++ b/chrome/browser/ui/browser_finder.cc
@@ -18,6 +18,14 @@
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
+#if defined(OS_WIN)
+#include <shobjidl.h>
+#include <wrl/client.h>
+#include "base/win/windows_version.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#endif
+
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client.h"
@@ -36,6 +44,51 @@
 const int kMatchCanSupportWindowFeature = 1 << 1;
 const int kMatchTabbed = 1 << 2;
 const int kMatchDisplayId = 1 << 3;
+#if defined(OS_WIN)
+const int kMatchCurrentWorkspace = 1 << 4;
+#endif
+
+#if defined(OS_WIN)
+// Returns true if the browser window is on another virtual desktop, false if
+// we can't tell, or it's on the current virtual desktop.
+// Must not be called while application is dispatching an input synchronous
+// call like SendMessage, because IsWindowOnCurrentVirtualDesktop will return
+// an error.
+bool IsOnOtherVirtualDesktop(Browser* browser) {
+  if (base::win::GetVersion() < base::win::Version::WIN10)
+    return false;
+
+  Microsoft::WRL::ComPtr<IVirtualDesktopManager> virtual_desktop_manager;
+  if (!SUCCEEDED(::CoCreateInstance(__uuidof(VirtualDesktopManager), nullptr,
+                                    CLSCTX_ALL,
+                                    IID_PPV_ARGS(&virtual_desktop_manager)))) {
+    return false;
+  }
+  BrowserWindow* window = browser->window();
+  // In tests, |window| can be null.
+  if (!window)
+    return false;
+
+  BOOL on_current_desktop;
+  aura::Window* native_win = window->GetNativeWindow();
+  if (!native_win ||
+      FAILED(virtual_desktop_manager->IsWindowOnCurrentVirtualDesktop(
+          native_win->GetHost()->GetAcceleratedWidget(),
+          &on_current_desktop)) ||
+      on_current_desktop) {
+    return false;
+  }
+
+  // IsWindowOnCurrentVirtualDesktop() is flaky for newly opened windows,
+  // which causes test flakiness. Occasionally, it incorrectly says a window
+  // is not on the current virtual desktop when it is. In this situation,
+  // it also returns GUID_NULL for the desktop id.
+  GUID workspace_guid;
+  return SUCCEEDED(virtual_desktop_manager->GetWindowDesktopId(
+             native_win->GetHost()->GetAcceleratedWidget(), &workspace_guid)) &&
+         workspace_guid != GUID_NULL;
+}
+#endif  // OS_WIN
 
 // Returns true if the specified |browser| matches the specified arguments.
 // |match_types| is a bitmask dictating what parameters to match:
@@ -93,6 +146,13 @@
   if ((match_types & kMatchTabbed) && !browser->is_type_tabbed())
     return false;
 
+#if defined(OS_WIN)
+  if ((match_types & kMatchCurrentWorkspace) &&
+      IsOnOtherVirtualDesktop(browser)) {
+    return false;
+  }
+#endif  // OS_WIN
+
   if (match_types & kMatchDisplayId) {
     return display::Screen::GetScreen()
                ->GetDisplayNearestWindow(browser->window()->GetNativeWindow())
@@ -134,6 +194,9 @@
     match_types |= kMatchOriginalProfile;
   if (display_id != display::kInvalidDisplayId)
     match_types |= kMatchDisplayId;
+#if defined(OS_WIN)
+  match_types |= kMatchCurrentWorkspace;
+#endif
   Browser* browser =
       FindBrowserMatching(browser_list_impl->begin_last_active(),
                           browser_list_impl->end_last_active(), profile,
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 1c3647e..b414d5f7 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -912,6 +912,28 @@
 }
 
 // static
+void StartupBrowserCreator::ProcessCommandLineAlreadyRunningImpl(
+    const base::CommandLine& command_line,
+    const base::FilePath& cur_dir,
+    const base::FilePath& profile_path) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  Profile* profile = profile_manager->GetProfileByPath(profile_path);
+
+  // The profile isn't loaded yet and so needs to be loaded asynchronously.
+  if (!profile) {
+    profile_manager->CreateProfileAsync(
+        profile_path,
+        base::BindRepeating(&ProcessCommandLineOnProfileCreated, command_line,
+                            cur_dir),
+        base::string16(), std::string());
+    return;
+  }
+  StartupBrowserCreator startup_browser_creator;
+  startup_browser_creator.ProcessCmdLineImpl(
+      command_line, cur_dir, /*process_startup=*/false, profile, Profiles());
+}
+
+// static
 void StartupBrowserCreator::ProcessCommandLineOnProfileCreated(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
@@ -929,20 +951,15 @@
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
     const base::FilePath& profile_path) {
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  Profile* profile = profile_manager->GetProfileByPath(profile_path);
-
-  // The profile isn't loaded yet and so needs to be loaded asynchronously.
-  if (!profile) {
-    profile_manager->CreateProfileAsync(
-        profile_path,
-        base::Bind(&ProcessCommandLineOnProfileCreated, command_line, cur_dir),
-        base::string16(), std::string());
-    return;
-  }
-  StartupBrowserCreator startup_browser_creator;
-  startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir, false,
-                                             profile, Profiles());
+  // The Windows-specific code in browser_finder.cc that determines if a window
+  // is on the current virtual desktop uses a COM interface that can't be
+  // invoked if we're processing a SendMessage call. So, we post a task to
+  // finish the command line processing.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &StartupBrowserCreator::ProcessCommandLineAlreadyRunningImpl,
+          command_line, cur_dir, profile_path));
 }
 
 // static
diff --git a/chrome/browser/ui/startup/startup_browser_creator.h b/chrome/browser/ui/startup/startup_browser_creator.h
index 187c30d..448df5d 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.h
+++ b/chrome/browser/ui/startup/startup_browser_creator.h
@@ -181,6 +181,12 @@
                               const base::FilePath& cur_dir,
                               Profile* profile);
 
+  // This is run as a task by ProcessCommandLineAlreadyRunning.
+  static void ProcessCommandLineAlreadyRunningImpl(
+      const base::CommandLine& command_line,
+      const base::FilePath& cur_dir,
+      const base::FilePath& profile_path);
+
   // Callback after a profile has been created.
   static void ProcessCommandLineOnProfileCreated(
       const base::CommandLine& command_line,
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
index b588ee3..2cdd70e 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -107,15 +107,14 @@
     GUID workspace_guid;
     HRESULT hr = virtual_desktop_manager_->GetWindowDesktopId(GetHWND(),
                                                               &workspace_guid);
-    if (SUCCEEDED(hr)) {
-      LPOLESTR workspace_widestr;
-      StringFromCLSID(workspace_guid, &workspace_widestr);
-      workspace_id = base::WideToUTF8(workspace_widestr);
-      workspace_ = workspace_id;
-      CoTaskMemFree(workspace_widestr);
-    } else {
+    if (FAILED(hr) || workspace_guid == GUID_NULL)
       return workspace_.value_or("");
-    }
+
+    LPOLESTR workspace_widestr;
+    StringFromCLSID(workspace_guid, &workspace_widestr);
+    workspace_id = base::WideToUTF8(workspace_widestr);
+    workspace_ = workspace_id;
+    CoTaskMemFree(workspace_widestr);
   }
   return workspace_id;
 }
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
index ef5b159..2cc05ec 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -211,6 +211,10 @@
   return details_->should_do_learning;
 }
 
+void RemoteTextInputClient::SetCompositionFromExistingText(
+    const gfx::Range& range,
+    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+
 ui::EventDispatchDetails RemoteTextInputClient::DispatchKeyEventPostIME(
     ui::KeyEvent* event,
     DispatchKeyEventPostIMECallback callback) {
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
index 75127adc..7d851e0a 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -66,6 +66,9 @@
   void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
+  void SetCompositionFromExistingText(
+      const gfx::Range& range,
+      const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
 
   // ui::internal::InputMethodDelegate:
   ui::EventDispatchDetails DispatchKeyEventPostIME(
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index f4ec7e4..4133653 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -806,7 +806,6 @@
 
 #if defined(GOOGLE_CHROME_BUILD)
 void ProfileChooserView::AddManageGoogleAccountButton() {
-  AddMenuGroup(false /* add_separator */);
   manage_google_account_button_ = CreateAndAddButton(
       GetGoogleIconForUserMenu(GetDefaultIconSize()),
       l10n_util::GetStringUTF16(IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT));
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index 62ffd437d..eb46e75 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -381,7 +381,15 @@
         bottom_margin = kLarge;
       }
 
-      child_spacing = group.different_item_types ? kLarge : kNone;
+      if (!group.different_item_types) {
+        child_spacing = kNone;
+      } else if (group.items.size() == 2 &&
+                 group.first_item_type == MenuItems::kTitleCard &&
+                 group.last_item_type == MenuItems::kButton) {
+        child_spacing = kNone;
+      } else {
+        child_spacing = kLarge;
+      }
 
       sub_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
           views::BoxLayout::kVertical,
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index fe468bf1..1e59697 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -6,6 +6,9 @@
   public_configs = [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
+group("web_app_test_group") {
+}
+
 source_set("web_applications") {
   sources = [
     "abstract_web_app_database.h",
@@ -77,7 +80,7 @@
   ]
 
   deps = [
-    ":web_app_group",
+    ":web_app_test_group",
     ":web_applications",
     "//chrome/browser/web_applications/components",
     "//chrome/test:test_support",
@@ -98,7 +101,7 @@
   ]
 
   deps = [
-    ":web_app_group",
+    ":web_app_test_group",
     ":web_applications",
     ":web_applications_test_support",
     "//base/test:test_support",
@@ -142,7 +145,7 @@
   testonly = true
 
   deps = [
-    ":web_app_group",
+    ":web_app_test_group",
     ":web_applications_unit_tests",
     "//chrome/browser/web_applications/bookmark_apps:unit_tests",
     "//chrome/browser/web_applications/components:unit_tests",
@@ -154,7 +157,7 @@
   testonly = true
 
   deps = [
-    ":web_app_group",
+    ":web_app_test_group",
     "//chrome/browser/web_applications/bookmark_apps:browser_tests",
     "//chrome/browser/web_applications/components:browser_tests",
     "//chrome/browser/web_applications/extensions:browser_tests",
diff --git a/chrome/browser/web_applications/bookmark_apps/BUILD.gn b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
index 10403c2..24b8a82 100644
--- a/chrome/browser/web_applications/bookmark_apps/BUILD.gn
+++ b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
@@ -38,7 +38,7 @@
     "//base",
     "//chrome/browser",
     "//chrome/browser/web_applications",
-    "//chrome/browser/web_applications:web_app_group",
+    "//chrome/browser/web_applications:web_app_test_group",
     "//chrome/browser/web_applications:web_applications_on_extensions",
     "//chrome/browser/web_applications/components",
     "//components/keyed_service/content",
@@ -61,7 +61,7 @@
     "//base",
     "//chrome/browser",
     "//chrome/browser/web_applications",
-    "//chrome/browser/web_applications:web_app_group",
+    "//chrome/browser/web_applications:web_app_test_group",
     "//chrome/browser/web_applications:web_applications_on_extensions",
     "//chrome/browser/web_applications:web_applications_test_support",
     "//chrome/browser/web_applications/components",
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
index e53b49a..f848710 100644
--- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
@@ -36,20 +36,20 @@
 
 namespace {
 
-const char kWindowedUrl[] = "https://windowed.example/";
-const char kTabbedUrl[] = "https://tabbed.example/";
-const char kNoContainerUrl[] = "https://no-container.example/";
+const GURL kWindowedUrl("https://windowed.example/");
+const GURL kTabbedUrl("https://tabbed.example/");
+const GURL kNoContainerUrl("https://no-container.example/");
 
 base::Value GetWindowedItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kWindowedUrl));
+  item.SetKey(kUrlKey, base::Value(kWindowedUrl.spec()));
   item.SetKey(kDefaultLaunchContainerKey,
               base::Value(kDefaultLaunchContainerWindowValue));
   return item;
 }
 
 InstallOptions GetWindowedInstallOptions() {
-  InstallOptions options(GURL(kWindowedUrl), LaunchContainer::kWindow,
+  InstallOptions options(kWindowedUrl, LaunchContainer::kWindow,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = false;
@@ -62,14 +62,14 @@
 
 base::Value GetTabbedItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kTabbedUrl));
+  item.SetKey(kUrlKey, base::Value(kTabbedUrl.spec()));
   item.SetKey(kDefaultLaunchContainerKey,
               base::Value(kDefaultLaunchContainerTabValue));
   return item;
 }
 
 InstallOptions GetTabbedInstallOptions() {
-  InstallOptions options(GURL(kTabbedUrl), LaunchContainer::kTab,
+  InstallOptions options(kTabbedUrl, LaunchContainer::kTab,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = false;
@@ -82,12 +82,12 @@
 
 base::Value GetNoContainerItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kNoContainerUrl));
+  item.SetKey(kUrlKey, base::Value(kNoContainerUrl.spec()));
   return item;
 }
 
 InstallOptions GetNoContainerInstallOptions() {
-  InstallOptions options(GURL(kNoContainerUrl), LaunchContainer::kTab,
+  InstallOptions options(kNoContainerUrl, LaunchContainer::kTab,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = false;
@@ -100,12 +100,12 @@
 
 base::Value GetCreateDesktopShorcutDefaultItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kNoContainerUrl));
+  item.SetKey(kUrlKey, base::Value(kNoContainerUrl.spec()));
   return item;
 }
 
 InstallOptions GetCreateDesktopShorcutDefaultInstallOptions() {
-  InstallOptions options(GURL(kNoContainerUrl), LaunchContainer::kTab,
+  InstallOptions options(kNoContainerUrl, LaunchContainer::kTab,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = false;
@@ -118,13 +118,13 @@
 
 base::Value GetCreateDesktopShorcutFalseItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kNoContainerUrl));
+  item.SetKey(kUrlKey, base::Value(kNoContainerUrl.spec()));
   item.SetKey(kCreateDesktopShorcutKey, base::Value(false));
   return item;
 }
 
 InstallOptions GetCreateDesktopShorcutFalseInstallOptions() {
-  InstallOptions options(GURL(kNoContainerUrl), LaunchContainer::kTab,
+  InstallOptions options(kNoContainerUrl, LaunchContainer::kTab,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = false;
@@ -137,13 +137,13 @@
 
 base::Value GetCreateDesktopShorcutTrueItem() {
   base::Value item(base::Value::Type::DICTIONARY);
-  item.SetKey(kUrlKey, base::Value(kNoContainerUrl));
+  item.SetKey(kUrlKey, base::Value(kNoContainerUrl.spec()));
   item.SetKey(kCreateDesktopShorcutKey, base::Value(true));
   return item;
 }
 
 InstallOptions GetCreateDesktopShorcutTrueInstallOptions() {
-  InstallOptions options(GURL(kNoContainerUrl), LaunchContainer::kTab,
+  InstallOptions options(kNoContainerUrl, LaunchContainer::kTab,
                          InstallSource::kExternalPolicy);
   options.add_to_applications_menu = true;
   options.add_to_desktop = true;
@@ -336,12 +336,9 @@
 TEST_F(WebAppPolicyManagerTest, UninstallAppInstalledInPreviousSession) {
   // Simulate two policy apps and a regular app that were installed in the
   // previous session.
-  SimulatePreviouslyInstalledApp(GURL(kWindowedUrl),
-                                 InstallSource::kExternalPolicy);
-  SimulatePreviouslyInstalledApp(GURL(kTabbedUrl),
-                                 InstallSource::kExternalPolicy);
-  SimulatePreviouslyInstalledApp(GURL(kNoContainerUrl),
-                                 InstallSource::kInternal);
+  SimulatePreviouslyInstalledApp(kWindowedUrl, InstallSource::kExternalPolicy);
+  SimulatePreviouslyInstalledApp(kTabbedUrl, InstallSource::kExternalPolicy);
+  SimulatePreviouslyInstalledApp(kNoContainerUrl, InstallSource::kInternal);
 
   // Push a policy with only one of the apps.
   base::Value first_list(base::Value::Type::LIST);
@@ -359,7 +356,7 @@
             expected_install_options_list);
 
   // We should try to uninstall the app that is no longer in the policy.
-  EXPECT_EQ(std::vector<GURL>({GURL(kTabbedUrl)}),
+  EXPECT_EQ(std::vector<GURL>({kTabbedUrl}),
             pending_app_manager()->uninstall_requests());
 }
 
@@ -398,7 +395,7 @@
 
   EXPECT_EQ(install_requests, expected_install_options_list);
 
-  EXPECT_EQ(std::vector<GURL>({GURL(kTabbedUrl)}),
+  EXPECT_EQ(std::vector<GURL>({kTabbedUrl}),
             pending_app_manager()->uninstall_requests());
 }
 
@@ -417,7 +414,7 @@
   const auto& install_options_list = pending_app_manager()->install_requests();
   EXPECT_EQ(expected_options_list, install_options_list);
 
-  policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl));
+  policy_manager()->ReinstallPlaceholderAppIfNecessary(kWindowedUrl);
   base::RunLoop().RunUntilIdle();
 
   auto reinstall_options = GetWindowedInstallOptions();
@@ -444,7 +441,7 @@
   EXPECT_EQ(expected_options_list, install_options_list);
 
   // Try to reinstall for app not installed by policy.
-  policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kTabbedUrl));
+  policy_manager()->ReinstallPlaceholderAppIfNecessary(kTabbedUrl);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(expected_options_list, install_options_list);
@@ -474,13 +471,13 @@
 
   const auto& install_options_list = pending_app_manager()->install_requests();
   EXPECT_EQ(expected_options_list, install_options_list);
-  EXPECT_EQ(std::vector<GURL>({GURL(kWindowedUrl)}),
+  EXPECT_EQ(std::vector<GURL>({kWindowedUrl}),
             pending_app_manager()->uninstall_requests());
 
   // There should be exactly 1 app remaining.
   EXPECT_EQ(1u, pending_app_manager()->installed_apps().size());
   EXPECT_EQ(InstallSource::kExternalPolicy,
-            pending_app_manager()->installed_apps().at(GURL(kTabbedUrl)));
+            pending_app_manager()->installed_apps().at(kTabbedUrl));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_unittest.cc b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_unittest.cc
index 9378ed8..69e6055 100644
--- a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_unittest.cc
@@ -34,12 +34,12 @@
 
 namespace {
 
-const char kAppUrl1[] = "chrome://system-app1";
-const char kAppUrl2[] = "chrome://system-app2";
-const char kAppUrl3[] = "chrome://system-app3";
+const GURL kAppUrl1("chrome://system-app1");
+const GURL kAppUrl2("chrome://system-app2");
+const GURL kAppUrl3("chrome://system-app3");
 
 InstallOptions GetWindowedInstallOptions() {
-  InstallOptions options(GURL(kAppUrl1), LaunchContainer::kWindow,
+  InstallOptions options(kAppUrl1, LaunchContainer::kWindow,
                          InstallSource::kSystemInstalled);
   options.add_to_applications_menu = false;
   options.add_to_desktop = false;
@@ -114,11 +114,10 @@
   base::test::ScopedFeatureList disable_feature_list;
   disable_feature_list.InitWithFeatures({}, {features::kSystemWebApps});
 
-  SimulatePreviouslyInstalledApp(GURL(kAppUrl1),
-                                 InstallSource::kSystemInstalled);
+  SimulatePreviouslyInstalledApp(kAppUrl1, InstallSource::kSystemInstalled);
 
   base::flat_map<SystemAppType, GURL> system_apps;
-  system_apps[SystemAppType::SETTINGS] = GURL(kAppUrl1);
+  system_apps[SystemAppType::SETTINGS] = kAppUrl1;
 
   system_web_app_manager()->SetSystemApps(std::move(system_apps));
   system_web_app_manager()->Start();
@@ -129,15 +128,15 @@
 
   // We should try to uninstall the app that is no longer in the System App
   // list.
-  EXPECT_EQ(std::vector<GURL>({GURL(kAppUrl1)}),
+  EXPECT_EQ(std::vector<GURL>({kAppUrl1}),
             pending_app_manager()->uninstall_requests());
 }
 
 // Test that System Apps do install with the feature enabled.
 TEST_F(SystemWebAppManagerTest, Enabled) {
   base::flat_map<SystemAppType, GURL> system_apps;
-  system_apps[SystemAppType::SETTINGS] = GURL(kAppUrl1);
-  system_apps[SystemAppType::DISCOVER] = GURL(kAppUrl2);
+  system_apps[SystemAppType::SETTINGS] = kAppUrl1;
+  system_apps[SystemAppType::DISCOVER] = kAppUrl2;
 
   system_web_app_manager()->SetSystemApps(std::move(system_apps));
   system_web_app_manager()->Start();
@@ -151,13 +150,11 @@
 TEST_F(SystemWebAppManagerTest, UninstallAppInstalledInPreviousSession) {
   // Simulate System Apps and a regular app that were installed in the
   // previous session.
-  SimulatePreviouslyInstalledApp(GURL(kAppUrl1),
-                                 InstallSource::kSystemInstalled);
-  SimulatePreviouslyInstalledApp(GURL(kAppUrl2),
-                                 InstallSource::kSystemInstalled);
-  SimulatePreviouslyInstalledApp(GURL(kAppUrl3), InstallSource::kInternal);
+  SimulatePreviouslyInstalledApp(kAppUrl1, InstallSource::kSystemInstalled);
+  SimulatePreviouslyInstalledApp(kAppUrl2, InstallSource::kSystemInstalled);
+  SimulatePreviouslyInstalledApp(kAppUrl3, InstallSource::kInternal);
   base::flat_map<SystemAppType, GURL> system_apps;
-  system_apps[SystemAppType::SETTINGS] = GURL(kAppUrl1);
+  system_apps[SystemAppType::SETTINGS] = kAppUrl1;
 
   system_web_app_manager()->SetSystemApps(std::move(system_apps));
   system_web_app_manager()->Start();
@@ -172,7 +169,7 @@
 
   // We should try to uninstall the app that is no longer in the System App
   // list.
-  EXPECT_EQ(std::vector<GURL>({GURL(kAppUrl2)}),
+  EXPECT_EQ(std::vector<GURL>({kAppUrl2}),
             pending_app_manager()->uninstall_requests());
 }
 
@@ -181,7 +178,7 @@
       SystemWebAppManager::UpdatePolicy::kAlwaysUpdate);
 
   base::flat_map<SystemAppType, GURL> system_apps;
-  system_apps[SystemAppType::SETTINGS] = GURL(kAppUrl1);
+  system_apps[SystemAppType::SETTINGS] = kAppUrl1;
   system_web_app_manager()->SetSystemApps(system_apps);
 
   system_web_app_manager()->set_current_version(base::Version("1.0.0.0"));
@@ -192,7 +189,7 @@
 
   // Create another app. The version hasn't changed but the app should still
   // install.
-  system_apps[SystemAppType::DISCOVER] = GURL(kAppUrl2);
+  system_apps[SystemAppType::DISCOVER] = kAppUrl2;
   system_web_app_manager()->SetSystemApps(system_apps);
   system_web_app_manager()->Start();
 
@@ -222,7 +219,7 @@
       SystemWebAppManager::UpdatePolicy::kOnVersionChange);
 
   base::flat_map<SystemAppType, GURL> system_apps;
-  system_apps[SystemAppType::SETTINGS] = GURL(kAppUrl1);
+  system_apps[SystemAppType::SETTINGS] = kAppUrl1;
   system_web_app_manager()->SetSystemApps(system_apps);
 
   system_web_app_manager()->set_current_version(base::Version("1.0.0.0"));
@@ -233,7 +230,7 @@
 
   // Create another app. The version hasn't changed so the install won't
   // process.
-  system_apps[SystemAppType::DISCOVER] = GURL(kAppUrl2);
+  system_apps[SystemAppType::DISCOVER] = kAppUrl2;
   system_web_app_manager()->SetSystemApps(system_apps);
   system_web_app_manager()->Start();
 
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn
index 8d13956..6842544 100644
--- a/chrome/browser/web_applications/components/BUILD.gn
+++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -122,7 +122,7 @@
     ":test_support",
     "//base/test:test_support",
     "//chrome/app/theme:theme_resources",
-    "//chrome/browser/web_applications:web_app_group",
+    "//chrome/browser/web_applications:web_app_test_group",
     "//chrome/test:test_support",
     "//content/public/browser",
     "//skia",
diff --git a/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc b/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc
index d83b33d..69ac4a3 100644
--- a/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_data_retriever_unittest.cc
@@ -32,10 +32,10 @@
 
 namespace {
 
-const char kFooUrl[] = "https://foo.example";
-const char kFooUrl2[] = "https://foo.example/bar";
+const GURL kFooUrl("https://foo.example");
+const GURL kFooUrl2("https://foo.example/bar");
 const char kFooTitle[] = "Foo Title";
-const char kBarUrl[] = "https://bar.example";
+const GURL kBarUrl("https://bar.example");
 
 }  // namespace
 
@@ -147,7 +147,7 @@
 }
 
 TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_AppUrlAbsent) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   WebApplicationInfo original_web_app_info;
   original_web_app_info.app_url = GURL();
@@ -165,14 +165,14 @@
 
   // If the WebApplicationInfo has no URL, we fallback to the last committed
   // URL.
-  EXPECT_EQ(GURL(kFooUrl), web_app_info()->app_url);
+  EXPECT_EQ(kFooUrl, web_app_info()->app_url);
 }
 
 TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_AppUrlPresent) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   WebApplicationInfo original_web_app_info;
-  original_web_app_info.app_url = GURL(kBarUrl);
+  original_web_app_info.app_url = kBarUrl;
 
   FakeChromeRenderFrame fake_chrome_render_frame(original_web_app_info);
   SetFakeChromeRenderFrame(&fake_chrome_render_frame);
@@ -189,7 +189,7 @@
 }
 
 TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_TitleAbsentFromRenderer) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   const auto web_contents_title = base::UTF8ToUTF16(kFooTitle);
   web_contents_tester()->SetTitle(web_contents_title);
@@ -215,7 +215,7 @@
 
 TEST_F(WebAppDataRetrieverTest,
        GetWebApplicationInfo_TitleAbsentFromWebContents) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   web_contents_tester()->SetTitle(base::UTF8ToUTF16(""));
 
@@ -240,7 +240,7 @@
 }
 
 TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_WebContentsDestroyed) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   FakeChromeRenderFrame fake_chrome_render_frame{WebApplicationInfo()};
   SetFakeChromeRenderFrame(&fake_chrome_render_frame);
@@ -258,7 +258,7 @@
 }
 
 TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_FrameNavigated) {
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl));
+  web_contents_tester()->NavigateAndCommit(kFooUrl);
 
   FakeChromeRenderFrame fake_chrome_render_frame{WebApplicationInfo()};
   SetFakeChromeRenderFrame(&fake_chrome_render_frame);
@@ -269,7 +269,7 @@
       web_contents(),
       base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
-  web_contents_tester()->NavigateAndCommit(GURL(kFooUrl2));
+  web_contents_tester()->NavigateAndCommit(kFooUrl2);
   run_loop.Run();
 
   EXPECT_EQ(nullptr, web_app_info());
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
index 48aa38d2..44ea633 100644
--- a/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
@@ -13,9 +13,9 @@
 
 namespace {
 
-const char kAppIconURL1[] = "http://foo.com/1.png";
-const char kAppIconURL2[] = "http://foo.com/2.png";
-const char kAppIconURL3[] = "http://foo.com/3.png";
+const GURL kAppIconURL1("http://foo.com/1.png");
+const GURL kAppIconURL2("http://foo.com/2.png");
+const GURL kAppIconURL3("http://foo.com/3.png");
 
 const int kIconSizeSmallBetweenMediumAndLarge = 63;
 const int kIconSizeLargeBetweenMediumAndLarge = 96;
@@ -157,8 +157,7 @@
   std::vector<BitmapAndSource> downloaded;
 
   // Add an icon with a URL and bitmap. 'Download' it.
-  downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL1), icon_size, SK_ColorRED));
+  downloaded.push_back(CreateSquareIcon(kAppIconURL1, icon_size, SK_ColorRED));
 
   // Now run the resizing/generation and validation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
@@ -221,7 +220,7 @@
 TEST(WebAppIconGeneratorTest, LinkedAppIconsAreNotChanged) {
   std::vector<BitmapAndSource> icons;
 
-  const GURL url = GURL(kAppIconURL3);
+  const GURL url = kAppIconURL3;
   const SkColor color = SK_ColorBLACK;
 
   icons.push_back(CreateSquareIcon(url, icon_size::k48, color));
@@ -250,12 +249,11 @@
   const SkColor color = SK_ColorRED;
 
   // Add three icons with a URL and bitmap. 'Download' each of them.
-  downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL1), icon_size::k32, color));
+  downloaded.push_back(CreateSquareIcon(kAppIconURL1, icon_size::k32, color));
   downloaded.push_back(CreateSquareIcon(
-      GURL(kAppIconURL2), kIconSizeSmallBetweenMediumAndLarge, color));
+      kAppIconURL2, kIconSizeSmallBetweenMediumAndLarge, color));
   downloaded.push_back(CreateSquareIcon(
-      GURL(kAppIconURL3), kIconSizeLargeBetweenMediumAndLarge, color));
+      kAppIconURL3, kIconSizeLargeBetweenMediumAndLarge, color));
 
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
@@ -273,9 +271,9 @@
   // Add three icons with a URL and bitmap. 'Download' two of them and pretend
   // the third failed to download.
   downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL1), icon_size::k32, SK_ColorRED));
+      CreateSquareIcon(kAppIconURL1, icon_size::k32, SK_ColorRED));
   downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL3), icon_size::k512, SK_ColorBLACK));
+      CreateSquareIcon(kAppIconURL3, icon_size::k512, SK_ColorBLACK));
 
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
@@ -307,9 +305,9 @@
 
   // Pretend the huge icon wasn't downloaded but two smaller ones were.
   downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL1), icon_size::k16, SK_ColorRED));
+      CreateSquareIcon(kAppIconURL1, icon_size::k16, SK_ColorRED));
   downloaded.push_back(
-      CreateSquareIcon(GURL(kAppIconURL2), icon_size::k48, SK_ColorBLUE));
+      CreateSquareIcon(kAppIconURL2, icon_size::k48, SK_ColorBLUE));
 
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
@@ -324,7 +322,7 @@
   // Verify specifically that the LARGE icons was resized from the medium icon.
   const auto it = size_map.find(icon_size::k128);
   EXPECT_NE(size_map.end(), it);
-  EXPECT_EQ(GURL(kAppIconURL2), it->second.source_url);
+  EXPECT_EQ(kAppIconURL2, it->second.source_url);
 }
 
 TEST(WebAppIconGeneratorTest, IconsResizedWhenOnlyATinyOneIsProvided) {
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
index 8850575..596fcfa 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -12,26 +12,26 @@
 namespace web_app {
 
 namespace {
-const char kAppIcon1[] = "fav1.png";
-const char kAppIcon2[] = "fav2.png";
-const char kAppIcon3[] = "fav3.png";
+const GURL kAppIcon1("fav1.png");
+const GURL kAppIcon2("fav2.png");
+const GURL kAppIcon3("fav3.png");
 const char kAppShortName[] = "Test short name";
 const char kAppTitle[] = "Test title";
-const char kAppUrl[] = "http://www.chromium.org/index.html";
-const char kAlternativeAppUrl[] = "http://www.notchromium.org";
+const GURL kAppUrl("http://www.chromium.org/index.html");
+const GURL kAlternativeAppUrl("http://www.notchromium.org");
 const char kAlternativeAppTitle[] = "Different test title";
 }  // namespace
 
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest) {
   WebApplicationInfo web_app_info;
   web_app_info.title = base::UTF8ToUTF16(kAlternativeAppTitle);
-  web_app_info.app_url = GURL(kAlternativeAppUrl);
+  web_app_info.app_url = kAlternativeAppUrl;
   WebApplicationInfo::IconInfo info;
-  info.url = GURL(kAppIcon1);
+  info.url = kAppIcon1;
   web_app_info.icons.push_back(info);
 
   blink::Manifest manifest;
-  manifest.start_url = GURL(kAppUrl);
+  manifest.start_url = kAppUrl;
   manifest.short_name =
       base::NullableString16(base::UTF8ToUTF16(kAppShortName), false);
 
@@ -48,23 +48,23 @@
   UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                ForInstallableSite::kNo);
   EXPECT_EQ(base::UTF8ToUTF16(kAppShortName), web_app_info.title);
-  EXPECT_EQ(GURL(kAppUrl), web_app_info.app_url);
+  EXPECT_EQ(kAppUrl, web_app_info.app_url);
 
   // The icon info from |web_app_info| should be left as is, since the manifest
   // doesn't have any icon information.
   EXPECT_EQ(1u, web_app_info.icons.size());
-  EXPECT_EQ(GURL(kAppIcon1), web_app_info.icons[0].url);
+  EXPECT_EQ(kAppIcon1, web_app_info.icons[0].url);
 
   // Test that |manifest.name| takes priority over |manifest.short_name|, and
   // that icons provided by the manifest replace icons in |web_app_info|.
   manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false);
 
   blink::Manifest::ImageResource icon;
-  icon.src = GURL(kAppIcon2);
+  icon.src = kAppIcon2;
   icon.purpose = {blink::Manifest::ImageResource::Purpose::ANY,
                   blink::Manifest::ImageResource::Purpose::BADGE};
   manifest.icons.push_back(icon);
-  icon.src = GURL(kAppIcon3);
+  icon.src = kAppIcon3;
   manifest.icons.push_back(icon);
   // Add an icon without purpose ANY (expect to be ignored).
   icon.purpose = {blink::Manifest::ImageResource::Purpose::BADGE};
@@ -75,8 +75,8 @@
   EXPECT_EQ(base::UTF8ToUTF16(kAppTitle), web_app_info.title);
 
   EXPECT_EQ(2u, web_app_info.icons.size());
-  EXPECT_EQ(GURL(kAppIcon2), web_app_info.icons[0].url);
-  EXPECT_EQ(GURL(kAppIcon3), web_app_info.icons[1].url);
+  EXPECT_EQ(kAppIcon2, web_app_info.icons[0].url);
+  EXPECT_EQ(kAppIcon3, web_app_info.icons[1].url);
 
   // Check file handlers were updated
   EXPECT_TRUE(web_app_info.file_handler.has_value());
@@ -91,8 +91,8 @@
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifestInstallableSite) {
   {
     blink::Manifest manifest;
-    manifest.start_url = GURL(kAppUrl);
-    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
+    manifest.start_url = kAppUrl;
+    manifest.scope = kAppUrl.GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kUnknown);
@@ -101,8 +101,8 @@
 
   {
     blink::Manifest manifest;
-    manifest.start_url = GURL(kAppUrl);
-    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
+    manifest.start_url = kAppUrl;
+    manifest.scope = kAppUrl.GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kNo);
@@ -111,8 +111,8 @@
 
   {
     blink::Manifest manifest;
-    manifest.start_url = GURL(kAppUrl);
-    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
+    manifest.start_url = kAppUrl;
+    manifest.scope = kAppUrl.GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kYes);
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn
index c47b54c..b523871 100644
--- a/chrome/browser/web_applications/extensions/BUILD.gn
+++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -58,7 +58,7 @@
   deps = [
     ":extensions",
     "//chrome/browser",
-    "//chrome/browser/web_applications:web_app_group",
+    "//chrome/browser/web_applications:web_app_test_group",
     "//chrome/browser/web_applications:web_applications_on_extensions",
     "//chrome/browser/web_applications:web_applications_test_support",
     "//chrome/browser/web_applications/bookmark_apps",
@@ -90,7 +90,7 @@
     "//base/test:test_support",
     "//chrome/browser",
     "//chrome/browser/ui",
-    "//chrome/browser/web_applications:web_app_group",
+    "//chrome/browser/web_applications:web_app_test_group",
     "//chrome/browser/web_applications:web_applications_on_extensions",
     "//chrome/browser/web_applications/components",
     "//chrome/test:test_support",
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc
index e2f64ef8..5d5a439 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc
@@ -32,7 +32,7 @@
 
 namespace {
 
-const char kWebAppUrl[] = "https://foo.example";
+const GURL kWebAppUrl("https://foo.example");
 const char kWebAppTitle[] = "Foo Title";
 
 }  // namespace
@@ -98,7 +98,7 @@
   BookmarkAppInstallFinalizer installer(profile());
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
   info->title = base::ASCIIToUTF16(kWebAppTitle);
 
   base::RunLoop run_loop;
@@ -134,7 +134,7 @@
       }));
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
   info->title = base::ASCIIToUTF16(kWebAppTitle);
 
   base::RunLoop run_loop;
@@ -214,7 +214,7 @@
   BookmarkAppInstallFinalizer installer(profile());
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
   info->title = base::ASCIIToUTF16(kWebAppTitle);
 
   web_app::InstallFinalizer::FinalizeOptions options;
@@ -241,7 +241,7 @@
   BookmarkAppInstallFinalizer installer(profile());
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
 
   web_app::InstallFinalizer::FinalizeOptions options;
   options.no_network_install = true;
@@ -268,7 +268,7 @@
   BookmarkAppInstallFinalizer installer(profile());
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
   // The info says extensions::LAUNCH_TYPE_WINDOW needed.
   info->open_as_window = true;
 
@@ -301,7 +301,7 @@
   BookmarkAppInstallFinalizer installer(profile());
 
   auto info = std::make_unique<WebApplicationInfo>();
-  info->app_url = GURL(kWebAppUrl);
+  info->app_url = kWebAppUrl;
   info->title = base::ASCIIToUTF16("Title1");
   info->description = base::ASCIIToUTF16("Description1");
 
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
index 9ee2238..669a993d 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
@@ -50,7 +50,7 @@
 namespace {
 
 const char kWebAppTitle[] = "Foo Title";
-const char kWebAppUrl[] = "https://foo.example";
+const GURL kWebAppUrl("https://foo.example");
 
 // TODO(ortuno): Move this to ExtensionIdsMap or replace with a method
 // in ExtensionIdsMap once there is one.
@@ -134,8 +134,6 @@
   }
 
  protected:
-  const GURL& app_url() const { return app_url_; }
-
   TestBookmarkAppHelper& test_helper() {
     DCHECK(test_helper_);
     return *test_helper_;
@@ -164,9 +162,9 @@
             }));
 
     install_manager->SetDataRetrieverFactoryForTesting(
-        base::BindLambdaForTesting([this]() {
+        base::BindLambdaForTesting([]() {
           auto info = std::make_unique<WebApplicationInfo>();
-          info->app_url = app_url_;
+          info->app_url = kWebAppUrl;
           info->title = base::UTF8ToUTF16(kWebAppTitle);
           auto data_retriever = std::make_unique<web_app::TestDataRetriever>();
           data_retriever->SetRendererWebApplicationInfo(std::move(info));
@@ -178,7 +176,6 @@
 
   std::unique_ptr<web_app::TestInstallFinalizer> install_finalizer_;
   TestBookmarkAppHelper* test_helper_ = nullptr;
-  GURL app_url_{kWebAppUrl};
 
   DISALLOW_COPY_AND_ASSIGN(BookmarkAppInstallationTaskTest);
 };
@@ -187,7 +184,7 @@
        WebAppOrShortcutFromContents_InstallationSucceeds) {
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(),
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kInternal));
 
   bool callback_called = false;
@@ -197,12 +194,12 @@
           [&](BookmarkAppInstallationTask::Result result) {
             base::Optional<std::string> id =
                 web_app::ExtensionIdsMap(profile()->GetPrefs())
-                    .LookupExtensionId(app_url());
+                    .LookupExtensionId(kWebAppUrl);
 
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, result.code);
             EXPECT_TRUE(result.app_id.has_value());
 
-            EXPECT_FALSE(IsPlaceholderApp(profile(), app_url()));
+            EXPECT_FALSE(IsPlaceholderApp(profile(), kWebAppUrl));
 
             EXPECT_EQ(result.app_id.value(), id.value());
 
@@ -230,7 +227,7 @@
        WebAppOrShortcutFromContents_InstallationFails) {
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(),
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kWindow,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kWindow,
                               web_app::InstallSource::kInternal));
 
   bool callback_called = false;
@@ -239,7 +236,7 @@
                     [&](BookmarkAppInstallationTask::Result result) {
                       base::Optional<std::string> id =
                           web_app::ExtensionIdsMap(profile()->GetPrefs())
-                              .LookupExtensionId(app_url());
+                              .LookupExtensionId(kWebAppUrl);
 
                       EXPECT_NE(web_app::InstallResultCode::kSuccess,
                                 result.code);
@@ -262,7 +259,7 @@
 
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_NoDesktopShortcut) {
-  web_app::InstallOptions install_options(app_url(),
+  web_app::InstallOptions install_options(kWebAppUrl,
                                           web_app::LaunchContainer::kWindow,
                                           web_app::InstallSource::kInternal);
   install_options.add_to_desktop = false;
@@ -291,7 +288,7 @@
 
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_NoQuickLaunchBarShortcut) {
-  web_app::InstallOptions install_options(app_url(),
+  web_app::InstallOptions install_options(kWebAppUrl,
                                           web_app::LaunchContainer::kWindow,
                                           web_app::InstallSource::kInternal);
   install_options.add_to_quick_launch_bar = false;
@@ -322,7 +319,7 @@
 TEST_F(
     BookmarkAppInstallationTaskTest,
     WebAppOrShortcutFromContents_NoDesktopShortcutAndNoQuickLaunchBarShortcut) {
-  web_app::InstallOptions install_options(app_url(),
+  web_app::InstallOptions install_options(kWebAppUrl,
                                           web_app::LaunchContainer::kWindow,
                                           web_app::InstallSource::kInternal);
   install_options.add_to_desktop = false;
@@ -354,7 +351,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_ForcedContainerWindow) {
   auto install_options =
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kWindow,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kWindow,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(), std::move(install_options));
@@ -381,7 +378,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_ForcedContainerTab) {
   auto install_options =
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kTab,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kTab,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(), std::move(install_options));
@@ -408,7 +405,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_DefaultApp) {
   auto install_options =
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(), std::move(install_options));
@@ -434,7 +431,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_AppFromPolicy) {
   auto install_options =
-      web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
+      web_app::InstallOptions(kWebAppUrl, web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kExternalPolicy);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(), std::move(install_options));
@@ -458,7 +455,7 @@
 }
 
 TEST_F(BookmarkAppInstallationTaskTest, InstallPlaceholder) {
-  web_app::InstallOptions options(app_url(), web_app::LaunchContainer::kWindow,
+  web_app::InstallOptions options(kWebAppUrl, web_app::LaunchContainer::kWindow,
                                   web_app::InstallSource::kExternalPolicy);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
       profile(), install_finalizer(), std::move(options));
@@ -469,15 +466,15 @@
         EXPECT_EQ(web_app::InstallResultCode::kSuccess, result.code);
         EXPECT_TRUE(result.app_id.has_value());
 
-        EXPECT_TRUE(IsPlaceholderApp(profile(), app_url()));
+        EXPECT_TRUE(IsPlaceholderApp(profile(), kWebAppUrl));
 
         EXPECT_EQ(1, install_finalizer()->num_create_os_shortcuts_calls());
         EXPECT_TRUE(install_finalizer()->finalize_options().policy_installed);
         std::unique_ptr<WebApplicationInfo> web_app_info =
             install_finalizer()->web_app_info();
 
-        EXPECT_EQ(base::UTF8ToUTF16(app_url().spec()), web_app_info->title);
-        EXPECT_EQ(app_url(), web_app_info->app_url);
+        EXPECT_EQ(base::UTF8ToUTF16(kWebAppUrl.spec()), web_app_info->title);
+        EXPECT_EQ(kWebAppUrl, web_app_info->app_url);
         EXPECT_TRUE(web_app_info->open_as_window);
         EXPECT_TRUE(web_app_info->icons.empty());
 
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc
index 78aafa6..21e2861 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc
@@ -27,8 +27,8 @@
 
 namespace {
 
-const char kFooWebAppUrl[] = "https://foo.example";
-const char kBarWebAppUrl[] = "https://bar.example";
+const GURL kFooWebAppUrl("https://foo.example");
+const GURL kBarWebAppUrl("https://bar.example");
 
 class TestExtensionRegistryObserver : public ExtensionRegistryObserver {
  public:
@@ -141,10 +141,10 @@
 };
 
 TEST_F(BookmarkAppUninstallerTest, Uninstall_Successful) {
-  SimulateInstalledApp(GURL(kFooWebAppUrl));
+  SimulateInstalledApp(kFooWebAppUrl);
   ASSERT_EQ(1u, enabled_extensions().size());
 
-  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_TRUE(uninstaller().UninstallApp(kFooWebAppUrl));
   content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(1u, uninstalled_extension_ids().size());
@@ -152,11 +152,11 @@
 }
 
 TEST_F(BookmarkAppUninstallerTest, Uninstall_Multiple) {
-  auto foo_app_id = SimulateInstalledApp(GURL(kFooWebAppUrl));
-  auto bar_app_id = SimulateInstalledApp(GURL(kBarWebAppUrl));
+  auto foo_app_id = SimulateInstalledApp(kFooWebAppUrl);
+  auto bar_app_id = SimulateInstalledApp(kBarWebAppUrl);
   ASSERT_EQ(2u, enabled_extensions().size());
 
-  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kBarWebAppUrl)));
+  EXPECT_TRUE(uninstaller().UninstallApp(kBarWebAppUrl));
   content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(1u, uninstalled_extension_ids().size());
@@ -166,7 +166,7 @@
 
   ResetResults();
 
-  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_TRUE(uninstaller().UninstallApp(kFooWebAppUrl));
   content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(1u, uninstalled_extension_ids().size());
@@ -174,22 +174,22 @@
 }
 
 TEST_F(BookmarkAppUninstallerTest, Uninstall_UninstalledExternalApp) {
-  SimulateInstalledApp(GURL(kFooWebAppUrl));
-  SimulateExternalAppUninstalledByUser(GURL(kFooWebAppUrl));
+  SimulateInstalledApp(kFooWebAppUrl);
+  SimulateExternalAppUninstalledByUser(kFooWebAppUrl);
 
-  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_FALSE(uninstaller().UninstallApp(kFooWebAppUrl));
 }
 
 // Tests trying to uninstall an app that was never installed.
 TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsNeverInstalled) {
-  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_FALSE(uninstaller().UninstallApp(kFooWebAppUrl));
 }
 
 // Tests trying to uninstall an app that was previously uninstalled.
 TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsAlreadyUninstalled) {
-  SimulateInstalledApp(GURL(kFooWebAppUrl));
+  SimulateInstalledApp(kFooWebAppUrl);
 
-  EXPECT_TRUE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_TRUE(uninstaller().UninstallApp(kFooWebAppUrl));
   content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(1u, uninstalled_extension_ids().size());
@@ -197,7 +197,7 @@
 
   ResetResults();
 
-  EXPECT_FALSE(uninstaller().UninstallApp(GURL(kFooWebAppUrl)));
+  EXPECT_FALSE(uninstaller().UninstallApp(kFooWebAppUrl));
   content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(0u, uninstalled_extension_ids().size());
diff --git a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
index 76a9479..f26d3c9 100644
--- a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
+++ b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
@@ -38,10 +38,10 @@
 
 namespace {
 
-const char kAppUrl[] = "https://www.chromium.org/index.html";
+const GURL kAppUrl("https://www.chromium.org/index.html");
 const char kAppTitle[] = "Test title";
 const char kAppDescription[] = "Test description";
-const char kAppScope[] = "https://www.chromium.org/";
+const GURL kAppScope("https://www.chromium.org/");
 
 const int kIconSizeTiny = extension_misc::EXTENSION_ICON_BITTY;
 const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL;
@@ -105,10 +105,10 @@
 
 TEST_F(InstallManagerBookmarkAppTest, CreateWebAppFromInfo) {
   auto web_app_info = std::make_unique<WebApplicationInfo>();
-  web_app_info->app_url = GURL(kAppUrl);
+  web_app_info->app_url = kAppUrl;
   web_app_info->title = base::UTF8ToUTF16(kAppTitle);
   web_app_info->description = base::UTF8ToUTF16(kAppDescription);
-  web_app_info->scope = GURL(kAppScope);
+  web_app_info->scope = kAppScope;
   web_app_info->icons.push_back(
       CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED));
 
@@ -136,8 +136,8 @@
   EXPECT_TRUE(extension->from_bookmark());
   EXPECT_EQ(kAppTitle, extension->name());
   EXPECT_EQ(kAppDescription, extension->description());
-  EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
-  EXPECT_EQ(GURL(kAppScope), GetScopeURLFromBookmarkApp(extension));
+  EXPECT_EQ(kAppUrl, AppLaunchInfo::GetLaunchWebURL(extension));
+  EXPECT_EQ(kAppScope, GetScopeURLFromBookmarkApp(extension));
   EXPECT_FALSE(IconsInfo::GetIconResource(extension, kIconSizeTiny,
                                           ExtensionIconSet::MATCH_EXACTLY)
                    .empty());
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
index b8b7bbf9..6acad24 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -40,15 +40,14 @@
     std::vector<std::pair<GURL, web_app::InstallResultCode>>;
 using UninstallAppsResults = std::vector<std::pair<GURL, bool>>;
 
-const char kFooWebAppUrl[] = "https://foo.example";
-const char kBarWebAppUrl[] = "https://bar.example";
-const char kQuxWebAppUrl[] = "https://qux.example";
+const GURL kFooWebAppUrl("https://foo.example");
+const GURL kBarWebAppUrl("https://bar.example");
+const GURL kQuxWebAppUrl("https://qux.example");
 
 web_app::InstallOptions GetFooInstallOptions(
     base::Optional<bool> override_previous_user_uninstall =
         base::Optional<bool>()) {
-  web_app::InstallOptions options(GURL(kFooWebAppUrl),
-                                  web_app::LaunchContainer::kTab,
+  web_app::InstallOptions options(kFooWebAppUrl, web_app::LaunchContainer::kTab,
                                   web_app::InstallSource::kExternalPolicy);
 
   if (override_previous_user_uninstall.has_value())
@@ -59,14 +58,14 @@
 }
 
 web_app::InstallOptions GetBarInstallOptions() {
-  web_app::InstallOptions options(GURL(kBarWebAppUrl),
+  web_app::InstallOptions options(kBarWebAppUrl,
                                   web_app::LaunchContainer::kWindow,
                                   web_app::InstallSource::kExternalPolicy);
   return options;
 }
 
 web_app::InstallOptions GetQuxInstallOptions() {
-  web_app::InstallOptions options(GURL(kQuxWebAppUrl),
+  web_app::InstallOptions options(kQuxWebAppUrl,
                                   web_app::LaunchContainer::kWindow,
                                   web_app::InstallSource::kExternalPolicy);
   return options;
@@ -411,14 +410,14 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_Succeeds) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   base::Optional<GURL> url;
   base::Optional<web_app::InstallResultCode> code;
   std::tie(url, code) =
       InstallAndWait(pending_app_manager.get(), GetFooInstallOptions());
 
   EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-  EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+  EXPECT_EQ(kFooWebAppUrl, url.value());
 
   EXPECT_EQ(1u, install_run_count());
   EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -427,7 +426,7 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_SerialCallsDifferentApps) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   {
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -435,14 +434,14 @@
         InstallAndWait(pending_app_manager.get(), GetFooInstallOptions());
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(GetFooInstallOptions(), last_app_info());
   }
 
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   {
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -451,7 +450,7 @@
         InstallAndWait(pending_app_manager.get(), GetBarInstallOptions());
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kBarWebAppUrl), url.value());
+    EXPECT_EQ(kBarWebAppUrl, url.value());
 
     EXPECT_EQ(2u, install_run_count());
     EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -462,9 +461,9 @@
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
 
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
   pending_app_manager->Install(
@@ -472,7 +471,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
 
             // Two installations tasks should have run at this point,
             // one from the last call to install (which gets higher priority),
@@ -487,7 +486,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kBarWebAppUrl), url);
+            EXPECT_EQ(kBarWebAppUrl, url);
 
             // The last call gets higher priority so only one
             // installation task should have run at this point.
@@ -500,9 +499,9 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_PendingSuccessfulTask) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SaveLoadUrlRequests();
 
   base::RunLoop foo_run_loop;
@@ -513,7 +512,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
 
             EXPECT_EQ(1u, install_run_count());
             EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -528,7 +527,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kBarWebAppUrl), url);
+            EXPECT_EQ(kBarWebAppUrl, url);
 
             EXPECT_EQ(2u, install_run_count());
             EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -549,10 +548,9 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_PendingFailingTask) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl),
-      web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SaveLoadUrlRequests();
 
   base::RunLoop foo_run_loop;
@@ -563,7 +561,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
 
             // The installation didn't run because we loaded the wrong url.
             EXPECT_EQ(0u, install_run_count());
@@ -577,7 +575,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kBarWebAppUrl), url);
+            EXPECT_EQ(kBarWebAppUrl, url);
 
             EXPECT_EQ(1u, install_run_count());
             EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -598,15 +596,15 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_ReentrantCallback) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
   auto final_callback = base::BindLambdaForTesting(
       [&](const GURL& url, web_app::InstallResultCode code) {
         EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-        EXPECT_EQ(GURL(kBarWebAppUrl), url);
+        EXPECT_EQ(kBarWebAppUrl, url);
 
         EXPECT_EQ(2u, install_run_count());
         EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -615,7 +613,7 @@
   auto reentrant_callback = base::BindLambdaForTesting(
       [&](const GURL& url, web_app::InstallResultCode code) {
         EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-        EXPECT_EQ(GURL(kFooWebAppUrl), url);
+        EXPECT_EQ(kFooWebAppUrl, url);
 
         EXPECT_EQ(1u, install_run_count());
         EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -631,7 +629,7 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_SerialCallsSameApp) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   {
     base::Optional<GURL> url;
@@ -640,7 +638,7 @@
         InstallAndWait(pending_app_manager.get(), GetFooInstallOptions());
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-    EXPECT_EQ(GURL(kFooWebAppUrl), url);
+    EXPECT_EQ(kFooWebAppUrl, url);
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -653,7 +651,7 @@
         InstallAndWait(pending_app_manager.get(), GetFooInstallOptions());
 
     EXPECT_EQ(web_app::InstallResultCode::kAlreadyInstalled, code);
-    EXPECT_EQ(GURL(kFooWebAppUrl), url);
+    EXPECT_EQ(kFooWebAppUrl, url);
 
     // The app is already installed so we shouldn't try to install it again.
     EXPECT_EQ(1u, install_run_count());
@@ -663,7 +661,7 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_ConcurrentCallsSameApp) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
   bool first_callback_ran = false;
@@ -675,7 +673,7 @@
             // kAlreadyInstalled because the last call to Install gets higher
             // priority.
             EXPECT_EQ(web_app::InstallResultCode::kAlreadyInstalled, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
 
             // Only one installation task should run because the app was already
             // installed.
@@ -691,7 +689,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
 
             EXPECT_EQ(1u, install_run_count());
             EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -706,10 +704,10 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_AlwaysUpdate) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   auto get_always_update_info = []() {
-    web_app::InstallOptions options(GURL(kFooWebAppUrl),
+    web_app::InstallOptions options(kFooWebAppUrl,
                                     web_app::LaunchContainer::kWindow,
                                     web_app::InstallSource::kExternalPolicy);
     options.always_update = true;
@@ -723,14 +721,14 @@
         InstallAndWait(pending_app_manager.get(), get_always_update_info());
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-    EXPECT_EQ(GURL(kFooWebAppUrl), url);
+    EXPECT_EQ(kFooWebAppUrl, url);
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(get_always_update_info(), last_app_info());
   }
 
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   {
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -738,7 +736,7 @@
         InstallAndWait(pending_app_manager.get(), get_always_update_info());
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-    EXPECT_EQ(GURL(kFooWebAppUrl), url);
+    EXPECT_EQ(kFooWebAppUrl, url);
 
     // The app should be installed again because of the |always_update| flag.
     EXPECT_EQ(2u, install_run_count());
@@ -749,8 +747,7 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_FailsLoadIncorrectURL) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl),
-      web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
 
   base::Optional<GURL> url;
   base::Optional<web_app::InstallResultCode> code;
@@ -758,7 +755,7 @@
       InstallAndWait(pending_app_manager.get(), GetFooInstallOptions());
 
   EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason, code);
-  EXPECT_EQ(GURL(kFooWebAppUrl), url);
+  EXPECT_EQ(kFooWebAppUrl, url);
 
   EXPECT_EQ(0u, install_run_count());
   EXPECT_EQ(0u, install_placeholder_run_count());
@@ -767,8 +764,7 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_PlaceholderApp) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl),
-      web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
 
   auto install_options = GetFooInstallOptions();
   install_options.install_placeholder = true;
@@ -779,7 +775,7 @@
       InstallAndWait(pending_app_manager.get(), install_options);
 
   EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-  EXPECT_EQ(GURL(kFooWebAppUrl), url);
+  EXPECT_EQ(kFooWebAppUrl, url);
 
   EXPECT_EQ(0u, install_run_count());
   EXPECT_EQ(1u, install_placeholder_run_count());
@@ -788,7 +784,7 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_Succeeds) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   std::vector<web_app::InstallOptions> apps_to_install;
   apps_to_install.push_back(GetFooInstallOptions());
@@ -798,7 +794,7 @@
 
   EXPECT_EQ(results,
             InstallAppsResults(
-                {{GURL(kFooWebAppUrl), web_app::InstallResultCode::kSuccess}}));
+                {{kFooWebAppUrl, web_app::InstallResultCode::kSuccess}}));
 
   EXPECT_EQ(1u, install_run_count());
   EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -807,8 +803,7 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_Fails) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl),
-      web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
 
   std::vector<web_app::InstallOptions> apps_to_install;
   apps_to_install.push_back(GetFooInstallOptions());
@@ -816,9 +811,10 @@
   InstallAppsResults results =
       InstallAppsAndWait(pending_app_manager.get(), std::move(apps_to_install));
 
-  EXPECT_EQ(results, InstallAppsResults(
-                         {{GURL(kFooWebAppUrl),
-                           web_app::InstallResultCode::kFailedUnknownReason}}));
+  EXPECT_EQ(
+      results,
+      InstallAppsResults(
+          {{kFooWebAppUrl, web_app::InstallResultCode::kFailedUnknownReason}}));
 
   EXPECT_EQ(0u, install_run_count());
   EXPECT_EQ(0u, install_placeholder_run_count());
@@ -827,8 +823,7 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_PlaceholderApp) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl),
-      web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
 
   std::vector<web_app::InstallOptions> apps_to_install;
   apps_to_install.push_back(GetFooInstallOptions());
@@ -839,7 +834,7 @@
 
   EXPECT_EQ(results,
             InstallAppsResults(
-                {{GURL(kFooWebAppUrl), web_app::InstallResultCode::kSuccess}}));
+                {{kFooWebAppUrl, web_app::InstallResultCode::kSuccess}}));
 
   EXPECT_EQ(0u, install_run_count());
   EXPECT_EQ(1u, install_placeholder_run_count());
@@ -848,9 +843,9 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_Multiple) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   std::vector<web_app::InstallOptions> apps_to_install;
   apps_to_install.push_back(GetFooInstallOptions());
@@ -861,8 +856,8 @@
 
   EXPECT_EQ(results,
             InstallAppsResults(
-                {{GURL(kFooWebAppUrl), web_app::InstallResultCode::kSuccess},
-                 {GURL(kBarWebAppUrl), web_app::InstallResultCode::kSuccess}}));
+                {{kFooWebAppUrl, web_app::InstallResultCode::kSuccess},
+                 {kBarWebAppUrl, web_app::InstallResultCode::kSuccess}}));
 
   EXPECT_EQ(2u, install_run_count());
   EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -871,9 +866,9 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_PendingInstallApps) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
   {
@@ -885,7 +880,7 @@
         base::BindLambdaForTesting(
             [&](const GURL& url, web_app::InstallResultCode code) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kFooWebAppUrl), url);
+              EXPECT_EQ(kFooWebAppUrl, url);
 
               EXPECT_EQ(1u, install_run_count());
               EXPECT_EQ(GetFooInstallOptions(), last_app_info());
@@ -901,7 +896,7 @@
         base::BindLambdaForTesting(
             [&](const GURL& url, web_app::InstallResultCode code) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kBarWebAppUrl), url);
+              EXPECT_EQ(kBarWebAppUrl, url);
 
               EXPECT_EQ(2u, install_run_count());
               EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -915,11 +910,11 @@
 TEST_F(PendingBookmarkAppManagerTest, Install_PendingMulitpleInstallApps) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kQuxWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kQuxWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
 
@@ -936,13 +931,13 @@
             ++callback_calls;
             if (callback_calls == 1) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kFooWebAppUrl), url);
+              EXPECT_EQ(kFooWebAppUrl, url);
 
               EXPECT_EQ(2u, install_run_count());
               EXPECT_EQ(GetFooInstallOptions(), last_app_info());
             } else if (callback_calls == 2) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kBarWebAppUrl), url);
+              EXPECT_EQ(kBarWebAppUrl, url);
 
               EXPECT_EQ(3u, install_run_count());
               EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -959,7 +954,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kQuxWebAppUrl), url);
+            EXPECT_EQ(kQuxWebAppUrl, url);
 
             // The install request from Install should be processed first.
             EXPECT_EQ(1u, install_run_count());
@@ -972,11 +967,11 @@
 TEST_F(PendingBookmarkAppManagerTest, InstallApps_PendingInstall) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kBarWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kBarWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
   url_loader()->SetNextLoadUrlResult(
-      GURL(kQuxWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kQuxWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
 
@@ -986,7 +981,7 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kQuxWebAppUrl), url);
+            EXPECT_EQ(kQuxWebAppUrl, url);
 
             // The install request from Install should be processed first.
             EXPECT_EQ(1u, install_run_count());
@@ -1006,7 +1001,7 @@
             ++callback_calls;
             if (callback_calls == 1) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kFooWebAppUrl), url);
+              EXPECT_EQ(kFooWebAppUrl, url);
 
               // The install requests from InstallApps should be processed next.
               EXPECT_EQ(2u, install_run_count());
@@ -1016,7 +1011,7 @@
             }
             if (callback_calls == 2) {
               EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-              EXPECT_EQ(GURL(kBarWebAppUrl), url);
+              EXPECT_EQ(kBarWebAppUrl, url);
 
               EXPECT_EQ(3u, install_run_count());
               EXPECT_EQ(GetBarInstallOptions(), last_app_info());
@@ -1032,7 +1027,7 @@
 TEST_F(PendingBookmarkAppManagerTest, ExtensionUninstalled) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   {
     base::Optional<GURL> url;
@@ -1045,13 +1040,13 @@
   }
 
   // Simulate the extension for the app getting uninstalled.
-  const std::string app_id = GenerateFakeAppId(GURL(kFooWebAppUrl));
+  const std::string app_id = GenerateFakeAppId(kFooWebAppUrl);
   registrar()->RemoveAsInstalled(app_id);
 
   // Try to install the app again.
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1067,7 +1062,7 @@
 TEST_F(PendingBookmarkAppManagerTest, ExternalExtensionUninstalled) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   {
     base::Optional<GURL> url;
@@ -1080,7 +1075,7 @@
   }
 
   // Simulate external extension for the app getting uninstalled by the user.
-  const std::string app_id = GenerateFakeAppId(GURL(kFooWebAppUrl));
+  const std::string app_id = GenerateFakeAppId(kFooWebAppUrl);
   registrar()->AddAsExternalAppUninstalledByUser(app_id);
   registrar()->RemoveAsInstalled(app_id);
 
@@ -1102,7 +1097,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1117,52 +1112,52 @@
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Succeeds) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
-  registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl)));
+  registrar()->AddAsInstalled(GenerateFakeAppId(kFooWebAppUrl));
 
-  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+  uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
   UninstallAppsResults results = UninstallAppsAndWait(
-      pending_app_manager.get(), std::vector<GURL>{GURL(kFooWebAppUrl)});
+      pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl});
 
-  EXPECT_EQ(results, UninstallAppsResults({{GURL(kFooWebAppUrl), true}}));
+  EXPECT_EQ(results, UninstallAppsResults({{kFooWebAppUrl, true}}));
 
   EXPECT_EQ(1u, uninstall_call_count());
-  EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+  EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 }
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Fails) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
 
-  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
+  uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false);
   UninstallAppsResults results = UninstallAppsAndWait(
-      pending_app_manager.get(), std::vector<GURL>{GURL(kFooWebAppUrl)});
-  EXPECT_EQ(results, UninstallAppsResults({{GURL(kFooWebAppUrl), false}}));
+      pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl});
+  EXPECT_EQ(results, UninstallAppsResults({{kFooWebAppUrl, false}}));
 
   EXPECT_EQ(1u, uninstall_call_count());
-  EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+  EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 }
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Multiple) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
-  registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl)));
-  registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kBarWebAppUrl)));
+  registrar()->AddAsInstalled(GenerateFakeAppId(kFooWebAppUrl));
+  registrar()->AddAsInstalled(GenerateFakeAppId(kBarWebAppUrl));
 
-  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
-  uninstaller()->SetNextResultForTesting(GURL(kBarWebAppUrl), true);
-  UninstallAppsResults results = UninstallAppsAndWait(
-      pending_app_manager.get(),
-      std::vector<GURL>{GURL(kFooWebAppUrl), GURL(kBarWebAppUrl)});
-  EXPECT_EQ(results, UninstallAppsResults({{GURL(kFooWebAppUrl), true},
-                                           {GURL(kBarWebAppUrl), true}}));
+  uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
+  uninstaller()->SetNextResultForTesting(kBarWebAppUrl, true);
+  UninstallAppsResults results =
+      UninstallAppsAndWait(pending_app_manager.get(),
+                           std::vector<GURL>{kFooWebAppUrl, kBarWebAppUrl});
+  EXPECT_EQ(results, UninstallAppsResults(
+                         {{kFooWebAppUrl, true}, {kBarWebAppUrl, true}}));
 
   EXPECT_EQ(2u, uninstall_call_count());
-  EXPECT_EQ(std::vector<GURL>({GURL(kFooWebAppUrl), GURL(kBarWebAppUrl)}),
+  EXPECT_EQ(std::vector<GURL>({kFooWebAppUrl, kBarWebAppUrl}),
             uninstalled_app_urls());
 }
 
 TEST_F(PendingBookmarkAppManagerTest, UninstallApps_PendingInstall) {
   auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
   url_loader()->SetNextLoadUrlResult(
-      GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
+      kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
 
   base::RunLoop run_loop;
   pending_app_manager->Install(
@@ -1170,15 +1165,14 @@
       base::BindLambdaForTesting(
           [&](const GURL& url, web_app::InstallResultCode code) {
             EXPECT_EQ(web_app::InstallResultCode::kSuccess, code);
-            EXPECT_EQ(GURL(kFooWebAppUrl), url);
+            EXPECT_EQ(kFooWebAppUrl, url);
             run_loop.Quit();
           }));
 
-  uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
+  uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false);
   UninstallAppsResults uninstall_results = UninstallAppsAndWait(
-      pending_app_manager.get(), std::vector<GURL>{GURL(kFooWebAppUrl)});
-  EXPECT_EQ(uninstall_results,
-            UninstallAppsResults({{GURL(kFooWebAppUrl), false}}));
+      pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl});
+  EXPECT_EQ(uninstall_results, UninstallAppsResults({{kFooWebAppUrl, false}}));
   EXPECT_EQ(1u, uninstall_call_count());
 
   run_loop.Run();
@@ -1192,8 +1186,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
     std::tie(url, code) =
@@ -1207,8 +1200,8 @@
   {
     install_options.reinstall_placeholder = true;
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
-    uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
+    uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1216,10 +1209,10 @@
         InstallAndWait(pending_app_manager.get(), install_options);
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     EXPECT_EQ(1u, uninstall_call_count());
-    EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+    EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(1u, install_placeholder_run_count());
@@ -1236,8 +1229,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
     std::tie(url, code) =
@@ -1251,8 +1243,8 @@
   {
     install_options.reinstall_placeholder = true;
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
-    uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
+    uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1260,10 +1252,10 @@
         InstallAndWait(pending_app_manager.get(), install_options);
 
     EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     EXPECT_EQ(1u, uninstall_call_count());
-    EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+    EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 
     EXPECT_EQ(0u, install_run_count());
     EXPECT_EQ(1u, install_placeholder_run_count());
@@ -1280,8 +1272,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
     std::tie(url, code) =
@@ -1295,9 +1286,8 @@
   {
     install_options.reinstall_placeholder = true;
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
-    uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+    uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1305,7 +1295,7 @@
         InstallAndWait(pending_app_manager.get(), install_options);
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     // We don't uninstall the placeholder app if we are going to fail
     // installing the new app.
@@ -1325,8 +1315,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
     std::tie(url, code) =
@@ -1340,11 +1329,10 @@
   {
     install_options.reinstall_placeholder = true;
     install_options.wait_for_windows_closed = true;
-    ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(GURL(kFooWebAppUrl)),
-                                       0);
+    ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(kFooWebAppUrl), 0);
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
-    uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
+    uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1352,10 +1340,10 @@
         InstallAndWait(pending_app_manager.get(), install_options);
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     EXPECT_EQ(1u, uninstall_call_count());
-    EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+    EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(1u, install_placeholder_run_count());
@@ -1372,8 +1360,7 @@
 
   {
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl),
-        web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
     std::tie(url, code) =
@@ -1387,11 +1374,10 @@
   {
     install_options.reinstall_placeholder = true;
     install_options.wait_for_windows_closed = true;
-    ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(GURL(kFooWebAppUrl)),
-                                       1);
+    ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(kFooWebAppUrl), 1);
     url_loader()->SetNextLoadUrlResult(
-        GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
-    uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
+        kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded);
+    uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true);
 
     base::Optional<GURL> url;
     base::Optional<web_app::InstallResultCode> code;
@@ -1399,10 +1385,10 @@
         InstallAndWait(pending_app_manager.get(), install_options);
 
     EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
-    EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
+    EXPECT_EQ(kFooWebAppUrl, url.value());
 
     EXPECT_EQ(1u, uninstall_call_count());
-    EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
+    EXPECT_EQ(kFooWebAppUrl, last_uninstalled_app_url());
 
     EXPECT_EQ(1u, install_run_count());
     EXPECT_EQ(1u, install_placeholder_run_count());
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc
index 32d9116..4d3b162 100644
--- a/chrome/service/service_process.cc
+++ b/chrome/service/service_process.cc
@@ -25,7 +25,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/thread_group_params.h"
 #include "base/task/thread_pool/thread_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -164,7 +164,7 @@
   base::ThreadPool::GetInstance()->Start(
       {{kMaxBackgroundThreads, kSuggestedReclaimTime},
        {kMaxForegroundThreads, kSuggestedReclaimTime,
-        base::SchedulerBackwardCompatibility::INIT_COM_STA}});
+        base::WorkerThreadBackwardCompatibility::INIT_COM_STA}});
 
   // The NetworkChangeNotifier must be created after ThreadPool because it
   // posts tasks to it.
diff --git a/chrome/services/cups_ipp_parser/BUILD.gn b/chrome/services/cups_ipp_parser/BUILD.gn
index 6b79dcd..88a16bc5 100644
--- a/chrome/services/cups_ipp_parser/BUILD.gn
+++ b/chrome/services/cups_ipp_parser/BUILD.gn
@@ -27,7 +27,7 @@
     "//services/service_manager/public/cpp",
   ]
 
-  # We stub the implementation if libCUPS is not present
+  # We stub the implementation if libCUPS is not present.
   if (enable_service) {
     configs += [ "//printing:cups" ]
     sources += [ "ipp_parser.cc" ]
diff --git a/chrome/services/cups_ipp_parser/cups_ipp_parser_service.h b/chrome/services/cups_ipp_parser/cups_ipp_parser_service.h
index 3c164e56..930aa39 100644
--- a/chrome/services/cups_ipp_parser/cups_ipp_parser_service.h
+++ b/chrome/services/cups_ipp_parser/cups_ipp_parser_service.h
@@ -11,6 +11,19 @@
 #include "services/service_manager/public/cpp/service_keepalive.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 
+// CupsIppParser Service Implementation.
+//
+// This service's sole purpose is parsing CUPS IPP printing requests. It accepts
+// arbitrary byte buffers as input and returns a fully-parsed IPP request,
+// mojom::IppRequest, as a result.
+//
+// Because this service doesn't know the origin of these requests, it
+// treats each request as potentially malicious. As such, this service runs
+// out-of-process, lessening the chance of exposing an exploit to the rest of
+// Chrome.
+//
+// Note: In practice, this service is used to support printing requests incoming
+// from ChromeOS.
 class CupsIppParserService : public service_manager::Service {
  public:
   explicit CupsIppParserService(service_manager::mojom::ServiceRequest request);
diff --git a/chrome/services/cups_ipp_parser/fake_ipp_parser.cc b/chrome/services/cups_ipp_parser/fake_ipp_parser.cc
index 043ecc33..182aa3f 100644
--- a/chrome/services/cups_ipp_parser/fake_ipp_parser.cc
+++ b/chrome/services/cups_ipp_parser/fake_ipp_parser.cc
@@ -15,10 +15,10 @@
 
 IppParser::~IppParser() = default;
 
-void IppParser::ParseIpp(const std::string& to_parse,
+void IppParser::ParseIpp(const std::vector<uint8_t>& to_parse,
                          ParseIppCallback callback) {
   DVLOG(1) << "IppParser stubbed";
-  std::move(callback).Run(mojom::IppParserResult::FAILURE, nullptr);
+  std::move(callback).Run(nullptr);
 }
 
 }  // namespace chrome
diff --git a/chrome/services/cups_ipp_parser/ipp_parser.cc b/chrome/services/cups_ipp_parser/ipp_parser.cc
index 95042b6..fbb1539 100644
--- a/chrome/services/cups_ipp_parser/ipp_parser.cc
+++ b/chrome/services/cups_ipp_parser/ipp_parser.cc
@@ -23,7 +23,7 @@
 // Log debugging error and send empty response, signalling error.
 void Fail(const std::string& error_log, IppParser::ParseIppCallback cb) {
   DVLOG(1) << "IPP Parser Error: " << error_log;
-  std::move(cb).Run(mojom::IppParserResult::FAILURE, nullptr);
+  std::move(cb).Run(nullptr);
   return;
 }
 
@@ -39,14 +39,14 @@
 
 // Returns the starting index of the first HTTP header, -1 on failure.
 int LocateStartOfHeaders(base::StringPiece request) {
-  auto idx = request.find(kCarriage);
-  if (idx == base::StringPiece::npos) {
+  auto idx = LocateEndOfRequestLine(request);
+  if (idx < 0) {
     return -1;
   }
 
   // Advance to first header and check it exists
   idx += strlen(kCarriage);
-  return idx < request.size() ? idx : -1;
+  return idx < static_cast<int>(request.size()) ? idx : -1;
 }
 
 // Returns the starting index of the end-of-headers-delimiter, -1 on failure.
@@ -58,36 +58,51 @@
 
   // Back up to the start of the delimiter.
   // Note: The end-of-http-headers delimiter is 2 back-to-back carriage returns.
-  const size_t end_of_headers_delimiter_size = 2 * strlen(kCarriage);
+  const int end_of_headers_delimiter_size = 2 * strlen(kCarriage);
   return idx - end_of_headers_delimiter_size;
 }
 
-// Returns the starting index of the IPP message, -1 on failure.
-int LocateStartOfIppMessage(base::StringPiece request) {
-  return net::HttpUtil::LocateEndOfHeaders(request.data(), request.size());
-}
-
-// Return the starting index of the IPP data/payload(pdf),
-// Returns |request|.size() on empty IppData and -1 on failure.
-int LocateStartOfIppData(base::StringPiece request) {
-  int end_of_headers = LocateEndOfHeaders(request);
-  if (end_of_headers < 0) {
+// Return the starting index of the IPP data/payload (pdf).
+// Returns |ipp_metadata|.size() on empty IPP data and -1 on failure.
+int LocateStartOfIppData(base::span<const uint8_t> ipp_metadata) {
+  std::vector<uint8_t> sentinel_wrapper(
+      ipp_converter::ConvertToByteBuffer(kIppSentinel));
+  auto it = std::search(ipp_metadata.begin(), ipp_metadata.end(),
+                        sentinel_wrapper.begin(), sentinel_wrapper.end());
+  if (it == ipp_metadata.end()) {
     return -1;
   }
 
-  auto idx = request.find(kIppSentinel, end_of_headers);
-  if (idx == base::StringPiece::npos) {
-    return -1;
-  }
-
-  // Advance to start and check existence or end of request.
-  idx += strlen(kIppSentinel);
-  return idx <= request.size() ? idx : -1;
+  // Advance to the start of IPP data and check existence or end of request.
+  it += strlen(kIppSentinel);
+  return it <= ipp_metadata.end() ? std::distance(ipp_metadata.begin(), it)
+                                  : -1;
 }
 
-base::Optional<std::vector<std::string>> ExtractRequestLine(
+// Returns the starting index of the IPP metadata, -1 on failure.
+int LocateStartOfIppMetadata(base::span<const uint8_t> request) {
+  std::vector<char> char_buffer = ipp_converter::ConvertToCharBuffer(request);
+  return net::HttpUtil::LocateEndOfHeaders(char_buffer.data(),
+                                           char_buffer.size());
+}
+
+bool SplitRequestMetadata(base::span<const uint8_t> request,
+                          std::string* http_metadata,
+                          base::span<const uint8_t>* ipp_metadata) {
+  size_t start_of_ipp_metadata = LocateStartOfIppMetadata(request);
+  if (start_of_ipp_metadata < 0) {
+    return false;
+  }
+
+  *http_metadata =
+      ipp_converter::ConvertToString(request.first(start_of_ipp_metadata));
+  *ipp_metadata = request.subspan(start_of_ipp_metadata);
+  return true;
+}
+
+base::Optional<std::vector<std::string>> ExtractHttpRequestLine(
     base::StringPiece request) {
-  int end_of_request_line = LocateEndOfRequestLine(request);
+  size_t end_of_request_line = LocateEndOfRequestLine(request);
   if (end_of_request_line < 0) {
     return base::nullopt;
   }
@@ -97,14 +112,14 @@
   return ipp_converter::ParseRequestLine(request_line_slice);
 }
 
-base::Optional<std::vector<HttpHeader>> ExtractHeaders(
+base::Optional<std::vector<HttpHeader>> ExtractHttpHeaders(
     base::StringPiece request) {
-  int start_of_headers = LocateStartOfHeaders(request);
+  size_t start_of_headers = LocateStartOfHeaders(request);
   if (start_of_headers < 0) {
     return base::nullopt;
   }
 
-  int end_of_headers = LocateEndOfHeaders(request);
+  size_t end_of_headers = LocateEndOfHeaders(request);
   if (end_of_headers < 0) {
     return base::nullopt;
   }
@@ -114,15 +129,8 @@
   return ipp_converter::ParseHeaders(headers_slice);
 }
 
-mojom::IppMessagePtr ExtractIppMessage(base::StringPiece request) {
-  int start_of_ipp_message = LocateStartOfIppMessage(request);
-  if (start_of_ipp_message < 0) {
-    return nullptr;
-  }
-
-  std::vector<uint8_t> ipp_slice =
-      ipp_converter::ConvertToByteBuffer(request.substr(start_of_ipp_message));
-  printing::ScopedIppPtr ipp = ipp_converter::ParseIppMessage(ipp_slice);
+mojom::IppMessagePtr ExtractIppMessage(base::span<const uint8_t> ipp_metadata) {
+  printing::ScopedIppPtr ipp = ipp_converter::ParseIppMessage(ipp_metadata);
   if (!ipp) {
     return nullptr;
   }
@@ -130,16 +138,15 @@
   return ipp_converter::ConvertIppToMojo(ipp.get());
 }
 
-// Parse IPP request's |ipp_data|
-base::Optional<std::vector<uint8_t>> ExtractIppData(base::StringPiece request) {
-  size_t start_of_ipp_data = LocateStartOfIppData(request);
+base::Optional<std::vector<uint8_t>> ExtractIppData(
+    base::span<const uint8_t> ipp_metadata) {
+  auto start_of_ipp_data = LocateStartOfIppData(ipp_metadata);
   if (start_of_ipp_data < 0) {
     return base::nullopt;
   }
 
-  // Subtlety: Correctly generates empty buffers for requests without ipp_data.
-  const base::StringPiece ipp_data_slice = request.substr(start_of_ipp_data);
-  return ipp_converter::ConvertToByteBuffer(ipp_data_slice);
+  ipp_metadata = ipp_metadata.subspan(start_of_ipp_data);
+  return std::vector<uint8_t>{ipp_metadata.begin(), ipp_metadata.end()};
 }
 
 }  // namespace
@@ -150,50 +157,54 @@
 
 IppParser::~IppParser() = default;
 
-// Checks that |to_parse| is a correctly formatted IPP request, per RFC2910.
-// Calls |callback| with a fully parsed IPP request on success, empty on
-// failure.
-void IppParser::ParseIpp(const std::string& to_parse,
+void IppParser::ParseIpp(const std::vector<uint8_t>& to_parse,
                          ParseIppCallback callback) {
-  // Parse Request line
-  auto request_line = ExtractRequestLine(to_parse);
+  // Separate |to_parse| into http metadata (interpreted as ASCII chars), and
+  // ipp metadata (interpreted as arbitrary bytes).
+  std::string http_metadata;
+  base::span<const uint8_t> ipp_metadata;
+  if (!SplitRequestMetadata(to_parse, &http_metadata, &ipp_metadata)) {
+    return Fail("Failed to split HTTP and IPP metadata", std::move(callback));
+  }
+
+  // Parse Request line.
+  auto request_line = ExtractHttpRequestLine(http_metadata);
   if (!request_line) {
     return Fail("Failed to parse request line", std::move(callback));
   }
 
-  // Parse Headers
-  auto headers = ExtractHeaders(to_parse);
+  // Parse Headers.
+  auto headers = ExtractHttpHeaders(http_metadata);
   if (!headers) {
     return Fail("Failed to parse headers", std::move(callback));
   }
 
-  // Parse IPP message
-  auto ipp_message = ExtractIppMessage(to_parse);
+  // Parse IPP message.
+  auto ipp_message = ExtractIppMessage(ipp_metadata);
   if (!ipp_message) {
     return Fail("Failed to parse IPP message", std::move(callback));
   }
 
-  // Parse IPP data
-  auto ipp_data = ExtractIppData(to_parse);
+  // Parse IPP data.
+  auto ipp_data = ExtractIppData(ipp_metadata);
   if (!ipp_data) {
     return Fail("Failed to parse IPP data", std::move(callback));
   }
 
-  // Marshall response
+  // Marshall response.
   mojom::IppRequestPtr parsed_request = mojom::IppRequest::New();
 
-  std::vector<std::string> request_line_terms = request_line.value();
+  std::vector<std::string> request_line_terms = *request_line;
   parsed_request->method = request_line_terms[0];
   parsed_request->endpoint = request_line_terms[1];
   parsed_request->http_version = request_line_terms[2];
 
-  parsed_request->headers = std::move(headers.value());
+  parsed_request->headers = std::move(*headers);
   parsed_request->ipp = std::move(ipp_message);
-  parsed_request->data = std::move(ipp_data.value());
+  parsed_request->data = std::move(*ipp_data);
 
   DVLOG(1) << "Finished parsing IPP request.";
-  std::move(callback).Run(mojom::IppParserResult::SUCCESS,
-                          std::move(parsed_request));
+  std::move(callback).Run(std::move(parsed_request));
 }
 
 }  // namespace chrome
diff --git a/chrome/services/cups_ipp_parser/ipp_parser.h b/chrome/services/cups_ipp_parser/ipp_parser.h
index d12d50c..3f3da3ee 100644
--- a/chrome/services/cups_ipp_parser/ipp_parser.h
+++ b/chrome/services/cups_ipp_parser/ipp_parser.h
@@ -10,10 +10,12 @@
 
 namespace chrome {
 
-// This class implements the chrome.mojom.IppParser interface.
-// It is intended to operate under the heavily jailed, out-of-process
-// cups_ipp_parser service, parsing incoming requests before passing
-// them to CUPS.
+// chrome.mojom.IppParser handler.
+//
+// This handler accepts incoming IPP requests as arbitrary buffers, parses
+// the contents using libCUPS, and yields a chrome::mojom::IppRequest. It is
+// intended to operate under the heavily jailed, out-of-process CupsIppParser
+// Service.
 class IppParser : public chrome::mojom::IppParser {
  public:
   explicit IppParser(
@@ -21,11 +23,11 @@
   ~IppParser() override;
 
  private:
-  // chrome::mojom::IppParser
+  // chrome::mojom::IppParser override.
   // Checks that |to_parse| is formatted as a valid IPP request, per RFC2910
   // Calls |callback| with a fully parsed IPP request on success, empty on
   // failure.
-  void ParseIpp(const std::string& to_parse,
+  void ParseIpp(const std::vector<uint8_t>& to_parse,
                 ParseIppCallback callback) override;
 
   const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
diff --git a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cpp b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cpp
index dda0e97..c9927bf 100644
--- a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cpp
+++ b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.cpp
@@ -378,4 +378,9 @@
   return char_buffer;
 }
 
+std::string ConvertToString(base::span<const uint8_t> byte_buffer) {
+  std::vector<char> char_buffer = ConvertToCharBuffer(byte_buffer);
+  return std::string(char_buffer.begin(), char_buffer.end());
+}
+
 }  // namespace ipp_converter
diff --git a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.h b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.h
index 7142bb93..9637305f 100644
--- a/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.h
+++ b/chrome/services/cups_ipp_parser/public/cpp/ipp_converter.h
@@ -91,6 +91,7 @@
 // Common converters for working with arbitrary byte buffers.
 std::vector<uint8_t> ConvertToByteBuffer(base::StringPiece char_buffer);
 std::vector<char> ConvertToCharBuffer(base::span<const uint8_t> byte_buffer);
+std::string ConvertToString(base::span<const uint8_t> byte_buffer);
 
 }  // namespace ipp_converter
 
diff --git a/chrome/services/cups_ipp_parser/public/mojom/ipp_parser.mojom b/chrome/services/cups_ipp_parser/public/mojom/ipp_parser.mojom
index 00546b6..0930032 100644
--- a/chrome/services/cups_ipp_parser/public/mojom/ipp_parser.mojom
+++ b/chrome/services/cups_ipp_parser/public/mojom/ipp_parser.mojom
@@ -2,18 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Interface defining an IPP, Internet Printing Protocol, validator to check
-// the format of incoming requests before passing them to CUPS.
+// Defines a mojom representation for an IPP, Internet Printing Protocol,
+// request, IppRequest, and an interface for parsing arbitrary requests into
+// this format, IppParser.
 
 module chrome.mojom;
 
 [Extensible]
-enum IppParserResult {
-  SUCCESS = 0,
-  FAILURE = 1
-};
-
-[Extensible]
 enum ValueType {
   BOOLEAN,
   DATE,
@@ -53,6 +48,10 @@
   array<uint8> data;
 };
 
+// Implemented by the CupsIppParserService; supports parsing arbitrary IPP
+// requests.
 interface IppParser {
-  ParseIpp(string to_parse) => (IppParserResult success, IppRequest? request);
+  // Treats |to_parse| as an IPP request and attempts to parse into IppRequest
+  // format. Returns empty IppRequest on failure.
+  ParseIpp(array<uint8> to_parse) => (IppRequest? request);
 };
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc
index 63d6b8a..8772374 100644
--- a/chrome/updater/updater.cc
+++ b/chrome/updater/updater.cc
@@ -54,10 +54,10 @@
   base::ThreadPool::Create("Updater");
   const auto thread_pool_init_params =
       std::make_unique<base::ThreadPool::InitParams>(
-          base::SchedulerWorkerPoolParams(
+          base::ThreadGroupParams(
               base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
               base::TimeDelta::FromSeconds(30)),
-          base::SchedulerWorkerPoolParams(
+          base::ThreadGroupParams(
               base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
               base::TimeDelta::FromSeconds(30)));
   base::ThreadPool::GetInstance()->Start(*thread_pool_init_params);
diff --git a/chromecast/media/cma/backend/stream_mixer.cc b/chromecast/media/cma/backend/stream_mixer.cc
index 9911b32..58cdab3 100644
--- a/chromecast/media/cma/backend/stream_mixer.cc
+++ b/chromecast/media/cma/backend/stream_mixer.cc
@@ -729,7 +729,7 @@
 
 void StreamMixer::RemoveLoopbackAudioObserverOnThread(
     CastMediaShlib::LoopbackAudioObserver* observer) {
-  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
+  DCHECK(loopback_task_runner_->BelongsToCurrentThread());
   LOG(INFO) << __func__;
 
   loopback_observers_.erase(observer);
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index df3ce5a..7e1816c 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -143,11 +143,11 @@
       &CastRenderer::OnGetMultiroomInfo, base::Unretained(this), media_resource,
       client, init_cb, application_media_info.Clone(),
       chromecast::mojom::MultiroomInfo::New()));
+  std::string session_id = application_media_info->application_session_id;
   multiroom_manager_->GetMultiroomInfo(
-      application_media_info->application_session_id,
-      base::BindOnce(&CastRenderer::OnGetMultiroomInfo, base::Unretained(this),
-                     media_resource, client, init_cb,
-                     std::move(application_media_info)));
+      session_id, base::BindOnce(&CastRenderer::OnGetMultiroomInfo,
+                                 base::Unretained(this), media_resource, client,
+                                 init_cb, std::move(application_media_info)));
 }
 
 void CastRenderer::OnGetMultiroomInfo(
diff --git a/chromeos/dbus/power/power_manager_client.cc b/chromeos/dbus/power/power_manager_client.cc
index f6b9d9c..1209b65 100644
--- a/chromeos/dbus/power/power_manager_client.cc
+++ b/chromeos/dbus/power/power_manager_client.cc
@@ -1152,13 +1152,15 @@
   DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
 };
 
-// Unlike most D-Bus clients, PowerManagerClient doesn't set the singleton
-// instance in the ctor. This is because the mojo client is also a
-// PowerManagerClient, and co-exists with the D-Bus client in single process
-// Mash. When multi-process Mash is default, g_instance setting/clearing can be
-// moved back to the ctor/dtor.
-PowerManagerClient::PowerManagerClient() = default;
-PowerManagerClient::~PowerManagerClient() = default;
+PowerManagerClient::PowerManagerClient() {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
+
+PowerManagerClient::~PowerManagerClient() {
+  DCHECK_EQ(g_instance, this);
+  g_instance = nullptr;
+}
 
 // static
 void PowerManagerClient::Initialize(dbus::Bus* bus) {
@@ -1171,15 +1173,12 @@
 
 // static
 void PowerManagerClient::InitializeFake() {
-  DCHECK(!g_instance);
-  g_instance = new FakePowerManagerClient();
+  new FakePowerManagerClient();
 }
 
 // static
 void PowerManagerClient::Shutdown() {
-  DCHECK(g_instance);
   delete g_instance;
-  g_instance = nullptr;
 }
 
 // static
diff --git a/chromeos/services/BUILD.gn b/chromeos/services/BUILD.gn
index 78da6acf8..37ea9e7 100644
--- a/chromeos/services/BUILD.gn
+++ b/chromeos/services/BUILD.gn
@@ -25,7 +25,6 @@
     "//chromeos/services/machine_learning/public/cpp:unit_tests",
     "//chromeos/services/multidevice_setup:unit_tests",
     "//chromeos/services/network_config:unit_tests",
-    "//chromeos/services/power/public/cpp:unit_tests",
     "//chromeos/services/secure_channel:unit_tests",
   ]
 
diff --git a/chromeos/services/power/public/cpp/BUILD.gn b/chromeos/services/power/public/cpp/BUILD.gn
deleted file mode 100644
index ec7aff66..0000000
--- a/chromeos/services/power/public/cpp/BUILD.gn
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_chromeos, "Non-Chrome-OS builds must not depend on //chromeos")
-
-import("//testing/test.gni")
-
-# This code is the Mojo controller, so it lives in the same process as the D-Bus
-# client.
-component("controller") {
-  output_name = "chromeos_power_mojo_controller"
-  defines = [ "IS_CHROMEOS_POWER_MOJO_CONTROLLER_IMPL" ]
-
-  public_deps = [
-    "//chromeos/dbus/power:power_manager_proto",
-    "//chromeos/services/power/public/mojom",
-  ]
-  deps = [
-    "//base",
-    "//chromeos/dbus/power",
-  ]
-  sources = [
-    "power_manager_mojo_controller.cc",
-    "power_manager_mojo_controller.h",
-  ]
-}
-
-# The client may live in a separate process (such as Chrome in multi-process
-# Mash).
-component("client") {
-  output_name = "chromeos_power_mojo_client"
-  defines = [ "IS_CHROMEOS_POWER_MOJO_CLIENT_IMPL" ]
-
-  public_deps = [
-    "//chromeos/dbus/power:power_manager_proto",
-    "//chromeos/services/power/public/mojom",
-  ]
-  deps = [
-    "//base",
-    "//chromeos/constants",
-    "//chromeos/dbus/power",
-  ]
-  sources = [
-    "power_manager_mojo_client.cc",
-    "power_manager_mojo_client.h",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  deps = [
-    ":client",
-    ":controller",
-    "//base/test:test_support",
-    "//chromeos/constants",
-    "//chromeos/dbus/power",
-    "//testing/gtest",
-  ]
-  sources = [
-    "power_manager_mojo_controller_unittest.cc",
-  ]
-}
diff --git a/chromeos/services/power/public/cpp/power_manager_mojo_client.cc b/chromeos/services/power/public/cpp/power_manager_mojo_client.cc
deleted file mode 100644
index 6220cf3..0000000
--- a/chromeos/services/power/public/cpp/power_manager_mojo_client.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
-
-#include "base/feature_list.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/power_manager/backlight.pb.h"
-
-namespace chromeos {
-
-namespace {
-PowerManagerMojoClient* g_instance = nullptr;
-}  // namespace
-
-PowerManagerMojoClient::PowerManagerMojoClient() {
-  DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMojoDBusRelay));
-  DCHECK(!g_instance);
-  g_instance = this;
-}
-
-PowerManagerMojoClient::~PowerManagerMojoClient() {
-  DCHECK_EQ(g_instance, this);
-  g_instance = nullptr;
-}
-
-void PowerManagerMojoClient::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-  if (service_available_)
-    observer->PowerManagerBecameAvailable(*service_available_);
-}
-
-void PowerManagerMojoClient::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-bool PowerManagerMojoClient::HasObserver(const Observer* observer) const {
-  return observers_.HasObserver(observer);
-}
-
-void PowerManagerMojoClient::SetRenderProcessManagerDelegate(
-    base::WeakPtr<RenderProcessManagerDelegate> delegate) {}
-
-void PowerManagerMojoClient::DecreaseScreenBrightness(bool allow_off) {}
-
-void PowerManagerMojoClient::IncreaseScreenBrightness() {}
-
-void PowerManagerMojoClient::SetScreenBrightness(
-    const power_manager::SetBacklightBrightnessRequest& request) {}
-
-void PowerManagerMojoClient::GetScreenBrightnessPercent(
-    DBusMethodCallback<double> callback) {
-  // This extra thunk is only necessary to convert between
-  // power::mojom::BrightnessPtr and base::Optional<double>.
-  controller_->GetScreenBrightnessPercent(base::BindOnce(
-      [](DBusMethodCallback<double> callback,
-         power::mojom::BrightnessPtr brightness) {
-        if (brightness)
-          std::move(callback).Run(brightness->value);
-        else
-          std::move(callback).Run(base::nullopt);
-      },
-      std::move(callback)));
-}
-
-void PowerManagerMojoClient::DecreaseKeyboardBrightness() {}
-
-void PowerManagerMojoClient::IncreaseKeyboardBrightness() {}
-
-void PowerManagerMojoClient::GetKeyboardBrightnessPercent(
-    DBusMethodCallback<double> callback) {}
-
-const base::Optional<power_manager::PowerSupplyProperties>&
-PowerManagerMojoClient::GetLastStatus() {
-  return proto_;
-}
-
-void PowerManagerMojoClient::RequestStatusUpdate() {}
-
-void PowerManagerMojoClient::RequestSuspend() {}
-
-void PowerManagerMojoClient::RequestRestart(
-    power_manager::RequestRestartReason reason,
-    const std::string& description) {
-  controller_->RequestRestart(reason, description);
-}
-
-void PowerManagerMojoClient::RequestShutdown(
-    power_manager::RequestShutdownReason reason,
-    const std::string& description) {}
-
-void PowerManagerMojoClient::NotifyUserActivity(
-    power_manager::UserActivityType type) {}
-
-void PowerManagerMojoClient::NotifyVideoActivity(bool is_fullscreen) {}
-
-void PowerManagerMojoClient::NotifyWakeNotification() {}
-
-void PowerManagerMojoClient::SetPolicy(
-    const power_manager::PowerManagementPolicy& policy) {}
-
-void PowerManagerMojoClient::SetIsProjecting(bool is_projecting) {}
-
-void PowerManagerMojoClient::SetPowerSource(const std::string& id) {}
-
-void PowerManagerMojoClient::SetBacklightsForcedOff(bool forced_off) {}
-
-void PowerManagerMojoClient::GetBacklightsForcedOff(
-    DBusMethodCallback<bool> callback) {}
-
-void PowerManagerMojoClient::GetSwitchStates(
-    DBusMethodCallback<SwitchStates> callback) {}
-
-void PowerManagerMojoClient::GetInactivityDelays(
-    DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback) {
-}
-
-void PowerManagerMojoClient::BlockSuspend(const base::UnguessableToken& token,
-                                          const std::string& debug_info) {}
-
-void PowerManagerMojoClient::UnblockSuspend(
-    const base::UnguessableToken& token) {}
-
-void PowerManagerMojoClient::CreateArcTimers(
-    const std::string& tag,
-    std::vector<std::pair<clockid_t, base::ScopedFD>> arc_timer_requests,
-    DBusMethodCallback<std::vector<TimerId>> callback) {}
-
-void PowerManagerMojoClient::StartArcTimer(
-    TimerId timer_id,
-    base::TimeTicks absolute_expiration_time,
-    VoidDBusMethodCallback callback) {}
-
-void PowerManagerMojoClient::DeleteArcTimers(const std::string& tag,
-                                             VoidDBusMethodCallback callback) {}
-
-void PowerManagerMojoClient::DeferScreenDim() {}
-
-void PowerManagerMojoClient::PowerManagerBecameAvailable(bool available) {
-  service_available_ = available;
-  for (auto& observer : observers_)
-    observer.PowerManagerBecameAvailable(available);
-}
-
-void PowerManagerMojoClient::ScreenBrightnessChanged(
-    const power_manager::BacklightBrightnessChange& change) {
-  for (auto& observer : observers_)
-    observer.ScreenBrightnessChanged(change);
-}
-
-void PowerManagerMojoClient::KeyboardBrightnessChanged(
-    const power_manager::BacklightBrightnessChange& change) {
-  for (auto& observer : observers_)
-    observer.KeyboardBrightnessChanged(change);
-}
-
-void PowerManagerMojoClient::SuspendDone(base::TimeDelta sleep_duration) {
-  for (auto& observer : observers_)
-    observer.SuspendDone(sleep_duration);
-}
-
-void PowerManagerMojoClient::InitAfterInterfaceBound() {
-  DCHECK(controller_.is_bound());
-  power::mojom::PowerManagerObserverAssociatedPtrInfo ptr_info;
-  binding_.Bind(mojo::MakeRequest(&ptr_info));
-  controller_->SetObserver(std::move(ptr_info));
-}
-
-// static
-PowerManagerClient* PowerManagerMojoClient::Get() {
-  DCHECK_EQ(base::FeatureList::IsEnabled(chromeos::features::kMojoDBusRelay),
-            !!g_instance);
-  return g_instance ? g_instance : ::chromeos::PowerManagerClient::Get();
-}
-
-}  // namespace chromeos
diff --git a/chromeos/services/power/public/cpp/power_manager_mojo_client.h b/chromeos/services/power/public/cpp/power_manager_mojo_client.h
deleted file mode 100644
index f97f350a..0000000
--- a/chromeos/services/power/public/cpp/power_manager_mojo_client.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CLIENT_H_
-#define CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CLIENT_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-
-namespace chromeos {
-
-// PowerManagerMojoClient implements the PowerManagerClient interface (which is
-// shared with the D-Bus implementation) and forwards calls over mojo to
-// PowerManagerMojoController.
-class COMPONENT_EXPORT(CHROMEOS_POWER_MOJO_CLIENT) PowerManagerMojoClient
-    : public PowerManagerClient,
-      public power::mojom::PowerManagerObserver {
- public:
-  PowerManagerMojoClient();
-  ~PowerManagerMojoClient() override;
-
-  // PowerManagerClient:
-  void AddObserver(Observer* observer) override;
-  void RemoveObserver(Observer* observer) override;
-  bool HasObserver(const Observer* observer) const override;
-  void SetRenderProcessManagerDelegate(
-      base::WeakPtr<RenderProcessManagerDelegate> delegate) override;
-  void DecreaseScreenBrightness(bool allow_off) override;
-  void IncreaseScreenBrightness() override;
-  void SetScreenBrightness(
-      const power_manager::SetBacklightBrightnessRequest& request) override;
-  void GetScreenBrightnessPercent(DBusMethodCallback<double> callback) override;
-  void DecreaseKeyboardBrightness() override;
-  void IncreaseKeyboardBrightness() override;
-  void GetKeyboardBrightnessPercent(
-      DBusMethodCallback<double> callback) override;
-  const base::Optional<power_manager::PowerSupplyProperties>& GetLastStatus()
-      override;
-  void RequestStatusUpdate() override;
-  void RequestSuspend() override;
-  void RequestRestart(power_manager::RequestRestartReason reason,
-                      const std::string& description) override;
-  void RequestShutdown(power_manager::RequestShutdownReason reason,
-                       const std::string& description) override;
-  void NotifyUserActivity(power_manager::UserActivityType type) override;
-  void NotifyVideoActivity(bool is_fullscreen) override;
-  void NotifyWakeNotification() override;
-  void SetPolicy(const power_manager::PowerManagementPolicy& policy) override;
-  void SetIsProjecting(bool is_projecting) override;
-  void SetPowerSource(const std::string& id) override;
-  void SetBacklightsForcedOff(bool forced_off) override;
-  void GetBacklightsForcedOff(DBusMethodCallback<bool> callback) override;
-  void GetSwitchStates(DBusMethodCallback<SwitchStates> callback) override;
-  void GetInactivityDelays(
-      DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback)
-      override;
-  void BlockSuspend(const base::UnguessableToken& token,
-                    const std::string& debug_info) override;
-  void UnblockSuspend(const base::UnguessableToken& token) override;
-  void CreateArcTimers(
-      const std::string& tag,
-      std::vector<std::pair<clockid_t, base::ScopedFD>> arc_timer_requests,
-      DBusMethodCallback<std::vector<TimerId>> callback) override;
-  void StartArcTimer(TimerId timer_id,
-                     base::TimeTicks absolute_expiration_time,
-                     VoidDBusMethodCallback callback) override;
-  void DeleteArcTimers(const std::string& tag,
-                       VoidDBusMethodCallback callback) override;
-  void DeferScreenDim() override;
-
-  // power::mojom::PowerManagerObserver:
-  void PowerManagerBecameAvailable(bool available) override;
-  void ScreenBrightnessChanged(
-      const power_manager::BacklightBrightnessChange& change) override;
-  void KeyboardBrightnessChanged(
-      const power_manager::BacklightBrightnessChange& change) override;
-  void SuspendDone(base::TimeDelta sleep_duration) override;
-
-  power::mojom::PowerManagerControllerPtr* interface_ptr() {
-    return &controller_;
-  }
-
-  // Init done after |controller_| is bound.
-  void InitAfterInterfaceBound();
-
-  // Returns the chromeos::PowerManagerClient implementation, which may either
-  // be backed by D-Bus or a fake (if mojo is not enabled), or a
-  // PowerManagerMojoClient. This only exists for the sake of SingleProcessMash,
-  // where a PowerManagerMojoClient and a PowerManagerClientImpl may coexist in
-  // the same process. Otherwise, PowerManagerClient::Get would be enough.
-  static ::chromeos::PowerManagerClient* Get();
-
- private:
-  power::mojom::PowerManagerControllerPtr controller_;
-  mojo::AssociatedBinding<power::mojom::PowerManagerObserver> binding_{this};
-
-  base::ObserverList<Observer>::Unchecked observers_;
-
-  // The last proto received via mojo; initially empty.
-  base::Optional<power_manager::PowerSupplyProperties> proto_;
-
-  base::Optional<bool> service_available_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerManagerMojoClient);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CLIENT_H_
diff --git a/chromeos/services/power/public/cpp/power_manager_mojo_controller.cc b/chromeos/services/power/public/cpp/power_manager_mojo_controller.cc
deleted file mode 100644
index 8be21bd..0000000
--- a/chromeos/services/power/public/cpp/power_manager_mojo_controller.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/services/power/public/cpp/power_manager_mojo_controller.h"
-
-#include "chromeos/dbus/power_manager/backlight.pb.h"
-
-namespace chromeos {
-
-PowerManagerMojoController::PowerManagerMojoController() = default;
-
-PowerManagerMojoController::~PowerManagerMojoController() {
-  if (PowerManagerClient::Get()->HasObserver(this))
-    PowerManagerClient::Get()->RemoveObserver(this);
-}
-
-void PowerManagerMojoController::BindRequest(
-    power::mojom::PowerManagerControllerRequest request) {
-  binding_set_.AddBinding(this, std::move(request));
-}
-
-void PowerManagerMojoController::SetObserver(
-    power::mojom::PowerManagerObserverAssociatedPtrInfo client) {
-  DCHECK(!client_.is_bound());
-  client_.Bind(std::move(client));
-
-  PowerManagerClient::Get()->AddObserver(this);
-}
-
-void PowerManagerMojoController::SetScreenBrightness(
-    const power_manager::SetBacklightBrightnessRequest& request) {
-  PowerManagerClient::Get()->SetScreenBrightness(request);
-}
-
-void PowerManagerMojoController::GetScreenBrightnessPercent(
-    GetScreenBrightnessPercentCallback callback) {
-  // This extra thunk is only necessary to convert between
-  // power::mojom::BrightnessPtr and base::Optional<double>.
-  PowerManagerClient::Get()->GetScreenBrightnessPercent(base::BindOnce(
-      [](GetScreenBrightnessPercentCallback callback,
-         base::Optional<double> value) {
-        if (value)
-          std::move(callback).Run(power::mojom::Brightness::New(*value));
-        else
-          std::move(callback).Run({});
-      },
-      std::move(callback)));
-}
-
-void PowerManagerMojoController::RequestRestart(
-    power_manager::RequestRestartReason reason,
-    const std::string& description) {
-  PowerManagerClient::Get()->RequestRestart(reason, description);
-}
-
-void PowerManagerMojoController::PowerManagerBecameAvailable(bool available) {
-  client_->PowerManagerBecameAvailable(available);
-}
-
-void PowerManagerMojoController::ScreenBrightnessChanged(
-    const power_manager::BacklightBrightnessChange& change) {
-  client_->ScreenBrightnessChanged(change);
-}
-
-void PowerManagerMojoController::KeyboardBrightnessChanged(
-    const power_manager::BacklightBrightnessChange& change) {
-  client_->KeyboardBrightnessChanged(change);
-}
-
-void PowerManagerMojoController::SuspendDone(
-    const base::TimeDelta& sleep_duration) {
-  client_->SuspendDone(sleep_duration);
-}
-
-}  // namespace chromeos
diff --git a/chromeos/services/power/public/cpp/power_manager_mojo_controller.h b/chromeos/services/power/public/cpp/power_manager_mojo_controller.h
deleted file mode 100644
index b770bae..0000000
--- a/chromeos/services/power/public/cpp/power_manager_mojo_controller.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CONTROLLER_H_
-#define CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CONTROLLER_H_
-
-#include "base/macros.h"
-#include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-
-namespace chromeos {
-
-// PowerManagerMojoController simply passes incoming mojo messages through to
-// the D-Bus-backed (or fake) PowerManagerClient. It informs |client_| of
-// changes by passing along PowerManagerClient::Observer notifications.
-class COMPONENT_EXPORT(CHROMEOS_POWER_MOJO_CONTROLLER)
-    PowerManagerMojoController : public power::mojom::PowerManagerController,
-                                 public PowerManagerClient::Observer {
- public:
-  PowerManagerMojoController();
-  ~PowerManagerMojoController() override;
-
-  void BindRequest(power::mojom::PowerManagerControllerRequest request);
-
-  // mojom::PowerManagerMojoController:
-  void SetObserver(
-      power::mojom::PowerManagerObserverAssociatedPtrInfo client) override;
-  void SetScreenBrightness(
-      const power_manager::SetBacklightBrightnessRequest& request) override;
-  void GetScreenBrightnessPercent(
-      GetScreenBrightnessPercentCallback callback) override;
-  void RequestRestart(power_manager::RequestRestartReason reason,
-                      const std::string& description) override;
-
-  // PowerManagerClient::Observer:
-  void PowerManagerBecameAvailable(bool available) override;
-  void ScreenBrightnessChanged(
-      const power_manager::BacklightBrightnessChange& change) override;
-  void KeyboardBrightnessChanged(
-      const power_manager::BacklightBrightnessChange& change) override;
-  void SuspendDone(const base::TimeDelta& sleep_duration) override;
-
- private:
-  mojo::BindingSet<power::mojom::PowerManagerController> binding_set_;
-  power::mojom::PowerManagerObserverAssociatedPtr client_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerManagerMojoController);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROMEOS_SERVICES_POWER_PUBLIC_CPP_POWER_MANAGER_MOJO_CONTROLLER_H_
diff --git a/chromeos/services/power/public/cpp/power_manager_mojo_controller_unittest.cc b/chromeos/services/power/public/cpp/power_manager_mojo_controller_unittest.cc
deleted file mode 100644
index 1a5d1b6..0000000
--- a/chromeos/services/power/public/cpp/power_manager_mojo_controller_unittest.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/services/power/public/cpp/power_manager_mojo_controller.h"
-
-#include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/services/power/public/cpp/power_manager_mojo_client.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace chromeos {
-
-namespace {
-
-class TestObserver : public PowerManagerClient::Observer {
- public:
-  TestObserver() = default;
-  ~TestObserver() override = default;
-
-  void WaitForChange() { run_loop_.Run(); }
-
-  // PowerManagerClient::Observer:
-  void ScreenBrightnessChanged(
-      const power_manager::BacklightBrightnessChange& change) override {
-    last_change_ = change;
-    run_loop_.Quit();
-  }
-
-  const base::Optional<power_manager::BacklightBrightnessChange>&
-  last_change() {
-    return last_change_;
-  }
-
- private:
-  base::Optional<power_manager::BacklightBrightnessChange> last_change_;
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestObserver);
-};
-
-class PowerManagerMojoTest : public testing::Test {
- public:
-  PowerManagerMojoTest() {
-    scoped_feature_list_.InitAndEnableFeature(features::kMojoDBusRelay);
-    PowerManagerClient::InitializeFake();
-
-    controller_ = std::make_unique<PowerManagerMojoController>();
-    client_ = std::make_unique<PowerManagerMojoClient>();
-
-    power::mojom::PowerManagerObserverAssociatedPtr observer_ptr;
-    binding_ = std::make_unique<
-        mojo::AssociatedBinding<power::mojom::PowerManagerObserver>>(
-        client_.get(),
-        mojo::MakeRequestAssociatedWithDedicatedPipe(&observer_ptr));
-    controller_->SetObserver(observer_ptr.PassInterface());
-    base::RunLoop().RunUntilIdle();
-  }
-
-  ~PowerManagerMojoTest() override {
-    binding_.reset();
-    client_.reset();
-    controller_.reset();
-    PowerManagerClient::Shutdown();
-  }
-
- protected:
-  std::unique_ptr<PowerManagerMojoController> controller_;
-  std::unique_ptr<PowerManagerMojoClient> client_;
-
- private:
-  std::unique_ptr<mojo::AssociatedBinding<power::mojom::PowerManagerObserver>>
-      binding_;
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerManagerMojoTest);
-};
-
-TEST_F(PowerManagerMojoTest, SetScreenBrightness) {
-  TestObserver observer;
-  client_->AddObserver(&observer);
-
-  // TODO(estade): also verify |cause|.
-  power_manager::SetBacklightBrightnessRequest brightness_request;
-  brightness_request.set_percent(0.6);
-  chromeos::FakePowerManagerClient::Get()->SetScreenBrightness(
-      brightness_request);
-  observer.WaitForChange();
-  EXPECT_EQ(0.6, observer.last_change()->percent());
-
-  // TODO(estade): add SetScreenBrightness to PowerManagerMojoController and
-  // test it here.
-}
-
-}  // namespace
-
-}  // namespace chromeos
diff --git a/chromeos/services/power/public/mojom/BUILD.gn b/chromeos/services/power/public/mojom/BUILD.gn
deleted file mode 100644
index 199d325..0000000
--- a/chromeos/services/power/public/mojom/BUILD.gn
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("mojom") {
-  disable_variants = true
-
-  sources = [
-    "power_manager.mojom",
-  ]
-
-  public_deps = [
-    "//mojo/public/mojom/base",
-    "//services/content/public/mojom",
-    "//services/preferences/public/mojom",
-    "//ui/base/mojo",
-  ]
-
-  component_macro_prefix = "CHROMEOS_POWER_MOJO"
-  component_output_prefix = "chromeos_power_mojo_mojom"
-}
diff --git a/chromeos/services/power/public/mojom/OWNERS b/chromeos/services/power/public/mojom/OWNERS
deleted file mode 100644
index b15e65d..0000000
--- a/chromeos/services/power/public/mojom/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-per-file mojom_traits.*=set noparent
-per-file mojom_traits.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/services/power/public/mojom/mojom_traits.cc b/chromeos/services/power/public/mojom/mojom_traits.cc
deleted file mode 100644
index da5f2ca..0000000
--- a/chromeos/services/power/public/mojom/mojom_traits.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/services/power/public/mojom/mojom_traits.h"
-
-namespace mojo {
-
-using chromeos::power::mojom::BacklightBrightnessChangeCause;
-using chromeos::power::mojom::RequestRestartReason;
-using chromeos::power::mojom::SetBacklightBrightnessRequestCause;
-using chromeos::power::mojom::SetBacklightBrightnessRequestTransition;
-
-// static
-SetBacklightBrightnessRequestTransition
-EnumTraits<SetBacklightBrightnessRequestTransition,
-           power_manager::SetBacklightBrightnessRequest_Transition>::
-    ToMojom(
-        power_manager::SetBacklightBrightnessRequest_Transition transition) {
-  switch (transition) {
-    case power_manager::SetBacklightBrightnessRequest_Transition_GRADUAL:
-      return SetBacklightBrightnessRequestTransition::kGradual;
-    case power_manager::SetBacklightBrightnessRequest_Transition_INSTANT:
-      return SetBacklightBrightnessRequestTransition::kInstant;
-  }
-  NOTREACHED();
-  return SetBacklightBrightnessRequestTransition::kGradual;
-}
-
-// static
-bool EnumTraits<SetBacklightBrightnessRequestTransition,
-                power_manager::SetBacklightBrightnessRequest_Transition>::
-    FromMojom(SetBacklightBrightnessRequestTransition transition,
-              power_manager::SetBacklightBrightnessRequest_Transition* out) {
-  switch (transition) {
-    case SetBacklightBrightnessRequestTransition::kGradual:
-      *out = power_manager::SetBacklightBrightnessRequest_Transition_GRADUAL;
-      return true;
-    case SetBacklightBrightnessRequestTransition::kInstant:
-      *out = power_manager::SetBacklightBrightnessRequest_Transition_INSTANT;
-      return true;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-// static
-SetBacklightBrightnessRequestCause
-EnumTraits<SetBacklightBrightnessRequestCause,
-           power_manager::SetBacklightBrightnessRequest_Cause>::
-    ToMojom(power_manager::SetBacklightBrightnessRequest_Cause cause) {
-  switch (cause) {
-    case power_manager::SetBacklightBrightnessRequest_Cause_USER_REQUEST:
-      return SetBacklightBrightnessRequestCause::kUserRequest;
-    case power_manager::SetBacklightBrightnessRequest_Cause_MODEL:
-      return SetBacklightBrightnessRequestCause::kModel;
-  }
-  NOTREACHED();
-  return SetBacklightBrightnessRequestCause::kUserRequest;
-}
-
-// static
-bool EnumTraits<SetBacklightBrightnessRequestCause,
-                power_manager::SetBacklightBrightnessRequest_Cause>::
-    FromMojom(SetBacklightBrightnessRequestCause cause,
-              power_manager::SetBacklightBrightnessRequest_Cause* out) {
-  switch (cause) {
-    case SetBacklightBrightnessRequestCause::kUserRequest:
-      *out = power_manager::SetBacklightBrightnessRequest_Cause_USER_REQUEST;
-      return true;
-    case SetBacklightBrightnessRequestCause::kModel:
-      *out = power_manager::SetBacklightBrightnessRequest_Cause_MODEL;
-      return true;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-// static
-bool StructTraits<chromeos::power::mojom::SetBacklightBrightnessRequestDataView,
-                  power_manager::SetBacklightBrightnessRequest>::
-    Read(chromeos::power::mojom::SetBacklightBrightnessRequestDataView data,
-         power_manager::SetBacklightBrightnessRequest* out) {
-  if (data.percent() < 0. || data.percent() > 100.)
-    return false;
-
-  out->set_percent(data.percent());
-
-  power_manager::SetBacklightBrightnessRequest_Transition transition;
-  power_manager::SetBacklightBrightnessRequest_Cause cause;
-  if (!data.ReadTransition(&transition) || !data.ReadCause(&cause))
-    return false;
-
-  out->set_transition(transition);
-  out->set_cause(cause);
-  return true;
-}
-
-// static
-BacklightBrightnessChangeCause
-EnumTraits<BacklightBrightnessChangeCause,
-           power_manager::BacklightBrightnessChange_Cause>::
-    ToMojom(power_manager::BacklightBrightnessChange_Cause cause) {
-  switch (cause) {
-    case power_manager::BacklightBrightnessChange_Cause_USER_REQUEST:
-      return BacklightBrightnessChangeCause::kUserRequest;
-    case power_manager::BacklightBrightnessChange_Cause_USER_ACTIVITY:
-      return BacklightBrightnessChangeCause::kUserActivity;
-    case power_manager::BacklightBrightnessChange_Cause_USER_INACTIVITY:
-      return BacklightBrightnessChangeCause::kUserInactivity;
-    case power_manager::BacklightBrightnessChange_Cause_AMBIENT_LIGHT_CHANGED:
-      return BacklightBrightnessChangeCause::kAmbientLightChanged;
-    case power_manager::
-        BacklightBrightnessChange_Cause_EXTERNAL_POWER_CONNECTED:
-      return BacklightBrightnessChangeCause::kExternalPowerConnected;
-    case power_manager::
-        BacklightBrightnessChange_Cause_EXTERNAL_POWER_DISCONNECTED:
-      return BacklightBrightnessChangeCause::kExternalPowerDisconnected;
-    case power_manager::BacklightBrightnessChange_Cause_FORCED_OFF:
-      return BacklightBrightnessChangeCause::kForcedOff;
-    case power_manager::BacklightBrightnessChange_Cause_NO_LONGER_FORCED_OFF:
-      return BacklightBrightnessChangeCause::kNoLongerForcedOff;
-    case power_manager::BacklightBrightnessChange_Cause_OTHER:
-      return BacklightBrightnessChangeCause::kOther;
-    case power_manager::BacklightBrightnessChange_Cause_MODEL:
-      return BacklightBrightnessChangeCause::kModel;
-    case power_manager::BacklightBrightnessChange_Cause_WAKE_NOTIFICATION:
-      return BacklightBrightnessChangeCause::kWakeNotification;
-  }
-  NOTREACHED();
-  return BacklightBrightnessChangeCause::kUserRequest;
-}
-
-// static
-bool EnumTraits<BacklightBrightnessChangeCause,
-                power_manager::BacklightBrightnessChange_Cause>::
-    FromMojom(BacklightBrightnessChangeCause cause,
-              power_manager::BacklightBrightnessChange_Cause* out) {
-  switch (cause) {
-    case BacklightBrightnessChangeCause::kUserRequest:
-      *out = power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
-      return true;
-    case BacklightBrightnessChangeCause::kUserActivity:
-      *out = power_manager::BacklightBrightnessChange_Cause_USER_ACTIVITY;
-      return true;
-    case BacklightBrightnessChangeCause::kUserInactivity:
-      *out = power_manager::BacklightBrightnessChange_Cause_USER_INACTIVITY;
-      return true;
-    case BacklightBrightnessChangeCause::kAmbientLightChanged:
-      *out =
-          power_manager::BacklightBrightnessChange_Cause_AMBIENT_LIGHT_CHANGED;
-      return true;
-    case BacklightBrightnessChangeCause::kExternalPowerConnected:
-      *out = power_manager::
-          BacklightBrightnessChange_Cause_EXTERNAL_POWER_CONNECTED;
-      return true;
-    case BacklightBrightnessChangeCause::kExternalPowerDisconnected:
-      *out = power_manager::
-          BacklightBrightnessChange_Cause_EXTERNAL_POWER_DISCONNECTED;
-      return true;
-    case BacklightBrightnessChangeCause::kForcedOff:
-      *out = power_manager::BacklightBrightnessChange_Cause_FORCED_OFF;
-      return true;
-    case BacklightBrightnessChangeCause::kNoLongerForcedOff:
-      *out =
-          power_manager::BacklightBrightnessChange_Cause_NO_LONGER_FORCED_OFF;
-      return true;
-    case BacklightBrightnessChangeCause::kOther:
-      *out = power_manager::BacklightBrightnessChange_Cause_OTHER;
-      return true;
-    case BacklightBrightnessChangeCause::kModel:
-      *out = power_manager::BacklightBrightnessChange_Cause_MODEL;
-      return true;
-    case BacklightBrightnessChangeCause::kWakeNotification:
-      *out = power_manager::BacklightBrightnessChange_Cause_WAKE_NOTIFICATION;
-      return true;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-// static
-bool StructTraits<chromeos::power::mojom::BacklightBrightnessChangeDataView,
-                  power_manager::BacklightBrightnessChange>::
-    Read(chromeos::power::mojom::BacklightBrightnessChangeDataView data,
-         power_manager::BacklightBrightnessChange* out) {
-  if (data.percent() < 0. || data.percent() > 100.)
-    return false;
-
-  out->set_percent(data.percent());
-
-  power_manager::BacklightBrightnessChange_Cause cause;
-  if (!data.ReadCause(&cause))
-    return false;
-
-  out->set_cause(cause);
-  return true;
-}
-
-// static
-RequestRestartReason
-EnumTraits<RequestRestartReason, power_manager::RequestRestartReason>::ToMojom(
-    power_manager::RequestRestartReason reason) {
-  switch (reason) {
-    case power_manager::REQUEST_RESTART_FOR_USER:
-      return RequestRestartReason::kForUser;
-    case power_manager::REQUEST_RESTART_FOR_UPDATE:
-      return RequestRestartReason::kForUpdate;
-    case power_manager::REQUEST_RESTART_OTHER:
-      return RequestRestartReason::kOther;
-  }
-}
-
-// static
-bool EnumTraits<RequestRestartReason, power_manager::RequestRestartReason>::
-    FromMojom(chromeos::power::mojom::RequestRestartReason reason,
-              power_manager::RequestRestartReason* out) {
-  switch (reason) {
-    case RequestRestartReason::kForUser:
-      *out = power_manager::REQUEST_RESTART_FOR_USER;
-      return true;
-    case RequestRestartReason::kForUpdate:
-      *out = power_manager::REQUEST_RESTART_FOR_UPDATE;
-      return true;
-    case RequestRestartReason::kOther:
-      *out = power_manager::REQUEST_RESTART_OTHER;
-      return true;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-}  // namespace mojo
diff --git a/chromeos/services/power/public/mojom/mojom_traits.h b/chromeos/services/power/public/mojom/mojom_traits.h
deleted file mode 100644
index 47c205f..0000000
--- a/chromeos/services/power/public/mojom/mojom_traits.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_SERVICES_POWER_PUBLIC_MOJOM_MOJOM_TRAITS_H_
-#define CHROMEOS_SERVICES_POWER_PUBLIC_MOJOM_MOJOM_TRAITS_H_
-
-#include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom-shared.h"
-#include "chromeos/services/power/public/mojom/power_manager.mojom.h"
-#include "mojo/public/cpp/bindings/enum_traits.h"
-#include "third_party/cros_system_api/dbus/power_manager/dbus-constants.h"
-
-namespace mojo {
-
-template <>
-struct EnumTraits<
-    chromeos::power::mojom::SetBacklightBrightnessRequestTransition,
-    power_manager::SetBacklightBrightnessRequest_Transition> {
-  static chromeos::power::mojom::SetBacklightBrightnessRequestTransition
-  ToMojom(power_manager::SetBacklightBrightnessRequest_Transition cause);
-
-  static bool FromMojom(
-      chromeos::power::mojom::SetBacklightBrightnessRequestTransition cause,
-      power_manager::SetBacklightBrightnessRequest_Transition* out);
-};
-
-template <>
-struct EnumTraits<chromeos::power::mojom::SetBacklightBrightnessRequestCause,
-                  power_manager::SetBacklightBrightnessRequest_Cause> {
-  static chromeos::power::mojom::SetBacklightBrightnessRequestCause ToMojom(
-      power_manager::SetBacklightBrightnessRequest_Cause cause);
-
-  static bool FromMojom(
-      chromeos::power::mojom::SetBacklightBrightnessRequestCause cause,
-      power_manager::SetBacklightBrightnessRequest_Cause* out);
-};
-
-template <>
-struct StructTraits<
-    chromeos::power::mojom::SetBacklightBrightnessRequestDataView,
-    power_manager::SetBacklightBrightnessRequest> {
-  static double percent(
-      const power_manager::SetBacklightBrightnessRequest& request) {
-    return request.percent();
-  }
-  static power_manager::SetBacklightBrightnessRequest_Transition transition(
-      const power_manager::SetBacklightBrightnessRequest& request) {
-    return request.transition();
-  }
-  static power_manager::SetBacklightBrightnessRequest_Cause cause(
-      const power_manager::SetBacklightBrightnessRequest& request) {
-    return request.cause();
-  }
-  static bool Read(
-      chromeos::power::mojom::SetBacklightBrightnessRequestDataView data,
-      power_manager::SetBacklightBrightnessRequest* out);
-};
-
-template <>
-struct EnumTraits<chromeos::power::mojom::BacklightBrightnessChangeCause,
-                  power_manager::BacklightBrightnessChange_Cause> {
-  static chromeos::power::mojom::BacklightBrightnessChangeCause ToMojom(
-      power_manager::BacklightBrightnessChange_Cause cause);
-
-  static bool FromMojom(
-      chromeos::power::mojom::BacklightBrightnessChangeCause cause,
-      power_manager::BacklightBrightnessChange_Cause* out);
-};
-
-template <>
-struct StructTraits<chromeos::power::mojom::BacklightBrightnessChangeDataView,
-                    power_manager::BacklightBrightnessChange> {
-  static double percent(
-      const power_manager::BacklightBrightnessChange& change) {
-    return change.percent();
-  }
-  static power_manager::BacklightBrightnessChange_Cause cause(
-      const power_manager::BacklightBrightnessChange& change) {
-    return change.cause();
-  }
-  static bool Read(
-      chromeos::power::mojom::BacklightBrightnessChangeDataView data,
-      power_manager::BacklightBrightnessChange* out);
-};
-
-template <>
-struct EnumTraits<chromeos::power::mojom::RequestRestartReason,
-                  power_manager::RequestRestartReason> {
-  static chromeos::power::mojom::RequestRestartReason ToMojom(
-      power_manager::RequestRestartReason reason);
-
-  static bool FromMojom(chromeos::power::mojom::RequestRestartReason reason,
-                        power_manager::RequestRestartReason* out);
-};
-
-}  // namespace mojo
-
-#endif  // CHROMEOS_SERVICES_POWER_PUBLIC_MOJOM_MOJOM_TRAITS_H_
diff --git a/chromeos/services/power/public/mojom/power_manager.mojom b/chromeos/services/power/public/mojom/power_manager.mojom
deleted file mode 100644
index 9c4d4ab..0000000
--- a/chromeos/services/power/public/mojom/power_manager.mojom
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module chromeos.power.mojom;
-
-import "mojo/public/mojom/base/time.mojom";
-
-enum SetBacklightBrightnessRequestTransition {
-  kGradual,
-  kInstant,
-};
-
-enum SetBacklightBrightnessRequestCause {
-  kUserRequest,
-  kModel,
-};
-
-struct SetBacklightBrightnessRequest {
-  // The brightness percent is in the range [0.0, 100.0].
-  double percent;
-  SetBacklightBrightnessRequestTransition transition;
-  SetBacklightBrightnessRequestCause cause;
-};
-
-// TODO(https://crbug.com/657632): This struct wrapper exists to allow the value
-// to be null.
-struct Brightness {
-  // Brightness percent, in the range [0.0, 100.0].
-  double value;
-};
-
-// Correlates to power_manager::BacklightBrightnessChange_Cause
-enum BacklightBrightnessChangeCause {
-  kUserRequest,
-  kUserActivity,
-  kUserInactivity,
-  kAmbientLightChanged,
-  kExternalPowerConnected,
-  kExternalPowerDisconnected,
-  kForcedOff,
-  kNoLongerForcedOff,
-  kOther,
-  kModel,
-  kWakeNotification,
-};
-
-// Correlates to power_manager::BacklightBrightnessChange
-struct BacklightBrightnessChange {
-  // The brightness percent is in the range [0.0, 100.0].
-  double percent;
-  BacklightBrightnessChangeCause cause;
-};
-
-enum RequestRestartReason {
-  kForUser,
-  kForUpdate,
-  kOther,
-};
-
-// The interface for handling out-of-process calls that query or adjust power
-// related state. The implementation relays calls to the D-Bus client, which
-// uses D-Bus to communicate with the Power Manager daemon. In Mash, this lives
-// in the Ash process.
-interface PowerManagerController {
-  SetObserver(associated PowerManagerObserver observer);
-
-  // All following methods and their semantics are copied from the
-  // PowerManagerClient interface. Refer to that for documentation.
-  SetScreenBrightness(SetBacklightBrightnessRequest request);
-  GetScreenBrightnessPercent() => (Brightness? brightness);
-  RequestRestart(RequestRestartReason reason, string description);
-};
-
-// An interface for observing changes to power state. The changes are dispatched
-// over mojo from PowerManagerController.
-interface PowerManagerObserver {
-  // All following methods and their semantics are copied from the
-  // PowerManagerClient::Observer interface. Refer to that for documentation.
-  PowerManagerBecameAvailable(bool available);
-  ScreenBrightnessChanged(BacklightBrightnessChange change);
-  KeyboardBrightnessChanged(BacklightBrightnessChange change);
-  SuspendDone(mojo_base.mojom.TimeDelta sleep_duration);
-};
diff --git a/chromeos/services/power/public/mojom/power_types.typemap b/chromeos/services/power/public/mojom/power_types.typemap
deleted file mode 100644
index d9d3599e..0000000
--- a/chromeos/services/power/public/mojom/power_types.typemap
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//chromeos/services/power/public/mojom/power_manager.mojom"
-public_headers = [
-  "chromeos/dbus/power_manager/backlight.pb.h",
-  "third_party/cros_system_api/dbus/power_manager/dbus-constants.h",
-]
-traits_headers = [ "//chromeos/services/power/public/mojom/mojom_traits.h" ]
-sources = [
-  "//chromeos/services/power/public/mojom/mojom_traits.cc",
-]
-deps = [
-  "//chromeos/dbus/power:power_manager_proto",
-]
-
-type_mappings = [
-  "chromeos.power.mojom.BacklightBrightnessChange=power_manager::BacklightBrightnessChange",
-  "chromeos.power.mojom.BacklightBrightnessChangeCause=power_manager::BacklightBrightnessChange_Cause",
-  "chromeos.power.mojom.RequestRestartReason=power_manager::RequestRestartReason",
-  "chromeos.power.mojom.SetBacklightBrightnessRequest=power_manager::SetBacklightBrightnessRequest",
-  "chromeos.power.mojom.SetBacklightBrightnessRequestCause=power_manager::SetBacklightBrightnessRequest_Cause",
-  "chromeos.power.mojom.SetBacklightBrightnessRequestTransition=power_manager::SetBacklightBrightnessRequest_Transition",
-]
diff --git a/chromeos/services/power/public/mojom/typemaps.gni b/chromeos/services/power/public/mojom/typemaps.gni
deleted file mode 100644
index 7296993..0000000
--- a/chromeos/services/power/public/mojom/typemaps.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-typemaps = [ "//chromeos/services/power/public/mojom/power_types.typemap" ]
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc
index a06cc25..ae3c1dcb 100644
--- a/components/arc/ime/arc_ime_service.cc
+++ b/components/arc/ime/arc_ime_service.cc
@@ -520,6 +520,10 @@
   return is_personalized_learning_allowed_;
 }
 
+void ArcImeService::SetCompositionFromExistingText(
+    const gfx::Range& range,
+    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+
 // static
 void ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(
     base::Optional<double> scale_factor) {
diff --git a/components/arc/ime/arc_ime_service.h b/components/arc/ime/arc_ime_service.h
index 23297e1..b3a3cba 100644
--- a/components/arc/ime/arc_ime_service.h
+++ b/components/arc/ime/arc_ime_service.h
@@ -141,6 +141,9 @@
   }
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
+  void SetCompositionFromExistingText(
+      const gfx::Range& range,
+      const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
 
   // Normally, the default device scale factor is used to convert from DPI to
   // physical pixels. This method provides a way to override it for testing.
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index e0ba8bb3..d861b6d 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -24,18 +24,17 @@
 const base::Feature kAutocompleteRetentionPolicyEnabled{
     "AutocompleteRetentionPolicyEnabled", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Controls whether autofill activates on non-HTTP(S) pages. Useful for
-// automated with data URLS in cases where it's too difficult to use the
-// embedded test server. Generally avoid using.
-//
-const base::Feature kAutofillAllowNonHttpActivation{
-    "AutofillAllowNonHttpActivation", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether the AddressNormalizer is supplied. If available, it may be
 // used to normalize address and will incur fetching rules from the server.
 const base::Feature kAutofillAddressNormalizer{
     "AutofillAddressNormalizer", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Controls whether autofill activates on non-HTTP(S) pages. Useful for
+// automated with data URLS in cases where it's too difficult to use the
+// embedded test server. Generally avoid using.
+const base::Feature kAutofillAllowNonHttpActivation{
+    "AutofillAllowNonHttpActivation", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kAutofillAlwaysFillAddresses{
     "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -60,11 +59,6 @@
 const base::Feature kAutofillEnableAccountWalletStorage{
     "AutofillEnableAccountWalletStorage", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether autofill rejects using non-verified company names that are
-// in the format of a birthyear.
-const base::Feature kAutofillRejectCompanyBirthyear{
-    "AutofillRejectCompanyBirthyearName", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether we show also upload prompts when we are using the
 // account-based storage for server cards.
 const base::Feature kAutofillEnableAccountWalletStorageUpload{
@@ -75,14 +69,6 @@
 const base::Feature kAutofillEnableCompanyName{
     "AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kAutofillOffNoServerData{"AutofillOffNoServerData",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
-
-// When enabled, autofill server will override field types with rater
-// consensus data before returning to client.
-const base::Feature kAutofillOverrideWithRaterConsensus{
-    "AutofillOverrideWithRaterConsensus", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether or not a minimum number of fields is required before
 // heuristic field type prediction is run for a form.
 const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics{
@@ -122,14 +108,30 @@
 const base::Feature kAutofillMetadataUploads{"AutofillMetadataUploads",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kAutofillOffNoServerData{"AutofillOffNoServerData",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
+// When enabled, autofill server will override field types with rater
+// consensus data before returning to client.
+const base::Feature kAutofillOverrideWithRaterConsensus{
+    "AutofillOverrideWithRaterConsensus", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kAutofillPreferServerNamePredictions{
     "AutofillPreferServerNamePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kAutofillProfileClientValidation{
+    "AutofillProfileClientValidation", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls whether Autofill uses server-side validation to ensure that fields
 // with invalid data are not suggested.
 const base::Feature kAutofillProfileServerValidation{
     "AutofillProfileServerValidation", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Controls whether autofill rejects using non-verified company names that are
+// in the format of a birthyear.
+const base::Feature kAutofillRejectCompanyBirthyear{
+    "AutofillRejectCompanyBirthyearName", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls whether or not a group of fields not enclosed in a form can be
 // considered a form. If this is enabled, unowned fields will only constitute
 // a form if there are signals to suggest that this might a checkout page.
@@ -173,12 +175,6 @@
     "AutofillShowAutocompleteConsoleWarnings",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether suggestions' labels use the improved label disambiguation
-// format.
-const base::Feature kAutofillUseImprovedLabelDisambiguation{
-    "AutofillUseImprovedLabelDisambiguation",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls attaching the autofill type predictions to their respective
 // element in the DOM.
 const base::Feature kAutofillShowTypePredictions{
@@ -189,9 +185,6 @@
 const base::Feature kAutofillSkipComparingInferredLabels{
     "AutofillSkipComparingInferredLabels", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kAutofillProfileClientValidation{
-    "AutofillProfileClientValidation", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether Autofill should search prefixes of all words/tokens when
 // filtering profiles, or only on prefixes of the whole string.
 const base::Feature kAutofillTokenPrefixMatching{
@@ -204,6 +197,12 @@
 const base::Feature kAutofillUseApi{"AutofillUseApi",
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Controls whether suggestions' labels use the improved label disambiguation
+// format.
+const base::Feature kAutofillUseImprovedLabelDisambiguation{
+    "AutofillUseImprovedLabelDisambiguation",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls whether password generation is offered automatically on fields
 // perceived as eligible for generation.
 const base::Feature kAutomaticPasswordGeneration = {
@@ -220,6 +219,11 @@
     "AutofillRefreshStyleAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // OS_ANDROID
 
+#if defined(OS_ANDROID) || defined(OS_IOS)
+const base::Feature kAutofillUseMobileLabelDisambiguation{
+    "AutofillUseMobileLabelDisambiguation", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif  // defined(OS_ANDROID) || defined(OS_IOS)
+
 bool IsAutofillCreditCardAssistEnabled() {
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   return false;
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 6489b514..f8a1e66 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -21,10 +21,9 @@
 namespace features {
 
 // All features in alphabetical order.
-extern const base::Feature kAutofillProfileServerValidation;
 extern const base::Feature kAutocompleteRetentionPolicyEnabled;
-extern const base::Feature kAutofillAllowNonHttpActivation;
 extern const base::Feature kAutofillAddressNormalizer;
+extern const base::Feature kAutofillAllowNonHttpActivation;
 extern const base::Feature kAutofillAlwaysFillAddresses;
 extern const base::Feature kAutofillAlwaysShowServerCardsInSyncTransport;
 extern const base::Feature kAutofillCacheQueryResponses;
@@ -33,7 +32,6 @@
 extern const base::Feature kAutofillEnableAccountWalletStorage;
 extern const base::Feature kAutofillEnableAccountWalletStorageUpload;
 extern const base::Feature kAutofillEnableCompanyName;
-extern const base::Feature kAutofillRejectCompanyBirthyear;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForUpload;
@@ -45,7 +43,9 @@
 extern const base::Feature kAutofillOffNoServerData;
 extern const base::Feature kAutofillOverrideWithRaterConsensus;
 extern const base::Feature kAutofillPreferServerNamePredictions;
+extern const base::Feature kAutofillProfileClientValidation;
 extern const base::Feature kAutofillProfileServerValidation;
+extern const base::Feature kAutofillRejectCompanyBirthyear;
 extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
 extern const base::Feature kAutofillRichMetadataQueries;
 extern const base::Feature kAutofillSaveOnProbablySubmitted;
@@ -53,13 +53,12 @@
 extern const base::Feature kAutofillSettingsCardTypeSplit;
 extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms;
 extern const base::Feature kAutofillShowAutocompleteConsoleWarnings;
-extern const base::Feature kAutofillUseImprovedLabelDisambiguation;
 extern const base::Feature kAutofillShowTypePredictions;
 extern const base::Feature kAutofillSkipComparingInferredLabels;
 extern const base::Feature kAutofillTokenPrefixMatching;
 extern const base::Feature kAutofillUploadThrottling;
 extern const base::Feature kAutofillUseApi;
-extern const base::Feature kAutofillProfileClientValidation;
+extern const base::Feature kAutofillUseImprovedLabelDisambiguation;
 extern const base::Feature kAutomaticPasswordGeneration;
 
 #if defined(OS_ANDROID)
@@ -67,6 +66,10 @@
 extern const base::Feature kAutofillRefreshStyleAndroid;
 #endif  // OS_ANDROID
 
+#if defined(OS_ANDROID) || defined(OS_IOS)
+extern const base::Feature kAutofillUseMobileLabelDisambiguation;
+#endif  // defined(OS_ANDROID) || defined(OS_IOS)
+
 // Returns whether the Autofill credit card assist infobar should be shown.
 bool IsAutofillCreditCardAssistEnabled();
 
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index 501fd258..f326fa7 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/c++/c++.gni")
 import("//build/config/ios/rules.gni")
 import("//build/config/mac/symbols.gni")
 import("//build/mac/tweak_info_plist.gni")
@@ -169,6 +170,7 @@
   public_deps = [
     "//components/grpc_support",
   ]
+
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
@@ -180,6 +182,16 @@
   deps = [
     ":cronet_static",
   ]
+
+  if (use_custom_libcxx) {
+    deps += [
+      # Add shared_library_deps to include custom libc++ into dependencies.
+      # They are by default only added to executable(), loadable_module(), and
+      # shared_library() targets, but cronet_static_complete library needs it as well to
+      # avoid linking with different versions of libc++.
+      "//build/config:shared_library_deps",
+    ]
+  }
 }
 
 # A static library which contains cronet and all dependendencies hidden inside.
@@ -207,6 +219,9 @@
     "--current_cpu",
     current_cpu,
   ]
+  if (use_custom_libcxx) {
+    args += [ "--use_custom_libcxx" ]
+  }
 
   if (!use_system_xcode) {
     args += [
diff --git a/components/cronet/native/cronet.idl b/components/cronet/native/cronet.idl
index a74865a..95d5883 100644
--- a/components/cronet/native/cronet.idl
+++ b/components/cronet/native/cronet.idl
@@ -1339,14 +1339,20 @@
 
   /**
    * Time when sending HTTP request headers started.
+   *
+   * Will equal null if the request failed or was canceled before sending
+   * started.
    */
-  DateTime sending_start;
+  DateTime? sending_start;
 
   /**
    * Time when sending HTTP request body finished. (Sending request body
    * happens after sending request headers.)
+   *
+   * Will equal null if the request failed or was canceled before sending
+   * ended.
    */
-  DateTime sending_end;
+  DateTime? sending_end;
 
   /**
    * Time when first byte of HTTP/2 server push was received.  Will equal
@@ -1362,8 +1368,11 @@
 
   /**
    * Time when the end of the response headers was received.
+   *
+   * Will equal null if the request failed or was canceled before the response
+   * started.
    */
-  DateTime response_start;
+  DateTime? response_start;
 
   /**
    * Time when the request finished.
diff --git a/components/cronet/native/test/test_url_request_callback.cc b/components/cronet/native/test/test_url_request_callback.cc
index e770e81..b90f3607 100644
--- a/components/cronet/native/test/test_url_request_callback.cc
+++ b/components/cronet/native/test/test_url_request_callback.cc
@@ -209,6 +209,9 @@
 
   response_step_ = ON_CANCELED;
   on_canceled_called_ = true;
+  // It is possible |info| is nullptr if the response has not started.
+  if (info)
+    response_info_ = std::make_unique<UrlResponseInfo>(info);
   MaybeCancelOrPause(request);
   SignalDone();
 }
diff --git a/components/cronet/native/test/url_request_test.cc b/components/cronet/native/test/url_request_test.cc
index 043371b1..29b70b2 100644
--- a/components/cronet/native/test/url_request_test.cc
+++ b/components/cronet/native/test/url_request_test.cc
@@ -1125,11 +1125,11 @@
 
 TEST_P(UrlRequestTest, TestCancel) {
   TestCancel(TestUrlRequestCallback::CANCEL_SYNC,
-             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, false, false);
+             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, true, false);
   TestCancel(TestUrlRequestCallback::CANCEL_ASYNC,
-             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, false, false);
+             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, true, false);
   TestCancel(TestUrlRequestCallback::CANCEL_ASYNC_WITHOUT_PAUSE,
-             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, false, false);
+             TestUrlRequestCallback::ON_RECEIVED_REDIRECT, true, false);
 
   TestCancel(TestUrlRequestCallback::CANCEL_SYNC,
              TestUrlRequestCallback::ON_RESPONSE_STARTED, true, false);
diff --git a/components/cronet/native/url_request.cc b/components/cronet/native/url_request.cc
index 6237f025..a993f40 100644
--- a/components/cronet/native/url_request.cc
+++ b/components/cronet/native/url_request.cc
@@ -755,7 +755,7 @@
     int64_t received_bytes_count) {
   DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
   base::AutoLock lock(url_request_->lock_);
-  DCHECK_EQ(url_request_->metrics_, nullptr)
+  DCHECK_EQ(url_request_->metrics_.get(), nullptr)
       << "Metrics collection should only happen once.";
   auto metrics = std::make_unique<Cronet_Metrics>();
   using native_metrics_util::ConvertTime;
diff --git a/components/cronet/tools/hide_symbols.py b/components/cronet/tools/hide_symbols.py
index 9680cba..788c90ff 100755
--- a/components/cronet/tools/hide_symbols.py
+++ b/components/cronet/tools/hide_symbols.py
@@ -53,6 +53,9 @@
       help='The current processor architecture in the format of the target_cpu '
            'attribute in GN.')
   parser.add_option(
+      '--use_custom_libcxx', default=False, action='store_true',
+      help='Confirm there is a custom libc++ linked in.')
+  parser.add_option(
       '--developer_dir',
       help='Path to Xcode.')
   (options, args) = parser.parse_args()
@@ -120,6 +123,12 @@
   ]
   subprocess.check_call(command)
 
+  if options.use_custom_libcxx:
+    ret = os.system('xcrun nm -u "' + options.output_obj + '" | grep ___cxa_pure_virtual')
+    if ret == 0:
+      print "ERROR: Found undefined libc++ symbols, is libc++ indcluded in dependencies?"
+      exit(2)
+
 
 if __name__ == "__main__":
   main()
diff --git a/components/dom_distiller/standalone/content_extractor_browsertest.cc b/components/dom_distiller/standalone/content_extractor_browsertest.cc
index fbcdff4..4c45a46 100644
--- a/components/dom_distiller/standalone/content_extractor_browsertest.cc
+++ b/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -32,7 +32,7 @@
 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
 #include "components/dom_distiller/core/task_tracker.h"
-#include "components/keyed_service/core/test_simple_factory_key.h"
+#include "components/keyed_service/core/simple_key_map.h"
 #include "components/leveldb_proto/content/proto_database_provider_factory.h"
 #include "components/leveldb_proto/public/proto_database.h"
 #include "components/leveldb_proto/public/proto_database_provider.h"
@@ -128,7 +128,6 @@
 
 std::unique_ptr<DomDistillerService> CreateDomDistillerService(
     content::BrowserContext* context,
-    SimpleFactoryKey* key,
     sync_preferences::TestingPrefServiceSyncable* pref_service,
     const base::FilePath& db_path,
     const FileToUrlMap& file_to_url_map) {
@@ -138,6 +137,8 @@
   // Setting up PrefService for DistilledPagePrefs.
   DistilledPagePrefs::RegisterProfilePrefs(pref_service->registry());
 
+  SimpleFactoryKey* key =
+      SimpleKeyMap::GetInstance()->GetForBrowserContext(context);
   auto* db_provider =
       leveldb_proto::ProtoDatabaseProviderFactory::GetForKey(key);
 
@@ -357,14 +358,11 @@
         command_line, &file_to_url_map);
     content::BrowserContext* context =
         shell()->web_contents()->GetBrowserContext();
-    key_ = std::make_unique<TestSimpleFactoryKey>(context->GetPath(),
-                                                  context->IsOffTheRecord());
     pref_service_ =
         std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
 
-    service_ =
-        CreateDomDistillerService(context, key_.get(), pref_service_.get(),
-                                  db_dir_.GetPath(), file_to_url_map);
+    service_ = CreateDomDistillerService(context, pref_service_.get(),
+                                         db_dir_.GetPath(), file_to_url_map);
     PumpQueue();
   }
 
@@ -440,8 +438,6 @@
   size_t max_tasks_;
   size_t next_request_;
 
-  std::unique_ptr<SimpleFactoryKey> key_;
-
   base::ScopedTempDir db_dir_;
   std::unique_ptr<net::ScopedDefaultHostResolverProc>
       mock_host_resolver_override_;
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc
index 02fb7dcd..5f037bc 100644
--- a/components/exo/text_input.cc
+++ b/components/exo/text_input.cc
@@ -311,6 +311,10 @@
   return should_do_learning_;
 }
 
+void TextInput::SetCompositionFromExistingText(
+    const gfx::Range& range,
+    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+
 void TextInput::OnKeyboardVisibilityStateChanged(bool is_visible) {
   delegate_->OnVirtualKeyboardVisibilityChanged(is_visible);
 }
diff --git a/components/exo/text_input.h b/components/exo/text_input.h
index b00873a..9672953d 100644
--- a/components/exo/text_input.h
+++ b/components/exo/text_input.h
@@ -134,6 +134,9 @@
   void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
+  void SetCompositionFromExistingText(
+      const gfx::Range& range,
+      const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
 
   // keyboard::KeyboardControllerObserver:
   void OnKeyboardVisibilityStateChanged(bool is_visible) override;
diff --git a/components/gwp_asan/client/BUILD.gn b/components/gwp_asan/client/BUILD.gn
index 25b2b9c..79ae3aa3 100644
--- a/components/gwp_asan/client/BUILD.gn
+++ b/components/gwp_asan/client/BUILD.gn
@@ -13,6 +13,7 @@
     "guarded_page_allocator_win.cc",
     "gwp_asan.cc",
     "gwp_asan.h",
+    "sampling_state.h",
   ]
 
   if (is_posix) {
diff --git a/components/gwp_asan/client/sampling_allocator_shims.cc b/components/gwp_asan/client/sampling_allocator_shims.cc
index f09acc9..bd6b70e 100644
--- a/components/gwp_asan/client/sampling_allocator_shims.cc
+++ b/components/gwp_asan/client/sampling_allocator_shims.cc
@@ -17,6 +17,7 @@
 #include "components/crash/core/common/crash_key.h"
 #include "components/gwp_asan/client/export.h"
 #include "components/gwp_asan/client/guarded_page_allocator.h"
+#include "components/gwp_asan/client/sampling_state.h"
 #include "components/gwp_asan/common/crash_key_name.h"
 
 #if defined(OS_MACOSX)
@@ -30,88 +31,13 @@
 
 using base::allocator::AllocatorDispatch;
 
-// Class that encapsulates the current sampling state. Sampling is performed
-// using a counter stored in thread-local storage.
-class SamplingState {
- public:
-  constexpr SamplingState() {}
-
-  void Init(size_t sampling_frequency) {
-    DCHECK_GT(sampling_frequency, 0U);
-    sampling_frequency_ = sampling_frequency;
-
-#if defined(OS_MACOSX)
-    pthread_key_create(&tls_key_, nullptr);
-#endif
-  }
-
-  // Return true if this allocation should be sampled.
-  ALWAYS_INLINE bool Sample() {
-    // For a new thread the initial TLS value will be zero, we do not want to
-    // sample on zero as it will always sample the first allocation on thread
-    // creation and heavily bias allocations towards that particular call site.
-    //
-    // Instead, use zero to mean 'get a new counter value' and one to mean
-    // that this allocation should be sampled.
-    size_t samples_left = GetCounter();
-    if (UNLIKELY(!samples_left))
-      samples_left = NextSample();
-
-    SetCounter(samples_left - 1);
-    return (samples_left == 1);
-  }
-
- private:
-  // Sample a single allocations in every chunk of |sampling_frequency_|
-  // allocations.
-  //
-  // TODO(https://crbug.com/919207): Replace with std::geometric_distribution
-  // once the LLVM floating point codegen issue in the linked bug is fixed.
-  size_t NextSample() {
-    size_t random = base::RandInt(1, sampling_frequency_ + 1);
-    size_t next_sample = increment_ + random;
-    increment_ = sampling_frequency_ + 1 - random;
-    return next_sample;
-  }
-
-#if !defined(OS_MACOSX)
-  ALWAYS_INLINE size_t GetCounter() { return tls_counter_; }
-  ALWAYS_INLINE void SetCounter(size_t value) { tls_counter_ = value; }
-
-  static thread_local size_t tls_counter_;
-#else
-  // On macOS, the first use of a thread_local variable on a new thread will
-  // cause a malloc(), causing infinite recursion. Instead, use pthread TLS to
-  // store the counter.
-  ALWAYS_INLINE size_t GetCounter() {
-    return reinterpret_cast<size_t>(pthread_getspecific(tls_key_));
-  }
-
-  ALWAYS_INLINE void SetCounter(size_t value) {
-    pthread_setspecific(tls_key_, reinterpret_cast<void*>(value));
-  }
-
-  pthread_key_t tls_key_ = 0;
-#endif
-
-  size_t sampling_frequency_ = 0;
-
-  // Stores the number of allocations we need to skip to reach the end of the
-  // current chunk of |sampling_frequency_| allocations.
-  size_t increment_ = 0;
-};
-
-#if !defined(OS_MACOSX)
-thread_local size_t SamplingState::tls_counter_ = 0;
-#endif
-
 // By being implemented as a global with inline method definitions, method calls
 // and member acceses are inlined and as efficient as possible in the
 // performance-sensitive allocation hot-path.
 //
 // Note that this optimization has not been benchmarked. However since it is
 // easy to do there is no reason to pay the extra cost.
-SamplingState sampling_state;
+SamplingState<MALLOC> sampling_state;
 
 // The global allocator singleton used by the shims. Implemented as a global
 // pointer instead of a function-local static to avoid initialization checks
diff --git a/components/gwp_asan/client/sampling_state.h b/components/gwp_asan/client/sampling_state.h
new file mode 100644
index 0000000..b5de88f
--- /dev/null
+++ b/components/gwp_asan/client/sampling_state.h
@@ -0,0 +1,108 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_GWP_ASAN_CLIENT_SAMPLING_STATE_H_
+#define COMPONENTS_GWP_ASAN_CLIENT_SAMPLING_STATE_H_
+
+#include <stddef.h>  // for size_t
+
+#include "base/compiler_specific.h"
+#include "base/rand_util.h"
+#include "build/build_config.h"
+
+#if defined(OS_MACOSX)
+#include <pthread.h>
+#endif
+
+namespace gwp_asan {
+namespace internal {
+
+enum ParentAllocator {
+  MALLOC = 0,
+};
+
+// Class that encapsulates the current sampling state. Sampling is performed
+// using a counter stored in thread-local storage.
+//
+// This class is templated so that a thread-local global it contains is not
+// shared between different instances (used by shims for different allocators.)
+template <ParentAllocator PA>
+class SamplingState {
+ public:
+  constexpr SamplingState() {}
+
+  void Init(size_t sampling_frequency) {
+    DCHECK_GT(sampling_frequency, 0U);
+    sampling_frequency_ = sampling_frequency;
+
+#if defined(OS_MACOSX)
+    pthread_key_create(&tls_key_, nullptr);
+#endif
+  }
+
+  // Return true if this allocation should be sampled.
+  ALWAYS_INLINE bool Sample() {
+    // For a new thread the initial TLS value will be zero, we do not want to
+    // sample on zero as it will always sample the first allocation on thread
+    // creation and heavily bias allocations towards that particular call site.
+    //
+    // Instead, use zero to mean 'get a new counter value' and one to mean
+    // that this allocation should be sampled.
+    size_t samples_left = GetCounter();
+    if (UNLIKELY(!samples_left))
+      samples_left = NextSample();
+
+    SetCounter(samples_left - 1);
+    return (samples_left == 1);
+  }
+
+ private:
+  // Sample a single allocations in every chunk of |sampling_frequency_|
+  // allocations.
+  //
+  // TODO(https://crbug.com/919207): Replace with std::geometric_distribution
+  // once the LLVM floating point codegen issue in the linked bug is fixed.
+  size_t NextSample() {
+    size_t random = base::RandInt(1, sampling_frequency_ + 1);
+    size_t next_sample = increment_ + random;
+    increment_ = sampling_frequency_ + 1 - random;
+    return next_sample;
+  }
+
+#if !defined(OS_MACOSX)
+  ALWAYS_INLINE size_t GetCounter() { return tls_counter_; }
+  ALWAYS_INLINE void SetCounter(size_t value) { tls_counter_ = value; }
+
+  static thread_local size_t tls_counter_;
+#else
+  // On macOS, the first use of a thread_local variable on a new thread will
+  // cause a malloc(), causing infinite recursion. Instead, use pthread TLS to
+  // store the counter.
+  ALWAYS_INLINE size_t GetCounter() {
+    return reinterpret_cast<size_t>(pthread_getspecific(tls_key_));
+  }
+
+  ALWAYS_INLINE void SetCounter(size_t value) {
+    pthread_setspecific(tls_key_, reinterpret_cast<void*>(value));
+  }
+
+  pthread_key_t tls_key_ = 0;
+#endif
+
+  size_t sampling_frequency_ = 0;
+
+  // Stores the number of allocations we need to skip to reach the end of the
+  // current chunk of |sampling_frequency_| allocations.
+  size_t increment_ = 0;
+};
+
+#if !defined(OS_MACOSX)
+template <ParentAllocator PA>
+thread_local size_t SamplingState<PA>::tls_counter_ = 0;
+#endif
+
+}  // namespace internal
+}  // namespace gwp_asan
+
+#endif  // COMPONENTS_GWP_ASAN_CLIENT_SAMPLING_STATE_H_
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc
index 82958e394..bf78f09 100644
--- a/components/omnibox/browser/clipboard_provider.cc
+++ b/components/omnibox/browser/clipboard_provider.cc
@@ -124,7 +124,7 @@
   UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge",
                                clipboard_contents_age);
 
-  matches_.emplace_back(match);
+  matches_.push_back(match);
 }
 
 base::Optional<AutocompleteMatch> ClipboardProvider::CreateURLMatch(
@@ -153,14 +153,12 @@
   auto format_types = AutocompleteMatch::GetFormatTypes(false, true);
   match.contents.assign(url_formatter::FormatUrl(
       url, format_types, net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
-  AutocompleteMatch::ClassifyLocationInString(
-      base::string16::npos, 0, match.contents.length(),
-      ACMatchClassification::URL, &match.contents_class);
+  if (!match.contents.empty())
+    match.contents_class.push_back({0, ACMatchClassification::URL});
 
   match.description.assign(l10n_util::GetStringUTF16(IDS_LINK_FROM_CLIPBOARD));
-  AutocompleteMatch::ClassifyLocationInString(
-      base::string16::npos, 0, match.description.length(),
-      ACMatchClassification::NONE, &match.description_class);
+  if (!match.description.empty())
+    match.description_class.push_back({0, ACMatchClassification::NONE});
 
   return match;
 }
@@ -204,14 +202,12 @@
   match.destination_url = result;
   match.contents.assign(l10n_util::GetStringFUTF16(
       IDS_COPIED_TEXT_FROM_CLIPBOARD, AutocompleteMatch::SanitizeString(text)));
-  AutocompleteMatch::ClassifyLocationInString(
-      base::string16::npos, 0, match.contents.length(),
-      ACMatchClassification::NONE, &match.contents_class);
+  if (!match.contents.empty())
+    match.contents_class.push_back({0, ACMatchClassification::NONE});
 
   match.description.assign(l10n_util::GetStringUTF16(IDS_TEXT_FROM_CLIPBOARD));
-  AutocompleteMatch::ClassifyLocationInString(
-      base::string16::npos, 0, match.description.length(),
-      ACMatchClassification::NONE, &match.description_class);
+  if (!match.description.empty())
+    match.description_class.push_back({0, ACMatchClassification::NONE});
 
   match.keyword = default_url->keyword();
   match.transition = ui::PAGE_TRANSITION_GENERATED;
@@ -285,9 +281,8 @@
                           AutocompleteMatchType::CLIPBOARD_IMAGE);
 
   match.description.assign(l10n_util::GetStringUTF16(IDS_IMAGE_FROM_CLIPBOARD));
-  AutocompleteMatch::ClassifyLocationInString(
-      base::string16::npos, 0, match.description.length(),
-      ACMatchClassification::NONE, &match.description_class);
+  if (!match.description.empty())
+    match.description_class.push_back({0, ACMatchClassification::NONE});
 
   TemplateURLRef::SearchTermsArgs search_args(base::ASCIIToUTF16(""));
   search_args.image_thumbnail_content.assign(image_bytes->front_as<char>(),
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc
index 96f2d47..eb76769 100644
--- a/components/omnibox/browser/document_provider.cc
+++ b/components/omnibox/browser/document_provider.cc
@@ -548,18 +548,22 @@
   // All URLs are canonicalized to a GURL form only used for deduplication and
   // not guaranteed to be usable for navigation.
   // URLs of the following forms are handled:
-  // https://drive.google.com/open?id=(id)
-  // https://docs.google.com/document/d/(id)/edit
-  // https://docs.google.com/spreadsheets/d/(id)/edit#gid=12345
-  // https://docs.google.com/presentation/d/(id)/edit#slide=id.g12345a_0_26
-  // https://www.google.com/url?[...]url=https://drive.google.com/a/google.com/open?id%3D1fkxx6KYRYnSqljThxShJVliQJLdKzuJBnzogzL3n8rE&[...]
+  // https://drive.google.com/[a/domain.tld]/open?id=(id)
+  // https://docs.google.com/[a/domain.tld/]document/d/(id)/[...]
+  // https://docs.google.com/[a/domain.tld/]spreadsheets/d/(id)/edit#gid=12345
+  // https://docs.google.com/[a/domain.tld/]presentation/d/(id)/edit#slide=id.g12345a_0_26
+  // https://www.google.com/url?[...]url=https://drive.google.com/a/domain.tld/open?id%3D1fkxx6KYRYnSqljThxShJVliQJLdKzuJBnzogzL3n8rE&[...]
   // where id is comprised of characters in [0-9A-Za-z\-_] = [\w\-]
   std::string id;
-  if (url.host() == "drive.google.com" && url.path() == "/open") {
-    net::GetValueForKeyInQuery(url, "id", &id);
+
+  if (url.host() == "drive.google.com") {
+    static re2::LazyRE2 path_regex = {"^/(?:a/[\\w\\.]+/)?open$"};
+    if (RE2::PartialMatch(url.path(), *path_regex))
+      net::GetValueForKeyInQuery(url, "id", &id);
   } else if (url.host() == "docs.google.com") {
     static re2::LazyRE2 doc_link_regex = {
-        "^/(?:document|spreadsheets|presentation|forms)/d/([\\w-]+)/"};
+        "^/(?:a/[\\w\\.]+/)?(?:document|spreadsheets|presentation|forms)/d/"
+        "([\\w-]+)/"};
     RE2::PartialMatch(url.path(), *doc_link_regex, &id);
   } else if (url.host() == "www.google.com" && url.path() == "/url") {
     // Redirect links wrapping a drive.google.com/open?id= link.
diff --git a/components/omnibox/browser/document_provider_unittest.cc b/components/omnibox/browser/document_provider_unittest.cc
index 591dd35..9106d0a 100644
--- a/components/omnibox/browser/document_provider_unittest.cc
+++ b/components/omnibox/browser/document_provider_unittest.cc
@@ -618,6 +618,8 @@
 
   // URLs that represent documents:
   CheckDeduper("https://drive.google.com/open?id=the_doc-id", "the_doc-id");
+  CheckDeduper("https://drive.google.com/a/domain.com/open?x=3&id=the_doc-id",
+               "the_doc-id");
   CheckDeduper("https://docs.google.com/document/d/the_doc-id/edit",
                "the_doc-id");
   CheckDeduper(
@@ -627,6 +629,10 @@
       "https://docs.google.com/spreadsheets/d/the_doc-id/preview?x=1#y=2",
       "the_doc-id");
   CheckDeduper(
+      "https://docs.google.com/a/domain/spreadsheets/d/the_doc-id/"
+      "preview?x=1#y=2",
+      "the_doc-id");
+  CheckDeduper(
       "https://www.google.com/"
       "url?sa=t&rct=j&esrc=s&source=appssearch&uact=8&cd=0&cad=rja&q&sig2=sig&"
       "url=https://drive.google.com/a/google.com/"
@@ -646,6 +652,8 @@
       "the_doc_id");
 
   // URLs that do not represent documents:
+  CheckDeduper("https://drive.google.com/b/domain.com/open?id=the_doc-id", "");
+  CheckDeduper("https://drive.google.com/b/domain.com/open?idx=the_doc-id", "");
   CheckDeduper("https://docs.google.com/help?id=d123", "");
   CheckDeduper("https://www.google.com", "");
   CheckDeduper("https://docs.google.com/kittens/d/d123/preview?x=1#y=2", "");
diff --git a/components/omnibox/browser/verbatim_match.cc b/components/omnibox/browser/verbatim_match.cc
index 25bda7d..82a42aec 100644
--- a/components/omnibox/browser/verbatim_match.cc
+++ b/components/omnibox/browser/verbatim_match.cc
@@ -30,9 +30,8 @@
         destination_url,
         !AutocompleteInput::HasHTTPScheme(input.text()));
     match.description = destination_description;
-    AutocompleteMatch::ClassifyLocationInString(
-        base::string16::npos, 0, match.description.length(),
-        ACMatchClassification::NONE, &match.description_class);
+    if (!match.description.empty())
+      match.description_class.push_back({0, ACMatchClassification::NONE});
   } else {
     client->Classify(input.text(), false, true,
                      input.current_page_classification(), &match, nullptr);
diff --git a/components/send_tab_to_self/BUILD.gn b/components/send_tab_to_self/BUILD.gn
index 7ab6767..558220b 100644
--- a/components/send_tab_to_self/BUILD.gn
+++ b/components/send_tab_to_self/BUILD.gn
@@ -24,6 +24,7 @@
     "//components/keyed_service/core",
     "//components/send_tab_to_self/proto:send_tab_to_self_proto",
     "//components/sync",
+    "//components/sync/device_info",
     "//components/version_info",
     "//url",
   ]
@@ -64,6 +65,7 @@
     "//components/history/core/browser",
     "//components/send_tab_to_self/proto:send_tab_to_self_proto",
     "//components/sync:test_support",
+    "//components/sync/device_info",
     "//testing/gtest",
     "//url",
   ]
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.cc b/components/send_tab_to_self/send_tab_to_self_bridge.cc
index 46fba17..7458e3a 100644
--- a/components/send_tab_to_self/send_tab_to_self_bridge.cc
+++ b/components/send_tab_to_self/send_tab_to_self_bridge.cc
@@ -4,6 +4,8 @@
 
 #include "components/send_tab_to_self/send_tab_to_self_bridge.h"
 
+#include <algorithm>
+
 #include "base/bind.h"
 #include "base/guid.h"
 #include "base/logging.h"
@@ -11,10 +13,12 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/time/clock.h"
+#include "base/time/time.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/send_tab_to_self/features.h"
 #include "components/send_tab_to_self/proto/send_tab_to_self.pb.h"
 #include "components/sync/base/get_session_name.h"
+#include "components/sync/device_info/device_info_tracker.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/metadata_change_list.h"
@@ -44,6 +48,8 @@
 
 const base::TimeDelta kDedupeTime = base::TimeDelta::FromSeconds(5);
 
+const base::TimeDelta kDeviceExpiration = base::TimeDelta::FromDays(10);
+
 const char kAddEntryStatus[] = "SendTabToSelf.Sync.AddEntryStatus";
 
 // Converts a time field from sync protobufs to a time object.
@@ -95,13 +101,16 @@
     std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
     base::Clock* clock,
     syncer::OnceModelTypeStoreFactory create_store_callback,
-    history::HistoryService* history_service)
+    history::HistoryService* history_service,
+    syncer::DeviceInfoTracker* device_info_tracker)
     : ModelTypeSyncBridge(std::move(change_processor)),
       clock_(clock),
       history_service_(history_service),
+      device_info_tracker_(device_info_tracker),
       mru_entry_(nullptr),
       weak_ptr_factory_(this) {
   DCHECK(clock_);
+  DCHECK(device_info_tracker_);
   if (history_service) {
     history_service->AddObserver(this);
   }
@@ -384,6 +393,14 @@
   return change_processor()->IsTrackingMetadata();
 }
 
+std::map<std::string, std::string>
+SendTabToSelfBridge::GetTargetDeviceNameToCacheGuidMap() {
+  if (ShouldUpdateTargetDeviceNameToCacheGuidMap()) {
+    SetTargetDeviceNameToCacheGuidMap();
+  }
+  return target_device_name_to_cache_guid_;
+}
+
 // static
 std::unique_ptr<syncer::ModelTypeStore>
 SendTabToSelfBridge::DestroyAndStealStoreForTest(
@@ -391,6 +408,10 @@
   return std::move(bridge->store_);
 }
 
+bool SendTabToSelfBridge::ShouldUpdateTargetDeviceNameToCacheGuidMapForTest() {
+  return ShouldUpdateTargetDeviceNameToCacheGuidMap();
+}
+
 void SendTabToSelfBridge::NotifyRemoteSendTabToSelfEntryAdded(
     const std::vector<const SendTabToSelfEntry*>& new_entries) {
   std::vector<const SendTabToSelfEntry*> new_local_entries;
@@ -523,4 +544,66 @@
   NotifyRemoteSendTabToSelfEntryDeleted(removed);
 }
 
+bool SendTabToSelfBridge::ShouldUpdateTargetDeviceNameToCacheGuidMap() const {
+  // The map should be updated if any of these is true:
+  //   * The map is empty.
+  //   * The number of total devices changed.
+  //   * The oldest non-expired entry in the map is now expired.
+  return target_device_name_to_cache_guid_.empty() ||
+         device_info_tracker_->GetAllDeviceInfo().size() !=
+             number_of_devices_ ||
+         clock_->Now() - change_processor()->GetEntityModificationTime(
+                             oldest_device_cache_guid_) >
+             kDeviceExpiration;
+}
+
+void SendTabToSelfBridge::SetTargetDeviceNameToCacheGuidMap() {
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> all_devices =
+      device_info_tracker_->GetAllDeviceInfo();
+  number_of_devices_ = all_devices.size();
+
+  // Sort the DeviceInfo vector so the most recenly modified devices are first.
+  const syncer::ModelTypeChangeProcessor* change_processor_ptr =
+      change_processor();
+  std::stable_sort(
+      all_devices.begin(), all_devices.end(),
+      [change_processor_ptr](
+          const std::unique_ptr<syncer::DeviceInfo>& device1,
+          const std::unique_ptr<syncer::DeviceInfo>& device2) {
+        return change_processor_ptr->GetEntityModificationTime(
+                   device1->guid()) >
+               change_processor_ptr->GetEntityModificationTime(device2->guid());
+      });
+
+  target_device_name_to_cache_guid_.clear();
+  for (const auto& device : all_devices) {
+    // If the current device is considered expired for our purposes, stop here
+    // since the next devices in the vector are at least as expired than this
+    // one.
+    if (clock_->Now() -
+            change_processor()->GetEntityModificationTime(device->guid()) >
+        kDeviceExpiration) {
+      break;
+    }
+
+    // TODO(crbug.com/957716): Dedupe older versions of this device as well.
+    // Don't include this device.
+    if (device->guid() == change_processor()->TrackedCacheGuid()) {
+      continue;
+    }
+
+    // Don't include devices that have disabled the send tab to self receiving
+    // feature.
+    if (!device->send_tab_to_self_receiving_enabled()) {
+      continue;
+    }
+
+    // Only keep one device per device name. We only keep the first occurrence
+    // which is the most recent.
+    target_device_name_to_cache_guid_.emplace(device->client_name(),
+                                              device->guid());
+    oldest_device_cache_guid_ = device->guid();
+  }
+}
+
 }  // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.h b/components/send_tab_to_self/send_tab_to_self_bridge.h
index 8b5c134..42086b644 100644
--- a/components/send_tab_to_self/send_tab_to_self_bridge.h
+++ b/components/send_tab_to_self/send_tab_to_self_bridge.h
@@ -26,6 +26,7 @@
 }  // namespace history
 
 namespace syncer {
+class DeviceInfoTracker;
 class ModelTypeChangeProcessor;
 }  // namespace syncer
 
@@ -41,12 +42,14 @@
                             public SendTabToSelfModel,
                             public history::HistoryServiceObserver {
  public:
-  // |clock| must not be null and must outlive this object.
+  // The caller should ensure that all raw pointers are not null and will
+  // outlive this object. This is not guaranteed by this class.
   SendTabToSelfBridge(
       std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
       base::Clock* clock,
       syncer::OnceModelTypeStoreFactory create_store_callback,
-      history::HistoryService* history_service);
+      history::HistoryService* history_service,
+      syncer::DeviceInfoTracker* device_info_tracker);
   ~SendTabToSelfBridge() override;
 
   // syncer::ModelTypeSyncBridge overrides.
@@ -76,6 +79,8 @@
   void DeleteEntry(const std::string& guid) override;
   void DismissEntry(const std::string& guid) override;
   bool IsReady() override;
+  std::map<std::string, std::string> GetTargetDeviceNameToCacheGuidMap()
+      override;
 
   // history::HistoryServiceObserver:
   void OnURLsDeleted(history::HistoryService* history_service,
@@ -84,6 +89,7 @@
   // For testing only.
   static std::unique_ptr<syncer::ModelTypeStore> DestroyAndStealStoreForTest(
       std::unique_ptr<SendTabToSelfBridge> bridge);
+  bool ShouldUpdateTargetDeviceNameToCacheGuidMapForTest();
 
  private:
   using SendTabToSelfEntries =
@@ -122,6 +128,12 @@
   // Delete expired entries.
   void DoGarbageCollection();
 
+  // Returns whether the target device name to cache guid map should be updated.
+  bool ShouldUpdateTargetDeviceNameToCacheGuidMap() const;
+
+  // Sets the target device name to cache guid map.
+  void SetTargetDeviceNameToCacheGuidMap();
+
   // |entries_| is keyed by GUIDs.
   SendTabToSelfEntries entries_;
 
@@ -131,6 +143,9 @@
   // |history_service_| isn't owned.
   history::HistoryService* const history_service_;
 
+  // |device_info_tracker_| isn't owned.
+  syncer::DeviceInfoTracker* const device_info_tracker_;
+
   // The name of this local device.
   std::string local_device_name_;
 
@@ -139,6 +154,15 @@
 
   // A pointer to the most recently used entry used for deduplication.
   const SendTabToSelfEntry* mru_entry_;
+
+  // A map of target devices names to their associated cache guid.
+  std::map<std::string, std::string> target_device_name_to_cache_guid_;
+
+  // The following two variables are used to determine whether we should update
+  // the target device name to cache guid map.
+  std::string oldest_device_cache_guid_ = "";
+  size_t number_of_devices_ = 0;
+
   base::WeakPtrFactory<SendTabToSelfBridge> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SendTabToSelfBridge);
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
index adb0fa6..2880b0b 100644
--- a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
+++ b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
@@ -17,6 +17,8 @@
 #include "components/history/core/browser/history_service.h"
 #include "components/send_tab_to_self/features.h"
 #include "components/send_tab_to_self/proto/send_tab_to_self.pb.h"
+#include "components/sync/device_info/device_info.h"
+#include "components/sync/device_info/device_info_tracker.h"
 #include "components/sync/model/entity_change.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/mock_model_type_change_processor.h"
@@ -32,15 +34,18 @@
 namespace {
 
 using testing::_;
+using testing::ElementsAre;
 using testing::IsEmpty;
+using testing::Pair;
 using testing::Return;
 using testing::SizeIs;
+using testing::UnorderedElementsAre;
 
 const char kGuidFormat[] = "guid %d";
 const char kURLFormat[] = "https://www.url%d.com/";
 const char kTitleFormat[] = "title %d";
 const char kDeviceFormat[] = "device %d";
-const char kTargetDeviceCacheGuid[] = "target_device";
+const char kLocalDeviceCacheGuid[] = "local_device_guid";
 
 sync_pb::SendTabToSelfSpecifics CreateSpecifics(
     int suffix,
@@ -51,7 +56,7 @@
   specifics.set_url(base::StringPrintf(kURLFormat, suffix));
   specifics.set_device_name(base::StringPrintf(kDeviceFormat, suffix));
   specifics.set_title(base::StringPrintf(kTitleFormat, suffix));
-  specifics.set_target_device_sync_cache_guid(kTargetDeviceCacheGuid);
+  specifics.set_target_device_sync_cache_guid(kLocalDeviceCacheGuid);
   specifics.set_shared_time_usec(
       shared_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
   specifics.set_navigation_time_usec(
@@ -65,6 +70,7 @@
   state.set_encryption_key_name(encryption_key_name);
   return state;
 }
+
 class MockSendTabToSelfModelObserver : public SendTabToSelfModelObserver {
  public:
   MOCK_METHOD0(SendTabToSelfModelLoaded, void());
@@ -74,12 +80,57 @@
   MOCK_METHOD1(EntriesRemovedRemotely, void(const std::vector<std::string>&));
 };
 
+// TODO(crbug.com/958016): Extract into its own file.
+// Mock DeviceInfoTracker class for setting device info.
+class TestDeviceInfoTracker : public syncer::DeviceInfoTracker {
+ public:
+  TestDeviceInfoTracker() = default;
+  ~TestDeviceInfoTracker() override = default;
+
+  static std::unique_ptr<syncer::DeviceInfo> CloneDeviceInfo(
+      const syncer::DeviceInfo& device_info) {
+    return std::make_unique<syncer::DeviceInfo>(
+        device_info.guid(), device_info.client_name(),
+        device_info.chrome_version(), device_info.sync_user_agent(),
+        device_info.device_type(), device_info.signin_scoped_device_id(),
+        device_info.send_tab_to_self_receiving_enabled());
+  }
+
+  void Add(const syncer::DeviceInfo* device) { devices_.push_back(device); }
+
+  // DeviceInfoTracker implementation.
+  bool IsSyncing() const override { return false; }
+  std::unique_ptr<syncer::DeviceInfo> GetDeviceInfo(
+      const std::string& client_id) const override {
+    NOTIMPLEMENTED();
+    return std::unique_ptr<syncer::DeviceInfo>();
+  }
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> GetAllDeviceInfo()
+      const override {
+    std::vector<std::unique_ptr<syncer::DeviceInfo>> devices;
+    for (const syncer::DeviceInfo* device : devices_) {
+      devices.push_back(CloneDeviceInfo(*device));
+    }
+    return devices;
+  }
+  int CountActiveDevices() const override { return devices_.size(); }
+  void AddObserver(Observer* observer) override { NOTIMPLEMENTED(); }
+  void RemoveObserver(Observer* observer) override { NOTIMPLEMENTED(); }
+  void ForcePulseForTest() override { NOTIMPLEMENTED(); }
+
+ private:
+  // DeviceInfo stored here are not owned.
+  std::vector<const syncer::DeviceInfo*> devices_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestDeviceInfoTracker);
+};
+
 class SendTabToSelfBridgeTest : public testing::Test {
  protected:
   SendTabToSelfBridgeTest()
       : store_(syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) {
     scoped_feature_list_.InitAndEnableFeature(kSendTabToSelfShowSendingUI);
-    SetLocalDeviceCacheGuid("target_device");
+    SetLocalDeviceCacheGuid(kLocalDeviceCacheGuid);
   }
 
   // Initialized the bridge based on the current local device and store. Can
@@ -89,7 +140,7 @@
     bridge_ = std::make_unique<SendTabToSelfBridge>(
         mock_processor_.CreateForwardingProcessor(), &clock_,
         syncer::ModelTypeStoreTestUtil::MoveStoreToFactory(std::move(store_)),
-        nullptr);
+        /*history_service=*/nullptr, &device_info_tracker_);
     bridge_->AddObserver(&mock_observer_);
     base::RunLoop().RunUntilIdle();
   }
@@ -145,13 +196,13 @@
   void AddSampleEntries() {
     // Adds timer to avoid having two entries with the same shared timestamp.
     bridge_->AddEntry(GURL("http://a.com"), "a", AdvanceAndGetTime(),
-                      "target_device");
+                      kLocalDeviceCacheGuid);
     bridge_->AddEntry(GURL("http://b.com"), "b", AdvanceAndGetTime(),
-                      "target_device");
+                      kLocalDeviceCacheGuid);
     bridge_->AddEntry(GURL("http://c.com"), "c", AdvanceAndGetTime(),
-                      "target_device");
+                      kLocalDeviceCacheGuid);
     bridge_->AddEntry(GURL("http://d.com"), "d", AdvanceAndGetTime(),
-                      "target_device");
+                      kLocalDeviceCacheGuid);
   }
 
   void SetLocalDeviceCacheGuid(const std::string& cache_guid) {
@@ -159,11 +210,18 @@
         .WillByDefault(Return(cache_guid));
   }
 
+  void AddTestDevice(const syncer::DeviceInfo* device) {
+    device_info_tracker_.Add(device);
+  }
+
   syncer::MockModelTypeChangeProcessor* processor() { return &mock_processor_; }
 
   SendTabToSelfBridge* bridge() { return bridge_.get(); }
+
   MockSendTabToSelfModelObserver* mock_observer() { return &mock_observer_; }
 
+  base::SimpleTestClock* clock() { return &clock_; }
+
  private:
   base::SimpleTestClock clock_;
 
@@ -174,6 +232,8 @@
 
   testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_;
 
+  TestDeviceInfoTracker device_info_tracker_;
+
   std::unique_ptr<SendTabToSelfBridge> bridge_;
 
   testing::NiceMock<MockSendTabToSelfModelObserver> mock_observer_;
@@ -198,7 +258,7 @@
 
   SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title",
                            AdvanceAndGetTime(), AdvanceAndGetTime(), "device",
-                           "target_device");
+                           kLocalDeviceCacheGuid);
 
   remote_input.push_back(
       syncer::EntityChange::CreateAdd("guid1", MakeEntityData(entry)));
@@ -232,7 +292,7 @@
   InitializeBridge();
   SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title",
                            AdvanceAndGetTime(), AdvanceAndGetTime(), "device",
-                           "target_device");
+                           kLocalDeviceCacheGuid);
 
   syncer::EntityChangeList add_changes;
 
@@ -252,7 +312,7 @@
   InitializeBridge();
   SendTabToSelfEntry entry("guid1", GURL("http://www.example.com/"), "title",
                            AdvanceAndGetTime(), AdvanceAndGetTime(), "device",
-                           "target_device");
+                           kLocalDeviceCacheGuid);
 
   syncer::EntityChangeList add_changes;
 
@@ -446,21 +506,24 @@
   EXPECT_CALL(*mock_observer(), EntriesAddedRemotely(_)).Times(0);
 
   // Add Entry should succeed in this case.
-  EXPECT_NE(nullptr, bridge()->AddEntry(GURL("http://www.example.com/"), "d",
-                                        AdvanceAndGetTime(), "target_device"));
+  EXPECT_NE(nullptr,
+            bridge()->AddEntry(GURL("http://www.example.com/"), "d",
+                               AdvanceAndGetTime(), kLocalDeviceCacheGuid));
 
   // Add Entry should fail on invalid URLs.
   EXPECT_EQ(nullptr, bridge()->AddEntry(GURL(), "d", AdvanceAndGetTime(),
-                                        "target_device"));
-  EXPECT_EQ(nullptr, bridge()->AddEntry(GURL("http://?k=v"), "d",
-                                        AdvanceAndGetTime(), "target_device"));
-  EXPECT_EQ(nullptr, bridge()->AddEntry(GURL("http//google.com"), "d",
-                                        AdvanceAndGetTime(), "target_device"));
+                                        kLocalDeviceCacheGuid));
+  EXPECT_EQ(nullptr,
+            bridge()->AddEntry(GURL("http://?k=v"), "d", AdvanceAndGetTime(),
+                               kLocalDeviceCacheGuid));
+  EXPECT_EQ(nullptr,
+            bridge()->AddEntry(GURL("http//google.com"), "d",
+                               AdvanceAndGetTime(), kLocalDeviceCacheGuid));
 
   // Add Entry should succeed on an invalid navigation_time, since that is the
   // case for sending links.
   EXPECT_NE(nullptr, bridge()->AddEntry(GURL("http://www.example.com/"), "d",
-                                        base::Time(), "target_device"));
+                                        base::Time(), kLocalDeviceCacheGuid));
 }
 
 TEST_F(SendTabToSelfBridgeTest, IsBridgeReady) {
@@ -480,15 +543,15 @@
   // The de-duplication code does not use the title as a comparator.
   // So they are intentionally different here.
   bridge()->AddEntry(GURL("http://a.com"), "a", navigation_time,
-                     "target_device");
+                     kLocalDeviceCacheGuid);
   bridge()->AddEntry(GURL("http://a.com"), "b", navigation_time,
-                     "target_device");
+                     kLocalDeviceCacheGuid);
   EXPECT_EQ(1ul, bridge()->GetAllGuids().size());
 
   bridge()->AddEntry(GURL("http://a.com"), "a", AdvanceAndGetTime(),
-                     "target_device");
+                     kLocalDeviceCacheGuid);
   bridge()->AddEntry(GURL("http://b.com"), "b", AdvanceAndGetTime(),
-                     "target_device");
+                     kLocalDeviceCacheGuid);
   EXPECT_EQ(3ul, bridge()->GetAllGuids().size());
 }
 
@@ -561,6 +624,200 @@
   EXPECT_EQ(2ul, bridge()->GetAllGuids().size());
 }
 
+// Tests that only the most recent device's guid is returned when multiple
+// devices have the same name.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_OneDevicePerName) {
+  const std::string kRecentGuid = "guid1";
+  const std::string kOldGuid = "guid2";
+  const std::string kOlderGuid = "guid3";
+
+  InitializeBridge();
+
+  // Create multiple DeviceInfo objects with the same name but different guids.
+  syncer::DeviceInfo device1(kOldGuid, "device_name", "72", "agent",
+                             sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                             "scoped_is",
+                             /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&device1);
+
+  syncer::DeviceInfo device2(kRecentGuid, "device_name", "72", "agent",
+                             sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                             "scoped_is",
+                             /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&device2);
+
+  syncer::DeviceInfo device3(kOlderGuid, "device_name", "72", "agent",
+                             sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                             "scoped_is",
+                             /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&device3);
+
+  // Make sure the device with cache id "recent_guid" was modified more
+  // recently.
+  ON_CALL(*processor(), GetEntityModificationTime(kRecentGuid))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+  ON_CALL(*processor(), GetEntityModificationTime(kOldGuid))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(3)));
+  ON_CALL(*processor(), GetEntityModificationTime(kOlderGuid))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(5)));
+
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("device_name", kRecentGuid)));
+}
+
+// Tests that only devices that have the send tab to self receiving feature
+// enabled are returned.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_OnlyReceivingEnabled) {
+  InitializeBridge();
+
+  syncer::DeviceInfo enabled_device(
+      "enabled_guid", "enabled_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&enabled_device);
+
+  syncer::DeviceInfo disabled_device(
+      "disabled_guid", "disabled_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/false);
+  AddTestDevice(&disabled_device);
+
+  // Make sure the devices were used recently.
+  ON_CALL(*processor(), GetEntityModificationTime("enabled_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+  ON_CALL(*processor(), GetEntityModificationTime("disabled_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("enabled_device_name", "enabled_guid")));
+}
+
+// Tests that only devices that are not expired are returned.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_NoExpiredDevices) {
+  InitializeBridge();
+
+  syncer::DeviceInfo expired_device(
+      "expired_guid", "expired_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&expired_device);
+
+  syncer::DeviceInfo valid_device(
+      "valid_guid", "valid_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&valid_device);
+
+  // Set one device to be expired and the other to be valid.
+  ON_CALL(*processor(), GetEntityModificationTime("expired_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(11)));
+  ON_CALL(*processor(), GetEntityModificationTime("valid_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("valid_device_name", "valid_guid")));
+}
+
+// Tests that the local device is not returned.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_NoLocalDevice) {
+  InitializeBridge();
+
+  syncer::DeviceInfo local_device(
+      kLocalDeviceCacheGuid, "local_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&local_device);
+
+  syncer::DeviceInfo other_device(
+      "other_guid", "other_device_name", "72", "agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is",
+      /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&other_device);
+
+  // Set both device to not be expired.
+  ON_CALL(*processor(), GetEntityModificationTime(kLocalDeviceCacheGuid))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+  ON_CALL(*processor(), GetEntityModificationTime("other_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("other_device_name", "other_guid")));
+}
+
+// Tests that the local device is not returned.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_Updated_DeviceExpired) {
+  InitializeBridge();
+
+  // Set a device that is about to expire and a more recent device.
+  syncer::DeviceInfo older_device("older_guid", "older_name", "72", "agent",
+                                  sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                                  "scoped_is",
+                                  /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&older_device);
+
+  syncer::DeviceInfo recent_device("recent_guid", "recent_name", "72", "agent",
+                                   sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                                   "scoped_is",
+                                   /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&recent_device);
+
+  // Set both device to not be expired.
+  ON_CALL(*processor(), GetEntityModificationTime("older_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(9)));
+  ON_CALL(*processor(), GetEntityModificationTime("recent_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  // Set the map by calling it. Make sure it has the 2 devices.
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              UnorderedElementsAre(Pair("older_name", "older_guid"),
+                                   Pair("recent_name", "recent_guid")));
+
+  // Advance the time so that the older device expires.
+  clock()->Advance(base::TimeDelta::FromDays(5));
+
+  // Make sure only the recent device is in the map.
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("recent_name", "recent_guid")));
+}
+
+// Tests that the local device is not returned.
+TEST_F(SendTabToSelfBridgeTest,
+       GetTargetDeviceNameToCacheGuidMap_Updated_NewEntries) {
+  InitializeBridge();
+
+  // Set a valid device.
+  syncer::DeviceInfo device("guid", "name", "72", "agent",
+                            sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                            "scoped_is",
+                            /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&device);
+  ON_CALL(*processor(), GetEntityModificationTime("guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  // Set the map by calling it. Make sure it has the device.
+  EXPECT_THAT(bridge()->GetTargetDeviceNameToCacheGuidMap(),
+              ElementsAre(Pair("name", "guid")));
+
+  // Add a new device.
+  syncer::DeviceInfo new_device("new_guid", "new_name", "72", "agent",
+                                sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
+                                "scoped_is",
+                                /*send_tab_to_self_receiving_enabled=*/true);
+  AddTestDevice(&new_device);
+  ON_CALL(*processor(), GetEntityModificationTime("new_guid"))
+      .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1)));
+
+  // Make sure both devices are in the map.
+  EXPECT_THAT(
+      bridge()->GetTargetDeviceNameToCacheGuidMap(),
+      UnorderedElementsAre(Pair("name", "guid"), Pair("new_name", "new_guid")));
+}
+
 }  // namespace
 
 }  // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/send_tab_to_self_model.h b/components/send_tab_to_self/send_tab_to_self_model.h
index c9f54dc..657af975 100644
--- a/components/send_tab_to_self/send_tab_to_self_model.h
+++ b/components/send_tab_to_self/send_tab_to_self_model.h
@@ -66,6 +66,12 @@
   void AddObserver(SendTabToSelfModelObserver* observer);
   void RemoveObserver(SendTabToSelfModelObserver* observer);
 
+  // Returns a map of the name of possible target devices for the send tab to
+  // self feature to their cache guid. This is a thin layer on top of
+  // DeviceInfoTracker.
+  virtual std::map<std::string, std::string>
+  GetTargetDeviceNameToCacheGuidMap() = 0;
+
  protected:
   // The observers.
   base::ObserverList<SendTabToSelfModelObserver>::Unchecked observers_;
diff --git a/components/send_tab_to_self/send_tab_to_self_sync_service.cc b/components/send_tab_to_self/send_tab_to_self_sync_service.cc
index e969891d..39ac2b6 100644
--- a/components/send_tab_to_self/send_tab_to_self_sync_service.cc
+++ b/components/send_tab_to_self/send_tab_to_self_sync_service.cc
@@ -12,6 +12,7 @@
 #include "components/send_tab_to_self/send_tab_to_self_bridge.h"
 #include "components/send_tab_to_self/send_tab_to_self_model.h"
 #include "components/sync/base/report_unrecoverable_error.h"
+#include "components/sync/device_info/device_info_tracker.h"
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/model_impl/client_tag_based_model_type_processor.h"
 
@@ -22,13 +23,14 @@
 SendTabToSelfSyncService::SendTabToSelfSyncService(
     version_info::Channel channel,
     syncer::OnceModelTypeStoreFactory create_store_callback,
-    history::HistoryService* history_service) {
+    history::HistoryService* history_service,
+    syncer::DeviceInfoTracker* device_info_tracker) {
   bridge_ = std::make_unique<send_tab_to_self::SendTabToSelfBridge>(
       std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
           syncer::SEND_TAB_TO_SELF,
           base::BindRepeating(&syncer::ReportUnrecoverableError, channel)),
       base::DefaultClock::GetInstance(), std::move(create_store_callback),
-      history_service);
+      history_service, device_info_tracker);
 }
 
 SendTabToSelfSyncService::~SendTabToSelfSyncService() = default;
diff --git a/components/send_tab_to_self/send_tab_to_self_sync_service.h b/components/send_tab_to_self/send_tab_to_self_sync_service.h
index 0eec5ea..769c95c 100644
--- a/components/send_tab_to_self/send_tab_to_self_sync_service.h
+++ b/components/send_tab_to_self/send_tab_to_self_sync_service.h
@@ -18,6 +18,7 @@
 }  // namespace history
 
 namespace syncer {
+class DeviceInfoTracker;
 class ModelTypeControllerDelegate;
 }  // namespace syncer
 
@@ -31,7 +32,8 @@
   SendTabToSelfSyncService(
       version_info::Channel channel,
       syncer::OnceModelTypeStoreFactory create_store_callback,
-      history::HistoryService* history_service);
+      history::HistoryService* history_service,
+      syncer::DeviceInfoTracker* device_info_tracker);
   ~SendTabToSelfSyncService() override;
 
   virtual SendTabToSelfModel* GetSendTabToSelfModel();
diff --git a/components/send_tab_to_self/test_send_tab_to_self_model.cc b/components/send_tab_to_self/test_send_tab_to_self_model.cc
index fa97a1f..e7e39a1 100644
--- a/components/send_tab_to_self/test_send_tab_to_self_model.cc
+++ b/components/send_tab_to_self/test_send_tab_to_self_model.cc
@@ -33,4 +33,9 @@
   return false;
 }
 
+std::map<std::string, std::string>
+TestSendTabToSelfModel::GetTargetDeviceNameToCacheGuidMap() {
+  return {};
+}
+
 }  // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/test_send_tab_to_self_model.h b/components/send_tab_to_self/test_send_tab_to_self_model.h
index 92c8810..971988f53 100644
--- a/components/send_tab_to_self/test_send_tab_to_self_model.h
+++ b/components/send_tab_to_self/test_send_tab_to_self_model.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_SEND_TAB_TO_SELF_TEST_SEND_TAB_TO_SELF_MODEL_H_
 #define COMPONENTS_SEND_TAB_TO_SELF_TEST_SEND_TAB_TO_SELF_MODEL_H_
 
+#include <map>
 #include <string>
 #include <vector>
 
@@ -32,6 +33,8 @@
   void DeleteEntry(const std::string& guid) override;
   void DismissEntry(const std::string& guid) override;
   bool IsReady() override;
+  std::map<std::string, std::string> GetTargetDeviceNameToCacheGuidMap()
+      override;
 };
 
 }  // namespace send_tab_to_self
diff --git a/components/thread_pool_util/variations_util.cc b/components/thread_pool_util/variations_util.cc
index bc4d699..09e66cc 100644
--- a/components/thread_pool_util/variations_util.cc
+++ b/components/thread_pool_util/variations_util.cc
@@ -20,9 +20,9 @@
 
 namespace {
 
-// Builds a SchedulerWorkerPoolParams from the pool descriptor in
+// Builds a ThreadGroupParams from the pool descriptor in
 // |variation_params[pool_name]|. Returns an invalid
-// SchedulerWorkerPoolParams on failure.
+// ThreadGroupParams on failure.
 //
 // The pool descriptor is a semi-colon separated value string with the following
 // items:
@@ -32,7 +32,7 @@
 // 3. Thread Count Offset (int)
 // 4. Detach Time in Milliseconds (int)
 // Additional values may appear as necessary and will be ignored.
-std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams(
+std::unique_ptr<base::ThreadGroupParams> GetThreadGroupParams(
     base::StringPiece pool_name,
     const std::map<std::string, std::string>& variation_params) {
   auto pool_descriptor_it = variation_params.find(pool_name.as_string());
@@ -61,7 +61,7 @@
     return nullptr;
   }
 
-  auto params = std::make_unique<base::SchedulerWorkerPoolParams>(
+  auto params = std::make_unique<base::ThreadGroupParams>(
       base::RecommendedMaxNumberOfThreadsInPool(min, max, cores_multiplier,
                                                 offset),
       base::TimeDelta::FromMilliseconds(detach_milliseconds));
@@ -84,11 +84,11 @@
 
 }  // namespace
 
-const base::Feature kBrowserSchedulerInitParams = {
-    "BrowserSchedulerInitParams", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kBrowserThreadPoolInitParams = {
+    "BrowserThreadPoolInitParams", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kRendererSchedulerInitParams = {
-    "RendererSchedulerInitParams", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kRendererThreadPoolInitParams = {
+    "RendererThreadPoolInitParams", base::FEATURE_DISABLED_BY_DEFAULT};
 
 std::unique_ptr<base::ThreadPool::InitParams> GetThreadPoolInitParams(
     const base::Feature& feature) {
@@ -97,9 +97,9 @@
     return nullptr;
 
   const auto background_worker_pool_params =
-      GetWorkerPoolParams("Background", variation_params);
+      GetThreadGroupParams("Background", variation_params);
   const auto foreground_worker_pool_params =
-      GetWorkerPoolParams("Foreground", variation_params);
+      GetThreadGroupParams("Foreground", variation_params);
 
   if (!background_worker_pool_params || !foreground_worker_pool_params)
     return nullptr;
@@ -111,15 +111,15 @@
 std::unique_ptr<base::ThreadPool::InitParams>
 GetThreadPoolInitParamsForBrowser() {
   // Variations params for the browser processes are associated with the feature
-  // |kBrowserSchedulerInitParams|.
-  return GetThreadPoolInitParams(kBrowserSchedulerInitParams);
+  // |kBrowserThreadPoolInitParams|.
+  return GetThreadPoolInitParams(kBrowserThreadPoolInitParams);
 }
 
 std::unique_ptr<base::ThreadPool::InitParams>
 GetThreadPoolInitParamsForRenderer() {
   // Variations params for the renderer processes are associated with the
-  // feature |kRendererSchedulerInitParams|.
-  return GetThreadPoolInitParams(kRendererSchedulerInitParams);
+  // feature |kRendererThreadPoolInitParams|.
+  return GetThreadPoolInitParams(kRendererThreadPoolInitParams);
 }
 
 }  // namespace thread_pool_util
diff --git a/components/thread_pool_util/variations_util.h b/components/thread_pool_util/variations_util.h
index 588ed6f8..9be9f66 100644
--- a/components/thread_pool_util/variations_util.h
+++ b/components/thread_pool_util/variations_util.h
@@ -13,8 +13,8 @@
 
 namespace thread_pool_util {
 
-extern const base::Feature kBrowserSchedulerInitParams;
-extern const base::Feature kRendererSchedulerInitParams;
+extern const base::Feature kBrowserThreadPoolInitParams;
+extern const base::Feature kRendererThreadPoolInitParams;
 
 // Builds a ThreadPool::InitParams from variations params that are prefixed
 // for |feature|. Returns nullptr on failure.
@@ -25,12 +25,12 @@
     const base::Feature& feature);
 
 // Builds a ThreadPool::InitParams to use in the browser process from
-// variation params in the BrowserScheduler field trial.
+// variation params in the BrowserThreadPool field trial.
 std::unique_ptr<base::ThreadPool::InitParams>
 GetThreadPoolInitParamsForBrowser();
 
 // Builds a ThreadPool::InitParams to use in renderer processes from
-// variation params in the BrowserScheduler field trial.
+// variation params in the RendererThreadPool field trial.
 std::unique_ptr<base::ThreadPool::InitParams>
 GetThreadPoolInitParamsForRenderer();
 
diff --git a/components/thread_pool_util/variations_util_unittest.cc b/components/thread_pool_util/variations_util_unittest.cc
index 13997483..fc23d859 100644
--- a/components/thread_pool_util/variations_util_unittest.cc
+++ b/components/thread_pool_util/variations_util_unittest.cc
@@ -9,8 +9,8 @@
 
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
-#include "base/task/thread_pool/scheduler_worker_params.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
+#include "base/task/thread_pool/thread_group_params.h"
+#include "base/task/thread_pool/worker_thread_params.h"
 #include "components/variations/variations_params_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -25,7 +25,7 @@
   void SetVariationParams(
       const std::map<std::string, std::string>& variation_params) {
     std::set<std::string> features;
-    features.insert(kRendererSchedulerInitParams.name);
+    features.insert(kRendererThreadPoolInitParams.name);
     variation_params_manager_.SetVariationParamsWithFeatureAssociations(
         "DummyTrial", variation_params, features);
   }
@@ -44,28 +44,28 @@
   variation_params["Foreground"] = "4;4;1;0;62";
   SetVariationParams(variation_params);
 
-  auto init_params = GetThreadPoolInitParams(kRendererSchedulerInitParams);
+  auto init_params = GetThreadPoolInitParams(kRendererThreadPoolInitParams);
   ASSERT_TRUE(init_params);
 
-  EXPECT_EQ(1, init_params->background_worker_pool_params.max_tasks());
+  EXPECT_EQ(1, init_params->background_thread_group_params.max_tasks());
   EXPECT_EQ(
       base::TimeDelta::FromMilliseconds(42),
-      init_params->background_worker_pool_params.suggested_reclaim_time());
+      init_params->background_thread_group_params.suggested_reclaim_time());
   EXPECT_EQ(
-      base::SchedulerBackwardCompatibility::DISABLED,
-      init_params->background_worker_pool_params.backward_compatibility());
+      base::WorkerThreadBackwardCompatibility::DISABLED,
+      init_params->background_thread_group_params.backward_compatibility());
 
-  EXPECT_EQ(4, init_params->foreground_worker_pool_params.max_tasks());
+  EXPECT_EQ(4, init_params->foreground_thread_group_params.max_tasks());
   EXPECT_EQ(
       base::TimeDelta::FromMilliseconds(62),
-      init_params->foreground_worker_pool_params.suggested_reclaim_time());
+      init_params->foreground_thread_group_params.suggested_reclaim_time());
   EXPECT_EQ(
-      base::SchedulerBackwardCompatibility::DISABLED,
-      init_params->foreground_worker_pool_params.backward_compatibility());
+      base::WorkerThreadBackwardCompatibility::DISABLED,
+      init_params->foreground_thread_group_params.backward_compatibility());
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, NoData) {
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, IncompleteParameters) {
@@ -73,7 +73,7 @@
   variation_params["Background"] = "1;1;1;0";
   variation_params["Foreground"] = "4;4;1;0";
   SetVariationParams(variation_params);
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, InvalidParametersFormat) {
@@ -81,37 +81,37 @@
   variation_params["Background"] = "a;b;c;d;e";
   variation_params["Foreground"] = "a;b;c;d;e";
   SetVariationParams(variation_params);
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, ZeroMaxThreads) {
-  // The Background pool has a maximum number of threads equal to zero, which is
-  // invalid.
+  // The Background thread group has a maximum number of threads equal to zero,
+  // which is invalid.
   std::map<std::string, std::string> variation_params;
   variation_params["Background"] = "0;0;0;0;0";
   variation_params["Foreground"] = "4;4;1;0;62";
   SetVariationParams(variation_params);
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, NegativeMaxThreads) {
-  // The Background pool has a negative maximum number of threads, which is
-  // invalid.
+  // The Background thread group has a negative maximum number of threads, which
+  // is invalid.
   std::map<std::string, std::string> variation_params;
   variation_params["Background"] = "-5;-5;0;0;0";
   variation_params["Foreground"] = "4;4;1;0;62";
   SetVariationParams(variation_params);
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 TEST_F(ThreadPoolUtilVariationsUtilTest, NegativeSuggestedReclaimTime) {
-  // The Background pool has a negative suggested reclaim time, which is
+  // The Background thread group has a negative suggested reclaim time, which is
   // invalid.
   std::map<std::string, std::string> variation_params;
   variation_params["Background"] = "1;1;1;0;-5";
   variation_params["Foreground"] = "4;4;1;0;62";
   SetVariationParams(variation_params);
-  EXPECT_FALSE(GetThreadPoolInitParams(kRendererSchedulerInitParams));
+  EXPECT_FALSE(GetThreadPoolInitParams(kRendererThreadPoolInitParams));
 }
 
 }  // namespace thread_pool_util
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index 47d39e5..3bcd019 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -155,9 +155,9 @@
   // Utility function to prepare translate_manager_ for testing.
   void PrepareTranslateManager() {
     TranslateManager::SetIgnoreMissingKeyForTesting(true);
-    translate_manager_.reset(new translate::TranslateManager(
+    translate_manager_ = std::make_unique<translate::TranslateManager>(
         &mock_translate_client_, &mock_translate_ranker_,
-        &mock_language_model_));
+        &mock_language_model_);
   }
 
   void SetHasLanguageChanged(bool has_language_changed) {
@@ -357,8 +357,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -393,8 +393,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -429,8 +429,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -472,8 +472,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -523,8 +523,8 @@
   // honored since "enforce_ranker" is "true" in the experiment params.
   mock_translate_ranker_.set_should_offer_translation(false);
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -560,8 +560,8 @@
   // not be honored since "enforce_ranker" is "true" in the experiment params.
   mock_translate_ranker_.set_should_offer_translation(false);
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   base::HistogramTester histogram_tester;
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -589,8 +589,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   // Accept languages shouldn't contain "hi" before translating to that language
   std::vector<std::string> languages;
@@ -630,8 +630,8 @@
   ON_CALL(mock_translate_client_, ShowTranslateUI(_, _, _, _, _))
       .WillByDefault(Return(true));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   // Add a regional variant locale to the list of accepted languages.
   mock_translate_client_.GetTranslatePrefs()->AddToLanguageList("en-US", false);
@@ -668,8 +668,8 @@
   ON_CALL(mock_translate_client_, GetTranslateAcceptLanguages())
       .WillByDefault(Return(&accept_languages));
 
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   // The test measures that the "Translate was disabled" exit can only be
   // reached after the early-out tests including IsOffline() passed.
@@ -874,8 +874,8 @@
 
 TEST_F(TranslateManagerTest, CanManuallyTranslate_PageNeedsTranslation) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
   ON_CALL(mock_translate_client_, IsTranslatableURL(GURL::EmptyGURL()))
@@ -891,8 +891,8 @@
 
 TEST_F(TranslateManagerTest, CanManuallyTranslate_Offline) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
   translate_manager_->GetLanguageState().LanguageDetermined("de", true);
@@ -908,8 +908,8 @@
 
 TEST_F(TranslateManagerTest, CanManuallyTranslate_TranslatableURL) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   translate_manager_->GetLanguageState().LanguageDetermined("de", true);
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
@@ -926,8 +926,8 @@
 
 TEST_F(TranslateManagerTest, CanManuallyTranslate_EmptySourceLanguage) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
   network_notifier_.SimulateOnline();
@@ -941,8 +941,8 @@
 
 TEST_F(TranslateManagerTest, CanManuallyTranslate_UndefinedSourceLanguage) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   prefs_.SetBoolean(prefs::kOfferTranslateEnabled, true);
   network_notifier_.SimulateOnline();
@@ -957,8 +957,8 @@
 
 TEST_F(TranslateManagerTest, PredefinedTargetLanguage) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
 
   manager_->set_application_locale("en");
   ASSERT_TRUE(TranslateDownloadManager::IsSupportedLanguage("en"));
@@ -988,8 +988,8 @@
 
 TEST_F(TranslateManagerTest, PredefinedTargetLanguage_HonourUserSettings) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_));
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
   manager_->set_application_locale("en");
 
   // Add german language to the list of accepted languages.
diff --git a/components/translate/core/browser/translate_prefs_unittest.cc b/components/translate/core/browser/translate_prefs_unittest.cc
index a65c965f..95a33aa 100644
--- a/components/translate/core/browser/translate_prefs_unittest.cc
+++ b/components/translate/core/browser/translate_prefs_unittest.cc
@@ -63,8 +63,8 @@
       : prefs_(new sync_preferences::TestingPrefServiceSyncable()) {
     language::LanguagePrefs::RegisterProfilePrefs(prefs_->registry());
     TranslatePrefs::RegisterProfilePrefs(prefs_->registry());
-    translate_prefs_.reset(new translate::TranslatePrefs(
-        prefs_.get(), kAcceptLanguagesPref, kPreferredLanguagesPref));
+    translate_prefs_ = std::make_unique<translate::TranslatePrefs>(
+        prefs_.get(), kAcceptLanguagesPref, kPreferredLanguagesPref);
     now_ = base::Time::Now();
     two_days_ago_ = now_ - base::TimeDelta::FromDays(2);
   }
diff --git a/components/translate/core/browser/translate_script_unittest.cc b/components/translate/core/browser/translate_script_unittest.cc
index b5596edb..f5cedd00 100644
--- a/components/translate/core/browser/translate_script_unittest.cc
+++ b/components/translate/core/browser/translate_script_unittest.cc
@@ -35,7 +35,7 @@
  protected:
   void SetUp() override {
     variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
-    script_.reset(new TranslateScript);
+    script_ = std::make_unique<TranslateScript>();
     auto* translate_download_manager = TranslateDownloadManager::GetInstance();
     translate_download_manager->set_application_locale("en");
     translate_download_manager->set_url_loader_factory(
diff --git a/components/translate/core/browser/translate_ui_delegate_unittest.cc b/components/translate/core/browser/translate_ui_delegate_unittest.cc
index 42f8d54..69d17ae 100644
--- a/components/translate/core/browser/translate_ui_delegate_unittest.cc
+++ b/components/translate/core/browser/translate_ui_delegate_unittest.cc
@@ -50,8 +50,8 @@
   TranslateUIDelegateTest() {}
 
   void SetUp() override {
-    pref_service_.reset(new sync_preferences::TestingPrefServiceSyncable());
-
+    pref_service_ =
+        std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
     language::LanguagePrefs::RegisterProfilePrefs(pref_service_->registry());
     pref_service_->SetString(language::prefs::kAcceptLanguages, std::string());
 #if defined(OS_CHROMEOS)
@@ -63,15 +63,16 @@
         prefs::kOfferTranslateEnabled, true);
     TranslatePrefs::RegisterProfilePrefs(pref_service_->registry());
 
-    client_.reset(new MockTranslateClient(&driver_, pref_service_.get()));
-    ranker_.reset(new MockTranslateRanker());
-    language_model_.reset(new MockLanguageModel());
-    manager_.reset(new TranslateManager(client_.get(), ranker_.get(),
-                                        language_model_.get()));
+    client_ =
+        std::make_unique<MockTranslateClient>(&driver_, pref_service_.get());
+    ranker_ = std::make_unique<MockTranslateRanker>();
+    language_model_ = std::make_unique<MockLanguageModel>();
+    manager_ = std::make_unique<TranslateManager>(client_.get(), ranker_.get(),
+                                                  language_model_.get());
     manager_->GetLanguageState().set_translation_declined(false);
 
-    delegate_.reset(
-        new TranslateUIDelegate(manager_->GetWeakPtr(), "ar", "fr"));
+    delegate_ = std::make_unique<TranslateUIDelegate>(manager_->GetWeakPtr(),
+                                                      "ar", "fr");
 
     ASSERT_FALSE(client_->GetTranslatePrefs()->IsTooOftenDenied("ar"));
   }
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 078069a4..0cdf417 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -59,10 +59,8 @@
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool IsSurfaceSynchronizationEnabled() {
-  auto* command_line = base::CommandLine::ForCurrentProcess();
   return IsVizDisplayCompositorEnabled() ||
-         base::FeatureList::IsEnabled(kEnableSurfaceSynchronization) ||
-         command_line->HasSwitch(switches::kEnableSurfaceSynchronization);
+         base::FeatureList::IsEnabled(kEnableSurfaceSynchronization);
 }
 
 bool IsVizDisplayCompositorEnabled() {
diff --git a/components/viz/common/switches.cc b/components/viz/common/switches.cc
index 0c9d3c1..939af777 100644
--- a/components/viz/common/switches.cc
+++ b/components/viz/common/switches.cc
@@ -15,17 +15,16 @@
 const char kDeadlineToSynchronizeSurfaces[] =
     "deadline-to-synchronize-surfaces";
 
+// Disables begin frame limiting in both cc scheduler and display scheduler.
+// Also implies --disable-gpu-vsync (see //ui/gl/gl_switches.h).
+const char kDisableFrameRateLimit[] = "disable-frame-rate-limit";
+
 // Enable compositing individual elements via hardware overlays when
 // permitted by device.
 // Setting the flag to "single-fullscreen" will try to promote a single
 // fullscreen overlay and use it as main framebuffer where possible.
 const char kEnableHardwareOverlays[] = "enable-hardware-overlays";
 
-// Enables multi-client Surface synchronization. In practice, this indicates
-// that LayerTreeHost expects to be given a valid viz::LocalSurfaceId provided
-// by the parent compositor.
-const char kEnableSurfaceSynchronization[] = "enable-surface-synchronization";
-
 // Enables inspecting Viz Display Compositor objects. Default port is 9229.
 // For local inspection use chrome://inspect#other
 const char kEnableVizDevTools[] = "enable-viz-devtools";
@@ -42,10 +41,6 @@
 // hit-test data coming from surface layer.
 const char kUseVizHitTestSurfaceLayer[] = "use-viz-hit-test-surface-layer";
 
-// Disables begin frame limiting in both cc scheduler and display scheduler.
-// Also implies --disable-gpu-vsync (see //ui/gl/gl_switches.h).
-const char kDisableFrameRateLimit[] = "disable-frame-rate-limit";
-
 base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)) {
diff --git a/components/viz/common/switches.h b/components/viz/common/switches.h
index 4757fd8..8326b1d 100644
--- a/components/viz/common/switches.h
+++ b/components/viz/common/switches.h
@@ -15,13 +15,12 @@
 
 // Keep list in alphabetical order.
 VIZ_COMMON_EXPORT extern const char kDeadlineToSynchronizeSurfaces[];
+VIZ_COMMON_EXPORT extern const char kDisableFrameRateLimit[];
 VIZ_COMMON_EXPORT extern const char kEnableHardwareOverlays[];
-VIZ_COMMON_EXPORT extern const char kEnableSurfaceSynchronization[];
 VIZ_COMMON_EXPORT extern const char kEnableVizDevTools[];
 VIZ_COMMON_EXPORT extern const char kEnableVizHitTestDebug[];
 VIZ_COMMON_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[];
 VIZ_COMMON_EXPORT extern const char kUseVizHitTestSurfaceLayer[];
-VIZ_COMMON_EXPORT extern const char kDisableFrameRateLimit[];
 
 VIZ_COMMON_EXPORT base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces();
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
index f75e8b80..dc87230e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/test/scoped_feature_list.h"
 #include "cc/test/fake_output_surface_client.h"
@@ -20,18 +19,15 @@
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "components/viz/common/frame_sinks/copy_output_util.h"
 #include "components/viz/service/gl/gpu_service_impl.h"
+#include "components/viz/test/test_gpu_service_holder.h"
 #include "gpu/command_buffer/service/scheduler.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/ipc/gpu_in_process_thread_service.h"
-#include "gpu/ipc/service/gpu_watchdog_thread.h"
 #include "gpu/vulkan/buildflags.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gl/init/gl_factory.h"
 
 #if BUILDFLAG(ENABLE_VULKAN)
-#include "gpu/vulkan/init/vulkan_factory.h"
 #include "gpu/vulkan/tests/native_window.h"
 #include "gpu/vulkan/vulkan_implementation.h"
 #endif
@@ -65,29 +61,15 @@
   void TearDown() override;
   void BlockMainThread();
   void UnblockMainThread();
-  bool is_vulkan_enabled() {
-#if BUILDFLAG(ENABLE_VULKAN)
-    return !!vulkan_implementation_;
-#else
-    return false;
-#endif
-  }
 
-  std::unique_ptr<base::Thread> gpu_thread_;
+  GpuServiceImpl* gpu_service() { return gpu_service_holder_->gpu_service(); }
+
+  std::unique_ptr<TestGpuServiceHolder> gpu_service_holder_;
   std::unique_ptr<SkiaOutputSurfaceImpl> output_surface_;
-  std::unique_ptr<GpuServiceImpl> gpu_service_;
 
  private:
   void SetUpSkiaOutputSurfaceImpl();
-  void TearDownGpuServiceOnGpuThread();
-  void SetUpGpuServiceOnGpuThread();
 
-#if BUILDFLAG(ENABLE_VULKAN)
-  std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation_;
-#endif
-
-  std::unique_ptr<base::Thread> io_thread_;
-  std::unique_ptr<gpu::CommandBufferTaskExecutor> task_executor_;
   std::unique_ptr<cc::FakeOutputSurfaceClient> output_surface_client_;
   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
   base::WaitableEvent wait_;
@@ -103,81 +85,10 @@
   wait_.Signal();
 }
 
-void SkiaOutputSurfaceImplTest::SetUpGpuServiceOnGpuThread() {
-  ASSERT_TRUE(gpu_thread_->task_runner()->BelongsToCurrentThread());
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  gpu::GpuPreferences gpu_preferences =
-      gpu::gles2::ParseGpuPreferences(command_line);
-  if (gpu_preferences.enable_vulkan) {
-#if BUILDFLAG(ENABLE_VULKAN)
-    vulkan_implementation_ = gpu::CreateVulkanImplementation();
-    if (!vulkan_implementation_ ||
-        !vulkan_implementation_->InitializeVulkanInstance(
-            !gpu_preferences.disable_vulkan_surface)) {
-      LOG(FATAL) << "Failed to create and initialize Vulkan implementation.";
-    }
-#else
-    NOTREACHED();
-#endif
-  }
-  gpu_service_ = std::make_unique<GpuServiceImpl>(
-      gpu::GPUInfo(), nullptr /* watchdog_thread */, io_thread_->task_runner(),
-      gpu::GpuFeatureInfo(), gpu_preferences,
-      gpu::GPUInfo() /* gpu_info_for_hardware_gpu */,
-      gpu::GpuFeatureInfo() /* gpu_feature_info_for_hardware_gpu */,
-#if BUILDFLAG(ENABLE_VULKAN)
-      vulkan_implementation_.get(),
-#else
-      nullptr /* vulkan_implementation */,
-#endif
-      base::DoNothing() /* exit_callback */);
-
-  // Uses a null gpu_host here, because we don't want to receive any message.
-  std::unique_ptr<mojom::GpuHost> gpu_host;
-  mojom::GpuHostPtr gpu_host_proxy;
-  mojo::MakeStrongBinding(std::move(gpu_host),
-                          mojo::MakeRequest(&gpu_host_proxy));
-  gpu_service_->InitializeWithHost(
-      std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
-      gl::init::CreateOffscreenGLSurface(gfx::Size()),
-      nullptr /* sync_point_manager */, nullptr /* shared_image_manager */,
-      nullptr /* shutdown_event */);
-  task_executor_ = std::make_unique<gpu::GpuInProcessThreadService>(
-      gpu_thread_->task_runner(), gpu_service_->scheduler(),
-      gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
-      gpu_service_->share_group(),
-      gpu_service_->gpu_channel_manager()
-          ->default_offscreen_surface()
-          ->GetFormat(),
-      gpu_service_->gpu_feature_info(),
-      gpu_service_->gpu_channel_manager()->gpu_preferences(),
-      gpu_service_->shared_image_manager(),
-      gpu_service_->gpu_channel_manager()->program_cache());
-  UnblockMainThread();
-}
-
-void SkiaOutputSurfaceImplTest::TearDownGpuServiceOnGpuThread() {
-  task_executor_.reset();
-  gpu_service_ = nullptr;
-  UnblockMainThread();
-}
-
 void SkiaOutputSurfaceImplTest::TearDown() {
-  output_surface_ = nullptr;
-
-  if (task_executor_) {
-    // Tear down the GPU service.
-    gpu_thread_->task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &SkiaOutputSurfaceImplTest::TearDownGpuServiceOnGpuThread,
-            base::Unretained(this)));
-    BlockMainThread();
-  }
-  io_thread_ = nullptr;
-  gpu_thread_ = nullptr;
-  scoped_feature_list_ = nullptr;
+  output_surface_.reset();
+  gpu_service_holder_.reset();
+  scoped_feature_list_.reset();
 }
 
 void SkiaOutputSurfaceImplTest::SetUpSkiaOutputSurfaceImpl() {
@@ -186,18 +97,7 @@
   const char disable_features[] = "";
   scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
   scoped_feature_list_->InitFromCommandLine(enable_features, disable_features);
-
-  // Set up the GPU service.
-  gpu_thread_ = std::make_unique<base::Thread>("GPUMainThread");
-  ASSERT_TRUE(gpu_thread_->Start());
-  io_thread_ = std::make_unique<base::Thread>("GPUIOThread");
-  ASSERT_TRUE(io_thread_->Start());
-
-  gpu_thread_->task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&SkiaOutputSurfaceImplTest::SetUpGpuServiceOnGpuThread,
-                     base::Unretained(this)));
-  BlockMainThread();
+  gpu_service_holder_ = std::make_unique<TestGpuServiceHolder>();
 
   // Set up the SkiaOutputSurfaceImpl.
   gpu::SurfaceHandle surface_handle_ = gpu::kNullSurfaceHandle;
@@ -210,14 +110,14 @@
 #endif
   }
   output_surface_ = std::make_unique<SkiaOutputSurfaceImpl>(
-      gpu_service_.get(), surface_handle_, RendererSettings());
+      gpu_service(), surface_handle_, RendererSettings());
   output_surface_->BindToClient(output_surface_client_.get());
 }
 
 void SkiaOutputSurfaceImplTest::CheckSyncTokenOnGpuThread(
     const gpu::SyncToken& sync_token) {
   EXPECT_TRUE(
-      gpu_service_->sync_point_manager()->IsSyncTokenReleased(sync_token));
+      gpu_service()->sync_point_manager()->IsSyncTokenReleased(sync_token));
   UnblockMainThread();
 }
 
@@ -255,7 +155,7 @@
 
 TEST_P(SkiaOutputSurfaceImplTest, SubmitPaint) {
   output_surface_->Reshape(kSurfaceRect.size(), 1, gfx::ColorSpace(),
-                           false /* has_alpha */, false /* use_stencil */);
+                           /*has_alpha=*/false, /*use_stencil=*/false);
   SkCanvas* root_canvas = output_surface_->BeginPaintCurrentFrame();
   SkPaint paint;
   const SkColor output_color = SK_ColorRED;
@@ -272,8 +172,8 @@
 
   std::vector<gpu::SyncToken> resource_sync_tokens;
   resource_sync_tokens.push_back(sync_token);
-  auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
-  gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+  auto sequence_id = gpu_service()->skia_output_surface_sequence_id();
+  gpu_service()->scheduler()->ScheduleTask(gpu::Scheduler::Task(
       sequence_id, std::move(closure), std::move(resource_sync_tokens)));
   BlockMainThread();
 
@@ -284,13 +184,14 @@
       base::BindOnce(&SkiaOutputSurfaceImplTest::CopyRequestCallbackOnGpuThread,
                      base::Unretained(this), output_color, output_rect,
                      color_space));
-  request->set_result_task_runner(gpu_thread_->task_runner());
+  request->set_result_task_runner(
+      gpu_service_holder_->gpu_thread_task_runner());
   copy_output::RenderPassGeometry geometry;
   geometry.result_bounds = kSurfaceRect;
   geometry.result_selection = output_rect;
   geometry.sampling_bounds = kSurfaceRect;
 
-  if (is_vulkan_enabled()) {
+  if (gpu_service_holder_->is_vulkan_enabled()) {
     // No flipping because Skia handles all co-ordinate transformation on the
     // software readback path currently implemented for Vulkan.
     geometry.readback_offset = geometry.readback_offset = gfx::Vector2d(0, 0);
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index 86618d6..5ccd380 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//components/viz/viz.gni")
+import("//gpu/vulkan/features.gni")
 
 viz_static_library("test_support") {
   testonly = true
@@ -58,6 +59,8 @@
     "test_gles2_interface.h",
     "test_gpu_memory_buffer_manager.cc",
     "test_gpu_memory_buffer_manager.h",
+    "test_gpu_service_holder.cc",
+    "test_gpu_service_holder.h",
     "test_latest_local_surface_id_lookup_delegate.cc",
     "test_latest_local_surface_id_lookup_delegate.h",
     "test_layer_tree_frame_sink.cc",
@@ -83,6 +86,10 @@
     "//ui/gl",
     "//ui/latency:test_support",
   ]
+
+  if (enable_vulkan) {
+    deps += [ "//gpu/vulkan/init" ]
+  }
 }
 
 viz_source_set("test_suite") {
diff --git a/components/viz/test/DEPS b/components/viz/test/DEPS
index 4cd834a1..142eb8b 100644
--- a/components/viz/test/DEPS
+++ b/components/viz/test/DEPS
@@ -39,4 +39,17 @@
   "run_all_unittests\.cc": [
     "+mojo/core/embedder/embedder.h",
   ],
+
+  "test_gpu_service_holder\.h": [
+    "+gpu/vulkan/buildflags.h",
+  ],
+
+  "test_gpu_service_holder\.cc": [
+    "+gpu/command_buffer/service/service_utils.h",
+    "+gpu/config",
+    "+gpu/ipc/gpu_in_process_thread_service.h",
+    "+gpu/ipc/service/gpu_watchdog_thread.h",
+    "+gpu/vulkan/init/vulkan_factory.h",
+    "+gpu/vulkan/vulkan_implementation.h",
+  ],
 }
diff --git a/components/viz/test/test_gpu_service_holder.cc b/components/viz/test/test_gpu_service_holder.cc
new file mode 100644
index 0000000..479af56
--- /dev/null
+++ b/components/viz/test/test_gpu_service_holder.cc
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/test/test_gpu_service_holder.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/viz/service/gl/gpu_service_impl.h"
+#include "gpu/command_buffer/service/service_utils.h"
+#include "gpu/config/gpu_feature_info.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_preferences.h"
+#include "gpu/config/gpu_util.h"
+#include "gpu/ipc/gpu_in_process_thread_service.h"
+#include "gpu/ipc/service/gpu_watchdog_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "ui/gl/init/gl_factory.h"
+
+#if BUILDFLAG(ENABLE_VULKAN)
+#include "gpu/vulkan/init/vulkan_factory.h"
+#include "gpu/vulkan/vulkan_implementation.h"
+#endif
+
+namespace viz {
+
+TestGpuServiceHolder::TestGpuServiceHolder()
+    : gpu_thread_("GPUMainThread"), io_thread_("GPUIOThread") {
+  CHECK(gpu_thread_.Start());
+  CHECK(io_thread_.Start());
+
+  base::WaitableEvent completion;
+  gpu_thread_.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&TestGpuServiceHolder::InitializeOnGpuThread,
+                                base::Unretained(this), &completion));
+  completion.Wait();
+}
+
+TestGpuServiceHolder::~TestGpuServiceHolder() {
+  // Ensure members created on GPU thread are destroyed there too.
+  gpu_thread_.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&TestGpuServiceHolder::DeleteOnGpuThread,
+                                base::Unretained(this)));
+  gpu_thread_.Stop();
+  io_thread_.Stop();
+}
+
+void TestGpuServiceHolder::InitializeOnGpuThread(
+    base::WaitableEvent* completion) {
+  DCHECK(gpu_thread_.task_runner()->BelongsToCurrentThread());
+  auto* command_line = base::CommandLine::ForCurrentProcess();
+  gpu::GpuPreferences gpu_preferences =
+      gpu::gles2::ParseGpuPreferences(command_line);
+
+  if (gpu_preferences.enable_vulkan) {
+#if BUILDFLAG(ENABLE_VULKAN)
+    vulkan_implementation_ = gpu::CreateVulkanImplementation();
+    if (!vulkan_implementation_ ||
+        !vulkan_implementation_->InitializeVulkanInstance(
+            !gpu_preferences.disable_vulkan_surface)) {
+      LOG(FATAL) << "Failed to create and initialize Vulkan implementation.";
+    }
+#else
+    NOTREACHED();
+#endif
+  }
+  // TODO(sgilhuly): Investigate why creating a GPUInfo and GpuFeatureInfo from
+  // the command line causes the test SkiaOutputSurfaceImplTest.SubmitPaint to
+  // fail on Android.
+  gpu_service_ = std::make_unique<GpuServiceImpl>(
+      gpu::GPUInfo(), /*watchdog_thread=*/nullptr, io_thread_.task_runner(),
+      gpu::GpuFeatureInfo(), gpu_preferences,
+      /*gpu_info_for_hardware_gpu=*/gpu::GPUInfo(),
+      /*gpu_feature_info_for_hardware_gpu=*/gpu::GpuFeatureInfo(),
+#if BUILDFLAG(ENABLE_VULKAN)
+      vulkan_implementation_.get(),
+#else
+      /*vulkan_implementation=*/nullptr,
+#endif
+      /*exit_callback=*/base::DoNothing());
+
+  // Use a disconnected mojo pointer, we don't need to receive any messages.
+  mojom::GpuHostPtr gpu_host_proxy;
+  mojo::MakeRequest(&gpu_host_proxy);
+  gpu_service_->InitializeWithHost(
+      std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
+      gl::init::CreateOffscreenGLSurface(gfx::Size()),
+      /*sync_point_manager=*/nullptr, /*shared_image_manager=*/nullptr,
+      /*shutdown_event=*/nullptr);
+  task_executor_ = std::make_unique<gpu::GpuInProcessThreadService>(
+      gpu_thread_.task_runner(), gpu_service_->scheduler(),
+      gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
+      gpu_service_->share_group(),
+      gpu_service_->gpu_channel_manager()
+          ->default_offscreen_surface()
+          ->GetFormat(),
+      gpu_service_->gpu_feature_info(),
+      gpu_service_->gpu_channel_manager()->gpu_preferences(),
+      gpu_service_->shared_image_manager(),
+      gpu_service_->gpu_channel_manager()->program_cache());
+
+  completion->Signal();
+}
+
+void TestGpuServiceHolder::DeleteOnGpuThread() {
+  task_executor_.reset();
+  gpu_service_.reset();
+}
+
+}  // namespace viz
diff --git a/components/viz/test/test_gpu_service_holder.h b/components/viz/test/test_gpu_service_holder.h
new file mode 100644
index 0000000..6a296a9
--- /dev/null
+++ b/components/viz/test/test_gpu_service_holder.h
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_TEST_TEST_GPU_SERVICE_HOLDER_H_
+#define COMPONENTS_VIZ_TEST_TEST_GPU_SERVICE_HOLDER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/threading/thread.h"
+#include "gpu/vulkan/buildflags.h"
+
+namespace gpu {
+class CommandBufferTaskExecutor;
+#if BUILDFLAG(ENABLE_VULKAN)
+class VulkanImplementation;
+#endif
+}  // namespace gpu
+
+namespace viz {
+class GpuServiceImpl;
+
+// Starts GPU Main and IO threads, and creates a GpuServiceImpl that can be used
+// to create a SkiaOutputSurfaceImpl. This isn't a full GPU service
+// implementation and should only be used in tests. GpuPreferences will be
+// constructed from the command line when this class is first created.
+class TestGpuServiceHolder {
+ public:
+  TestGpuServiceHolder();
+  ~TestGpuServiceHolder();
+
+  scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_task_runner() {
+    return gpu_thread_.task_runner();
+  }
+
+  // Most of |gpu_service_| is not safe to use off of the GPU thread, be careful
+  // when accessing this.
+  GpuServiceImpl* gpu_service() { return gpu_service_.get(); }
+
+  gpu::CommandBufferTaskExecutor* task_executor() {
+    return task_executor_.get();
+  }
+
+  bool is_vulkan_enabled() {
+#if BUILDFLAG(ENABLE_VULKAN)
+    return !!vulkan_implementation_;
+#else
+    return false;
+#endif
+  }
+
+ private:
+  void InitializeOnGpuThread(base::WaitableEvent* completion);
+  void DeleteOnGpuThread();
+
+  base::Thread gpu_thread_;
+  base::Thread io_thread_;
+
+  // These should only be created and deleted on the gpu thread.
+  std::unique_ptr<GpuServiceImpl> gpu_service_;
+  std::unique_ptr<gpu::CommandBufferTaskExecutor> task_executor_;
+#if BUILDFLAG(ENABLE_VULKAN)
+  std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(TestGpuServiceHolder);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_TEST_TEST_GPU_SERVICE_HOLDER_H_
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index fe57a75..6a1d8bb 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -1234,13 +1234,6 @@
   // so this cannot happen any earlier than now.
   InitializeMojo();
 
-#if BUILDFLAG(ENABLE_MUS)
-  if (features::IsUsingWindowService()) {
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kEnableSurfaceSynchronization);
-  }
-#endif
-
   HistogramSynchronizer::GetInstance();
 
   // cc assumes a single client name for metrics in a process, which is
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index 0c91d65..55719f8 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -313,6 +313,13 @@
 
 void VizProcessTransportFactory::DisableGpuCompositing(
     ui::Compositor* guilty_compositor) {
+#if defined(OS_CHROMEOS)
+  ALLOW_UNUSED_LOCAL(compositing_mode_reporter_);
+  // A fatal error has occurred and we can't fall back to software compositing
+  // on CrOS. These can be unrecoverable hardware errors, or bugs that should
+  // not happen. Crash the browser process to reset everything.
+  LOG(FATAL) << "Software compositing fallback is unavailable. Goodbye.";
+#else
   DLOG(ERROR) << "Switching to software compositing.";
 
   // Change the result of IsGpuCompositingDisabled() before notifying anything.
@@ -354,6 +361,7 @@
   }
 
   GpuDataManagerImpl::GetInstance()->NotifyGpuInfoUpdate();
+#endif
 }
 
 void VizProcessTransportFactory::OnGpuProcessLost() {
diff --git a/content/browser/devtools/devtools_background_services_context.cc b/content/browser/devtools/devtools_background_services_context.cc
index d46e3d6..a133852 100644
--- a/content/browser/devtools/devtools_background_services_context.cc
+++ b/content/browser/devtools/devtools_background_services_context.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/guid.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
@@ -31,12 +32,12 @@
 
 void DidLogServiceEvent(blink::ServiceWorkerStatusCode status) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  // TODO(rayankans): Log errors to UMA.
+  UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.LogEvent", status);
 }
 
 void DidClearServiceEvents(blink::ServiceWorkerStatusCode status) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  // TODO(rayankans): Log errors to UMA.
+  UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.ClearEvents", status);
 }
 
 }  // namespace
@@ -148,10 +149,11 @@
     blink::ServiceWorkerStatusCode status) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  UMA_HISTOGRAM_ENUMERATION("DevTools.BackgroundService.GetEvents", status);
+
   std::vector<devtools::proto::BackgroundServiceEvent> events;
 
   if (status != blink::ServiceWorkerStatusCode::kOk) {
-    // TODO(rayankans): Log errors to UMA.
     std::move(callback).Run(events);
     return;
   }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 5eb0746..2e00a540 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1049,13 +1049,15 @@
 void RenderFrameHostImpl::OnPortalActivated(
     const base::UnguessableToken& portal_token,
     blink::mojom::PortalAssociatedPtrInfo portal,
+    blink::mojom::PortalClientAssociatedRequest portal_client,
     blink::TransferableMessage data,
     base::OnceCallback<void(bool)> callback) {
   GetNavigationControl()->OnPortalActivated(
-      portal_token, std::move(portal), std::move(data), std::move(callback));
+      portal_token, std::move(portal), std::move(portal_client),
+      std::move(data), std::move(callback));
 }
 
-void RenderFrameHostImpl::ForwardMessageToPortalHost(
+void RenderFrameHostImpl::ForwardMessageFromHost(
     blink::TransferableMessage message,
     const url::Origin& source_origin,
     const base::Optional<url::Origin>& target_origin) {
@@ -1063,12 +1065,11 @@
   // navigated after the postMessage call, or if the renderer is compromised and
   // the check done in PortalHost::ReceiveMessage is bypassed.
   if (target_origin) {
-    DCHECK(!target_origin->opaque());
     if (target_origin != GetLastCommittedOrigin())
       return;
   }
-  GetNavigationControl()->ForwardMessageToPortalHost(
-      std::move(message), source_origin, target_origin);
+  GetNavigationControl()->ForwardMessageFromHost(std::move(message),
+                                                 source_origin, target_origin);
 }
 
 SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
@@ -3824,13 +3825,15 @@
 
 void RenderFrameHostImpl::CreatePortal(
     blink::mojom::PortalAssociatedRequest request,
+    blink::mojom::PortalClientAssociatedPtrInfo client,
     CreatePortalCallback callback) {
+  // We don't support attaching a portal inside a nested browsing context.
   if (frame_tree_node()->parent()) {
     mojo::ReportBadMessage(
         "RFHI::CreatePortal called in a nested browsing context");
     return;
   }
-  Portal* portal = Portal::Create(this, std::move(request));
+  Portal* portal = Portal::Create(this, std::move(request), std::move(client));
   RenderFrameProxyHost* proxy_host = portal->CreateProxyAndAttachPortal();
   std::move(callback).Run(proxy_host->GetRoutingID(), portal->portal_token(),
                           portal->GetDevToolsFrameToken());
@@ -4961,6 +4964,9 @@
   associated_registry_->AddInterface(
       base::BindRepeating(make_binding, base::Unretained(this)));
 
+  associated_registry_->AddInterface(base::BindRepeating(
+      &Portal::BindPortalHostRequest, base::Unretained(this)));
+
   RegisterMojoInterfaces();
   mojom::FrameFactoryPtr frame_factory;
   BindInterface(GetProcess(), &frame_factory);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 7aeb47c..636f320 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -868,17 +868,18 @@
   // identified by |portal_token| with the interface |portal|. The activation
   // can optionally include a message |data| dispatched with the
   // PortalActivateEvent.
-  void OnPortalActivated(const base::UnguessableToken& portal_token,
-                         blink::mojom::PortalAssociatedPtrInfo portal,
-                         blink::TransferableMessage data,
-                         base::OnceCallback<void(bool)> callback);
+  void OnPortalActivated(
+      const base::UnguessableToken& portal_token,
+      blink::mojom::PortalAssociatedPtrInfo portal,
+      blink::mojom::PortalClientAssociatedRequest portal_client,
+      blink::TransferableMessage data,
+      base::OnceCallback<void(bool)> callback);
 
   // Called on the main frame of a page embedded in a Portal to forward a
-  // message to the PortalHost object in the frame.
-  void ForwardMessageToPortalHost(
-      blink::TransferableMessage message,
-      const url::Origin& source_origin,
-      const base::Optional<url::Origin>& target_origin);
+  // message from the host of a portal.
+  void ForwardMessageFromHost(blink::TransferableMessage message,
+                              const url::Origin& source_origin,
+                              const base::Optional<url::Origin>& target_origin);
 
   // mojom::FrameHost:
   void VisibilityChanged(blink::mojom::FrameVisibility) override;
@@ -1161,6 +1162,7 @@
   void CreateNewWindow(mojom::CreateNewWindowParamsPtr params,
                        CreateNewWindowCallback callback) override;
   void CreatePortal(blink::mojom::PortalAssociatedRequest request,
+                    blink::mojom::PortalClientAssociatedPtrInfo client,
                     CreatePortalCallback callback) override;
   void AdoptPortal(const base::UnguessableToken& portal_token,
                    AdoptPortalCallback callback) override;
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index 77468a35..6701bbd 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -35,7 +35,8 @@
     : WebContentsObserver(
           WebContents::FromRenderFrameHost(owner_render_frame_host)),
       owner_render_frame_host_(owner_render_frame_host),
-      portal_token_(base::UnguessableToken::Create()) {
+      portal_token_(base::UnguessableToken::Create()),
+      portal_host_binding_(this) {
   auto pair = g_portal_token_map.Get().emplace(portal_token_, this);
   DCHECK(pair.second);
 }
@@ -64,11 +65,13 @@
 
 // static
 Portal* Portal::Create(RenderFrameHostImpl* owner_render_frame_host,
-                       blink::mojom::PortalAssociatedRequest request) {
+                       blink::mojom::PortalAssociatedRequest request,
+                       blink::mojom::PortalClientAssociatedPtrInfo client) {
   auto portal_ptr = base::WrapUnique(new Portal(owner_render_frame_host));
   Portal* portal = portal_ptr.get();
   portal->binding_ = mojo::MakeStrongAssociatedBinding(std::move(portal_ptr),
                                                        std::move(request));
+  portal->client_ = blink::mojom::PortalClientAssociatedPtr(std::move(client));
   return portal;
 }
 
@@ -78,6 +81,33 @@
   return base::WrapUnique(new Portal(owner_render_frame_host));
 }
 
+// static
+void Portal::BindPortalHostRequest(
+    RenderFrameHostImpl* frame,
+    blink::mojom::PortalHostAssociatedRequest request) {
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame));
+
+  // This guards against the blink::mojom::PortalHost interface being used
+  // outside the main frame of a Portal's guest.
+  if (!web_contents || !web_contents->IsPortal() ||
+      !frame->frame_tree_node()->IsMainFrame()) {
+    mojo::ReportBadMessage(
+        "blink.mojom.PortalHost can only be used by the the main frame of a "
+        "Portal's guest.");
+    return;
+  }
+
+  // This binding may already be bound to another request, and in such cases,
+  // we rebind with the new request. An example scenario is a new document after
+  // a portal navigation trying to create a connection, but the old document
+  // hasn't been destroyed yet (and the pipe hasn't been closed).
+  auto& binding = web_contents->portal()->portal_host_binding_;
+  if (binding.is_bound())
+    binding.Close();
+  binding.Bind(std::move(request));
+}
+
 RenderFrameProxyHost* Portal::CreateProxyAndAttachPortal() {
   WebContentsImpl* outer_contents_impl = static_cast<WebContentsImpl*>(
       WebContents::FromRenderFrameHost(owner_render_frame_host_));
@@ -165,24 +195,41 @@
   portal_contents_impl_->set_portal(nullptr);
 
   blink::mojom::PortalAssociatedPtr portal_ptr;
-  Portal* portal = Create(portal_contents_impl_->GetMainFrame(),
-                          mojo::MakeRequest(&portal_ptr));
+  blink::mojom::PortalClientAssociatedPtr portal_client_ptr;
+  auto portal_client_request = mojo::MakeRequest(&portal_client_ptr);
+  Portal* portal =
+      Create(portal_contents_impl_->GetMainFrame(),
+             mojo::MakeRequest(&portal_ptr), portal_client_ptr.PassInterface());
   portal->SetPortalContents(std::move(predecessor_web_contents));
 
   portal_contents_impl_->GetMainFrame()->OnPortalActivated(
-      portal->portal_token_, portal_ptr.PassInterface(), std::move(data),
-      std::move(callback));
+      portal->portal_token_, portal_ptr.PassInterface(),
+      std::move(portal_client_request), std::move(data), std::move(callback));
 
   devtools_instrumentation::PortalActivated(outer_contents->GetMainFrame());
 }
 
-void Portal::PostMessage(blink::TransferableMessage message,
-                         const base::Optional<url::Origin>& target_origin) {
-  portal_contents_impl_->GetMainFrame()->ForwardMessageToPortalHost(
+void Portal::PostMessageToGuest(
+    blink::TransferableMessage message,
+    const base::Optional<url::Origin>& target_origin) {
+  portal_contents_impl_->GetMainFrame()->ForwardMessageFromHost(
       std::move(message), owner_render_frame_host_->GetLastCommittedOrigin(),
       target_origin);
 }
 
+void Portal::PostMessageToHost(
+    const std::string& message,
+    const base::Optional<url::Origin>& target_origin) {
+  DCHECK(GetPortalContents());
+  if (target_origin) {
+    if (target_origin != owner_render_frame_host_->GetLastCommittedOrigin())
+      return;
+  }
+  client().ForwardMessageFromGuest(
+      message, GetPortalContents()->GetMainFrame()->GetLastCommittedOrigin(),
+      target_origin);
+}
+
 void Portal::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
   if (render_frame_host == owner_render_frame_host_)
     binding_->Close();  // Also deletes |this|.
@@ -212,6 +259,11 @@
   binding_ = binding;
 }
 
+void Portal::SetClientForTesting(
+    blink::mojom::PortalClientAssociatedPtr client) {
+  client_ = std::move(client);
+}
+
 void Portal::SetPortalContents(std::unique_ptr<WebContents> web_contents) {
   portal_contents_ = std::move(web_contents);
   portal_contents_impl_ = static_cast<WebContentsImpl*>(portal_contents_.get());
diff --git a/content/browser/portal/portal.h b/content/browser/portal/portal.h
index 5b2a671a..45af59d 100644
--- a/content/browser/portal/portal.h
+++ b/content/browser/portal/portal.h
@@ -30,6 +30,7 @@
 // The Portal is owned by its mojo binding, so it is kept alive as long as the
 // other end of the pipe (typically in the renderer) exists.
 class CONTENT_EXPORT Portal : public blink::mojom::Portal,
+                              public blink::mojom::PortalHost,
                               public WebContentsObserver,
                               public WebContentsDelegate {
  public:
@@ -43,12 +44,17 @@
   // function creates a strong binding, so the ownership of the Portal is
   // delegated to the binding.
   static Portal* Create(RenderFrameHostImpl* owner_render_frame_host,
-                        blink::mojom::PortalAssociatedRequest request);
+                        blink::mojom::PortalAssociatedRequest request,
+                        blink::mojom::PortalClientAssociatedPtrInfo client);
 
   // Creates a portal without binding it to any pipe. Only used in tests.
   static std::unique_ptr<Portal> CreateForTesting(
       RenderFrameHostImpl* owner_render_frame_host);
 
+  static void BindPortalHostRequest(
+      RenderFrameHostImpl* frame,
+      blink::mojom::PortalHostAssociatedRequest request);
+
   // Called from a synchronous IPC from the renderer process in order to create
   // the proxy.
   RenderFrameProxyHost* CreateProxyAndAttachPortal();
@@ -57,8 +63,14 @@
   void Navigate(const GURL& url) override;
   void Activate(blink::TransferableMessage data,
                 ActivateCallback callback) override;
-  void PostMessage(const blink::TransferableMessage message,
-                   const base::Optional<url::Origin>& target_origin) override;
+  void PostMessageToGuest(
+      const blink::TransferableMessage message,
+      const base::Optional<url::Origin>& target_origin) override;
+
+  // blink::mojom::PortalHost implementation
+  void PostMessageToHost(
+      const std::string& message,
+      const base::Optional<url::Origin>& target_origin) override;
 
   // WebContentsObserver overrides.
   void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
@@ -87,6 +99,9 @@
   }
   void SetBindingForTesting(
       mojo::StrongAssociatedBindingPtr<blink::mojom::Portal> binding);
+  void SetClientForTesting(blink::mojom::PortalClientAssociatedPtr client);
+
+  blink::mojom::PortalClient& client() { return *client_; }
 
  private:
   explicit Portal(RenderFrameHostImpl* owner_render_frame_host);
@@ -102,6 +117,13 @@
   // WeakPtr to StrongBinding.
   mojo::StrongAssociatedBindingPtr<blink::mojom::Portal> binding_;
 
+  // Receives messages from the inner render process.
+  mojo::AssociatedBinding<blink::mojom::PortalHost> portal_host_binding_;
+
+  // Used to communicate with the HTMLPortalElement in the renderer that
+  // hosts this Portal.
+  blink::mojom::PortalClientAssociatedPtr client_;
+
   // When the portal is not attached, the Portal owns its WebContents.
   std::unique_ptr<WebContents> portal_contents_;
 
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index 7231cc8..a3f3892 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -42,7 +42,8 @@
  public:
   static PortalInterceptorForTesting* Create(
       RenderFrameHostImpl* render_frame_host_impl,
-      blink::mojom::PortalAssociatedRequest request);
+      blink::mojom::PortalAssociatedRequest request,
+      blink::mojom::PortalClientAssociatedPtr client);
   static PortalInterceptorForTesting* From(content::Portal* portal);
 
   void Activate(blink::TransferableMessage data,
@@ -87,13 +88,15 @@
 // static
 PortalInterceptorForTesting* PortalInterceptorForTesting::Create(
     RenderFrameHostImpl* render_frame_host_impl,
-    blink::mojom::PortalAssociatedRequest request) {
+    blink::mojom::PortalAssociatedRequest request,
+    blink::mojom::PortalClientAssociatedPtr client) {
   auto test_portal_ptr =
       base::WrapUnique(new PortalInterceptorForTesting(render_frame_host_impl));
   PortalInterceptorForTesting* test_portal = test_portal_ptr.get();
   test_portal->GetPortal()->SetBindingForTesting(
       mojo::MakeStrongAssociatedBinding(std::move(test_portal_ptr),
                                         std::move(request)));
+  test_portal->GetPortal()->SetClientForTesting(std::move(client));
   return test_portal;
 }
 
@@ -126,10 +129,12 @@
   }
 
   void CreatePortal(blink::mojom::PortalAssociatedRequest request,
+                    blink::mojom::PortalClientAssociatedPtrInfo client,
                     CreatePortalCallback callback) override {
     PortalInterceptorForTesting* portal_interceptor =
-        PortalInterceptorForTesting::Create(render_frame_host_impl_,
-                                            std::move(request));
+        PortalInterceptorForTesting::Create(
+            render_frame_host_impl_, std::move(request),
+            blink::mojom::PortalClientAssociatedPtr(std::move(client)));
     portal_ = portal_interceptor->GetPortal();
     RenderFrameProxyHost* proxy_host = portal_->CreateProxyAndAttachPortal();
     std::move(callback).Run(proxy_host->GetRoutingID(), portal_->portal_token(),
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
index 170efa1..dd26e35 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
@@ -44,10 +44,10 @@
 
 // static
 const base::FeatureParam<std::string>
-    PassthroughTouchEventQueue::kSkipBrowserTouchFilterType{
-        &features::kSkipBrowserTouchFilter,
-        features::kSkipBrowserTouchFilterTypeParamName,
-        features::kSkipBrowserTouchFilterTypeParamValueDiscrete};
+    PassthroughTouchEventQueue::kSkipTouchEventFilterType{
+        &features::kSkipTouchEventFilter,
+        features::kSkipTouchEventFilterTypeParamName,
+        features::kSkipTouchEventFilterTypeParamValueDiscrete};
 
 PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState::
     TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event)
@@ -322,13 +322,13 @@
 
 bool PassthroughTouchEventQueue::ShouldFilterForEvent(
     const blink::WebTouchEvent& event) {
-  // Always run all filtering if the SkipBrowserTouchFilter is disabled.
+  // Always run all filtering if the SkipTouchEventFilter is disabled.
   if (!skip_touch_filter_)
     return true;
   // If the experiment is enabled and all events are forwarded, always skip
   // filtering.
   if (events_to_always_forward_ ==
-      features::kSkipBrowserTouchFilterTypeParamValueAll)
+      features::kSkipTouchEventFilterTypeParamValueAll)
     return false;
   // If the experiment is enabled and only discrete events are forwarded,
   // always run filtering for touchmove events only.
@@ -356,7 +356,7 @@
     drop_remaining_touches_in_sequence_ = false;
     if (!has_handlers_) {
       drop_remaining_touches_in_sequence_ = true;
-      // If the SkipBrowserTouchFilter experiment is running, drop through to
+      // If the SkipTouchEventFilter experiment is running, drop through to
       // the loop that filters events with no nonstationary pointers below.
       if (ShouldFilterForEvent(event))
         return PreFilterResult::kFilteredNoPageHandlers;
@@ -365,7 +365,7 @@
 
   if (drop_remaining_touches_in_sequence_ &&
       event.GetType() != WebInputEvent::kTouchCancel &&
-      // If the SkipBrowserTouchFilter experiment is running, drop through to
+      // If the SkipTouchEventFilter experiment is running, drop through to
       // the loop that filters events with no nonstationary pointers below.
       ShouldFilterForEvent(event))
     return PreFilterResult::kFilteredNoPageHandlers;
@@ -373,7 +373,7 @@
   if (event.GetType() == WebInputEvent::kTouchStart) {
     if (has_handlers_ || maybe_has_handler_for_current_sequence_)
       return PreFilterResult::kUnfiltered;
-    // If the SkipBrowserTouchFilter experiment is running, drop through to
+    // If the SkipTouchEventFilter experiment is running, drop through to
     // the loop that filters events with no nonstationary pointers below.
     else if (ShouldFilterForEvent(event))
       return PreFilterResult::kFilteredNoPageHandlers;
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.h b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
index 35330cb..3399455 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue.h
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
@@ -60,8 +60,8 @@
               base::TimeDelta::FromMilliseconds(1000)),
           touch_ack_timeout_supported(false),
           skip_touch_filter(
-              base::FeatureList::IsEnabled(features::kSkipBrowserTouchFilter)),
-          events_to_always_forward(kSkipBrowserTouchFilterType.Get()) {}
+              base::FeatureList::IsEnabled(features::kSkipTouchEventFilter)),
+          events_to_always_forward(kSkipTouchEventFilterType.Get()) {}
 
     // Touch ack timeout delay for desktop sites. If zero, timeout behavior
     // is disabled for such sites. Defaults to 200ms.
@@ -242,7 +242,7 @@
   const bool skip_touch_filter_;
   // What events types are allowed to bypass the filter.
   const std::string events_to_always_forward_;
-  static const base::FeatureParam<std::string> kSkipBrowserTouchFilterType;
+  static const base::FeatureParam<std::string> kSkipTouchEventFilterType;
 
   DISALLOW_COPY_AND_ASSIGN(PassthroughTouchEventQueue);
 };
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
index d192dbb..8d51360 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -121,8 +121,8 @@
   void SetUpForSkipFilterTesting(const std::string& events_to_always_forward) {
     base::test::ScopedFeatureList feature_list;
     feature_list.InitAndEnableFeatureWithParameters(
-        features::kSkipBrowserTouchFilter,
-        {{features::kSkipBrowserTouchFilterTypeParamName,
+        features::kSkipTouchEventFilter,
+        {{features::kSkipTouchEventFilterTypeParamName,
           events_to_always_forward}});
     ResetQueueWithConfig(PassthroughTouchEventQueue::Config());
   }
@@ -1933,7 +1933,7 @@
 TEST_F(PassthroughTouchEventQueueTest,
        TouchStartUnfilteredWithForwardDiscrete) {
   SetUpForSkipFilterTesting(
-      features::kSkipBrowserTouchFilterTypeParamValueDiscrete);
+      features::kSkipTouchEventFilterTypeParamValueDiscrete);
 
   OnHasTouchEventHandlers(false);
   SyntheticWebTouchEvent event;
@@ -1945,7 +1945,7 @@
 
 TEST_F(PassthroughTouchEventQueueTest, TouchMoveFilteredWithForwardDiscrete) {
   SetUpForSkipFilterTesting(
-      features::kSkipBrowserTouchFilterTypeParamValueDiscrete);
+      features::kSkipTouchEventFilterTypeParamValueDiscrete);
 
   OnHasTouchEventHandlers(false);
   // Start the touch sequence.
@@ -1961,7 +1961,7 @@
 }
 
 TEST_F(PassthroughTouchEventQueueTest, TouchStartUnfilteredWithForwardAll) {
-  SetUpForSkipFilterTesting(features::kSkipBrowserTouchFilterTypeParamValueAll);
+  SetUpForSkipFilterTesting(features::kSkipTouchEventFilterTypeParamValueAll);
 
   OnHasTouchEventHandlers(false);
   SyntheticWebTouchEvent event;
@@ -1972,7 +1972,7 @@
 }
 
 TEST_F(PassthroughTouchEventQueueTest, TouchMoveUnfilteredWithForwardAll) {
-  SetUpForSkipFilterTesting(features::kSkipBrowserTouchFilterTypeParamValueAll);
+  SetUpForSkipFilterTesting(features::kSkipTouchEventFilterTypeParamValueAll);
 
   OnHasTouchEventHandlers(false);
   // Start the touch sequence.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index abb4caa..dd8bdad9 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3064,7 +3064,6 @@
     cc::switches::kSlowDownRasterScaleFactor,
     cc::switches::kBrowserControlsHideThreshold,
     cc::switches::kBrowserControlsShowThreshold,
-    switches::kEnableSurfaceSynchronization,
     switches::kRunAllCompositorStagesBeforeDraw,
     switches::kUseVizHitTestSurfaceLayer,
 
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 2a62ca0..7714dc5 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1576,7 +1576,7 @@
   return GetTextInputManager() && GetTextInputManager()->should_do_learning();
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
 void RenderWidgetHostViewAura::SetCompositionFromExistingText(
     const gfx::Range& range,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
@@ -1588,6 +1588,9 @@
   }
 }
 
+#endif
+
+#if defined(OS_WIN)
 void RenderWidgetHostViewAura::SetActiveCompositionForAccessibility(
     const gfx::Range& range,
     const base::string16& active_composition_text,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 6eacfb5e..53845eb 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -240,11 +240,13 @@
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
 
-#if defined(OS_WIN)
-  // Overridden from ui::TextInputClient(Windows only):
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
   void SetCompositionFromExistingText(
       const gfx::Range& range,
       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
+#endif
+
+#if defined(OS_WIN)
   // API to notify accessibility whether there is an active composition
   // from TSF or not.
   // It notifies the composition range, composition text and whether the
diff --git a/content/browser/startup_helper.cc b/content/browser/startup_helper.cc
index 191db21e..ed24eb1 100644
--- a/content/browser/startup_helper.cc
+++ b/content/browser/startup_helper.cc
@@ -22,24 +22,24 @@
 #if defined(OS_ANDROID)
   // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
   return std::make_unique<base::ThreadPool::InitParams>(
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(4, 8, 0.2, 0),
           base::TimeDelta::FromSeconds(30)),
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(6, 8, 0.6, 0),
           base::TimeDelta::FromSeconds(30)));
 #else
   // Desktop config.
   return std::make_unique<base::ThreadPool::InitParams>(
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(6, 8, 0.2, 0),
           base::TimeDelta::FromSeconds(30)),
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(16, 32, 0.6, 0),
           base::TimeDelta::FromSeconds(30))
 #if defined(OS_WIN)
           ,
-      base::ThreadPool::InitParams::SharedWorkerPoolEnvironment::COM_MTA
+      base::ThreadPool::InitParams::CommonThreadPoolEnvironment::COM_MTA
 #endif  // defined(OS_WIN)
   );
 #endif
@@ -80,15 +80,14 @@
   // threads in the foreground pool.
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kSingleProcess)) {
-    const base::SchedulerWorkerPoolParams&
-        current_foreground_worker_pool_params(
-            thread_pool_init_params->foreground_worker_pool_params);
-    thread_pool_init_params->foreground_worker_pool_params =
-        base::SchedulerWorkerPoolParams(
+    const base::ThreadGroupParams& current_foreground_thread_group_params(
+        thread_pool_init_params->foreground_thread_group_params);
+    thread_pool_init_params->foreground_thread_group_params =
+        base::ThreadGroupParams(
             std::max(GetMinForegroundThreadsInRendererThreadPool(),
-                     current_foreground_worker_pool_params.max_tasks()),
-            current_foreground_worker_pool_params.suggested_reclaim_time(),
-            current_foreground_worker_pool_params.backward_compatibility());
+                     current_foreground_thread_group_params.max_tasks()),
+            current_foreground_thread_group_params.suggested_reclaim_time(),
+            current_foreground_thread_group_params.backward_compatibility());
   }
 
   base::ThreadPool::GetInstance()->Start(*thread_pool_init_params.get());
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index d716d334d..832333b 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -480,6 +480,9 @@
 
   if (!base::FeatureList::IsEnabled(features::kIdleDetection))
     WebRuntimeFeatures::EnableIdleDetection(false);
+
+  WebRuntimeFeatures::EnableSkipTouchEventFilter(
+      base::FeatureList::IsEnabled(features::kSkipTouchEventFilter));
 }
 
 }  // namespace
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 68cb13c4..ee0ca5d5 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -217,10 +217,11 @@
                    mojo_base.mojom.String16 target_origin,
                    blink.mojom.TransferableMessage message);
 
-  // Forwards message to the portal's main frame.
-  ForwardMessageToPortalHost(blink.mojom.TransferableMessage message,
-                             url.mojom.Origin source_origin,
-                             url.mojom.Origin? target_origin);
+  // Forwards a message from a portal's host to the main frame in the portal's
+  // guest contents.
+  ForwardMessageFromHost(blink.mojom.TransferableMessage message,
+                         url.mojom.Origin source_origin,
+                         url.mojom.Origin? target_origin);
 
   // Called on the main frame of a page embedded in a Portal when it is
   // activated. The frame has the option to adopt the previous page as a portal
@@ -231,6 +232,7 @@
   // current frame.
   OnPortalActivated(mojo_base.mojom.UnguessableToken portal_token,
                     associated blink.mojom.Portal portal,
+                    associated blink.mojom.PortalClient& portal_client,
                     blink.mojom.TransferableMessage data) => (bool was_adopted);
 };
 
@@ -340,10 +342,12 @@
       => (CreateNewWindowStatus status, CreateNewWindowReply? reply);
 
   // Sent by the renderer process to request the creation of a new portal.
-  // |portal| is the interface to be used for the Portal object. Returns
-  // |proxy_routing_id|, which is the routing id of the RenderFrameProxy and
-  // |portal_token|, which is the unique identifier for the portal.
-  [Sync] CreatePortal(associated blink.mojom.Portal& portal)
+  // |portal| is the pipe to be used for the Portal object, |client| is the pipe
+  // used to communicate back with the caller. Returns |proxy_routing_id|, which
+  // is the routing id of the RenderFrameProxy and |portal_token|, which is the
+  // unique identifier for the portal.
+  [Sync] CreatePortal(associated blink.mojom.Portal& portal,
+                      associated blink.mojom.PortalClient client)
       => (int32 proxy_routing_id,
           mojo_base.mojom.UnguessableToken portal_token,
           mojo_base.mojom.UnguessableToken devtools_frame_token);
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 06f440d7..2ed632c 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -258,15 +258,8 @@
     "MimeHandlerViewInCrossProcessFrame", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables/disables the video capture service.
-const base::Feature kMojoVideoCapture {
-  "MojoVideoCapture",
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_CHROMEOS) || \
-    defined(OS_ANDROID)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
+const base::Feature kMojoVideoCapture{"MojoVideoCapture",
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 // A secondary switch used in combination with kMojoVideoCapture.
 // This is intended as a kill switch to allow disabling the service on
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5f63149..bafe2572 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2661,18 +2661,20 @@
 void RenderFrameImpl::OnPortalActivated(
     const base::UnguessableToken& portal_token,
     blink::mojom::PortalAssociatedPtrInfo portal,
+    blink::mojom::PortalClientAssociatedRequest portal_client,
     blink::TransferableMessage data,
     OnPortalActivatedCallback callback) {
-  frame_->OnPortalActivated(portal_token, portal.PassHandle(), std::move(data),
+  frame_->OnPortalActivated(portal_token, portal.PassHandle(),
+                            portal_client.PassHandle(), std::move(data),
                             std::move(callback));
 }
 
-void RenderFrameImpl::ForwardMessageToPortalHost(
+void RenderFrameImpl::ForwardMessageFromHost(
     blink::TransferableMessage message,
     const url::Origin& source_origin,
     const base::Optional<url::Origin>& target_origin) {
-  frame_->ForwardMessageToPortalHost(std::move(message), source_origin,
-                                     target_origin);
+  frame_->ForwardMessageFromHost(std::move(message), source_origin,
+                                 target_origin);
 }
 
 void RenderFrameImpl::SetLifecycleState(
@@ -4261,13 +4263,16 @@
 }
 
 std::pair<blink::WebRemoteFrame*, base::UnguessableToken>
-RenderFrameImpl::CreatePortal(mojo::ScopedInterfaceEndpointHandle pipe) {
+RenderFrameImpl::CreatePortal(mojo::ScopedInterfaceEndpointHandle request,
+                              mojo::ScopedInterfaceEndpointHandle client) {
   int proxy_routing_id = MSG_ROUTING_NONE;
   base::UnguessableToken portal_token;
   base::UnguessableToken devtools_frame_token;
   GetFrameHost()->CreatePortal(
-      blink::mojom::PortalAssociatedRequest(std::move(pipe)), &proxy_routing_id,
-      &portal_token, &devtools_frame_token);
+      blink::mojom::PortalAssociatedRequest(std::move(request)),
+      blink::mojom::PortalClientAssociatedPtrInfo(
+          std::move(client), blink::mojom::PortalClient::Version_),
+      &proxy_routing_id, &portal_token, &devtools_frame_token);
   RenderFrameProxy* proxy = RenderFrameProxy::CreateProxyForPortal(
       this, proxy_routing_id, devtools_frame_token);
   return std::make_pair(proxy->web_frame(), portal_token);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 58e5b9e..4d8c563 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -533,10 +533,6 @@
   void BlockRequests() override;
   void ResumeBlockedRequests() override;
   void CancelBlockedRequests() override;
-  void ForwardMessageToPortalHost(
-      blink::TransferableMessage message,
-      const url::Origin& source_origin,
-      const base::Optional<url::Origin>& target_origin) override;
   void SetLifecycleState(blink::mojom::FrameLifecycleState state) override;
 
 #if defined(OS_ANDROID)
@@ -553,6 +549,10 @@
                         const base::string16& source_origin,
                         const base::string16& target_origin,
                         blink::TransferableMessage message) override;
+  void ForwardMessageFromHost(
+      blink::TransferableMessage message,
+      const url::Origin& source_origin,
+      const base::Optional<url::Origin>& target_origin) override;
 
   // mojom::FrameNavigationControl implementation:
   void CommitNavigation(
@@ -642,10 +642,12 @@
       const base::string16& javascript,
       int32_t world_id,
       JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
-  void OnPortalActivated(const base::UnguessableToken& portal_token,
-                         blink::mojom::PortalAssociatedPtrInfo portal,
-                         blink::TransferableMessage data,
-                         OnPortalActivatedCallback callback) override;
+  void OnPortalActivated(
+      const base::UnguessableToken& portal_token,
+      blink::mojom::PortalAssociatedPtrInfo portal,
+      blink::mojom::PortalClientAssociatedRequest portal_client,
+      blink::TransferableMessage data,
+      OnPortalActivatedCallback callback) override;
 
   // mojom::FullscreenVideoElementHandler implementation:
   void RequestFullscreenVideoElement() override;
@@ -696,7 +698,8 @@
       const blink::WebFrameOwnerProperties& frame_owner_properties,
       blink::FrameOwnerElementType frame_owner_element_type) override;
   std::pair<blink::WebRemoteFrame*, base::UnguessableToken> CreatePortal(
-      mojo::ScopedInterfaceEndpointHandle request) override;
+      mojo::ScopedInterfaceEndpointHandle request,
+      mojo::ScopedInterfaceEndpointHandle client) override;
   blink::WebRemoteFrame* AdoptPortal(
       const base::UnguessableToken& portal_token) override;
   blink::WebFrame* FindFrame(const blink::WebString& name) override;
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index b56885c7..97f719d 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -68,9 +68,9 @@
   constexpr auto kSuggestedReclaimTime = base::TimeDelta::FromSeconds(30);
 
   return std::make_unique<base::ThreadPool::InitParams>(
-      base::SchedulerWorkerPoolParams(kMaxNumThreadsInBackgroundPool,
-                                      kSuggestedReclaimTime),
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(kMaxNumThreadsInBackgroundPool,
+                              kSuggestedReclaimTime),
+      base::ThreadGroupParams(
           std::max(kMaxNumThreadsInForegroundPoolLowerBound,
                    content::GetMinForegroundThreadsInRendererThreadPool()),
           kSuggestedReclaimTime));
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 9d5af63e..d338d1e 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -106,6 +106,7 @@
   }
 
   void CreatePortal(blink::mojom::PortalAssociatedRequest request,
+                    blink::mojom::PortalClientAssociatedPtrInfo client,
                     CreatePortalCallback callback) override {
     std::move(callback).Run(MSG_ROUTING_NONE, base::UnguessableToken(),
                             base::UnguessableToken());
diff --git a/device/fido/credential_management.cc b/device/fido/credential_management.cc
index 8cafb718..ec848f22 100644
--- a/device/fido/credential_management.cc
+++ b/device/fido/credential_management.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "components/cbor/reader.h"
 #include "components/cbor/values.h"
+#include "components/cbor/writer.h"
 #include "device/fido/fido_parsing_utils.h"
 #include "device/fido/pin.h"
 #include "third_party/boringssl/src/include/openssl/hmac.h"
@@ -17,6 +18,7 @@
 namespace {
 std::array<uint8_t, 16> MakePINAuth(base::span<const uint8_t> pin_token,
                                     base::span<const uint8_t> pin_auth_bytes) {
+  DCHECK(!pin_token.empty() && !pin_auth_bytes.empty());
   std::array<uint8_t, SHA256_DIGEST_LENGTH> hmac;
   unsigned hmac_len;
   CHECK(HMAC(EVP_sha256(), pin_token.data(), pin_token.size(),
@@ -27,55 +29,132 @@
   std::copy(hmac.begin(), hmac.begin() + 16, pin_auth.begin());
   return pin_auth;
 }
-
-std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
-MakeCredentialManagementCommand(
-    CredentialManagementSubCommand subcommand,
-    base::Optional<std::array<uint8_t, 16>> opt_pin_auth) {
-  cbor::Value::MapValue request_map;
-  request_map.emplace(
-      static_cast<int>(CredentialManagementRequestKey::kSubCommand),
-      static_cast<int>(subcommand));
-  request_map.emplace(
-      static_cast<int>(CredentialManagementRequestKey::kPinProtocol),
-      static_cast<int>(pin::kProtocolVersion));
-
-  if (opt_pin_auth) {
-    request_map.emplace(
-        static_cast<int>(CredentialManagementRequestKey::kPinAuth),
-        *opt_pin_auth);
-  }
-
-  // TODO: allow setting kSubCommandParams.
-
-  return {CtapRequestCommand::kAuthenticatorCredentialManagement,
-          cbor::Value(std::move(request_map))};
-}
 }  // namespace
 
-CredentialsMetadataRequest::CredentialsMetadataRequest(
-    std::vector<uint8_t> pin_token_)
-    : pin_token(std::move(pin_token_)) {}
-CredentialsMetadataRequest::CredentialsMetadataRequest(
-    CredentialsMetadataRequest&&) = default;
-CredentialsMetadataRequest& CredentialsMetadataRequest::operator=(
-    CredentialsMetadataRequest&&) = default;
-CredentialsMetadataRequest::~CredentialsMetadataRequest() = default;
+CredentialManagementRequest::CredentialManagementRequest(
+    Version version_,
+    CredentialManagementSubCommand subcommand_,
+    base::Optional<cbor::Value::MapValue> params_,
+    base::Optional<std::array<uint8_t, 16>> pin_auth_)
+    : version(version_),
+      subcommand(subcommand_),
+      params(std::move(params_)),
+      pin_auth(std::move(pin_auth_)) {}
+CredentialManagementRequest::CredentialManagementRequest(
+    CredentialManagementRequest&&) = default;
+CredentialManagementRequest& CredentialManagementRequest::operator=(
+    CredentialManagementRequest&&) = default;
+CredentialManagementRequest::~CredentialManagementRequest() = default;
 
 // static
 std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
-CredentialsMetadataRequest::EncodeAsCBOR(
-    const CredentialsMetadataRequest& request) {
-  if (request.pin_token.empty()) {
-    return MakeCredentialManagementCommand(
-        CredentialManagementSubCommand::kGetCredsMetadata, base::nullopt);
+CredentialManagementRequest::EncodeAsCBOR(
+    const CredentialManagementRequest& request) {
+  cbor::Value::MapValue request_map;
+  request_map.emplace(
+      static_cast<int>(CredentialManagementRequestKey::kSubCommand),
+      static_cast<int>(request.subcommand));
+  if (request.params) {
+    request_map.emplace(
+        static_cast<int>(CredentialManagementRequestKey::kSubCommandParams),
+        *request.params);
   }
+  if (request.pin_auth) {
+    request_map.emplace(
+        static_cast<int>(CredentialManagementRequestKey::kPinProtocol),
+        static_cast<int>(pin::kProtocolVersion));
+    request_map.emplace(
+        static_cast<int>(CredentialManagementRequestKey::kPinAuth),
+        *request.pin_auth);
+  }
+  return {request.version == kPreview
+              ? CtapRequestCommand::kAuthenticatorCredentialManagementPreview
+              : CtapRequestCommand::kAuthenticatorCredentialManagement,
+          cbor::Value(std::move(request_map))};
+}
 
-  constexpr std::array<uint8_t, 1> pinauth_bytes = {
-      static_cast<uint8_t>(CredentialManagementSubCommand::kGetCredsMetadata)};
-  return MakeCredentialManagementCommand(
-      CredentialManagementSubCommand::kGetCredsMetadata,
-      MakePINAuth(request.pin_token, pinauth_bytes));
+// static
+CredentialManagementRequest CredentialManagementRequest::ForGetCredsMetadata(
+    Version version,
+    base::span<const uint8_t> pin_token) {
+  return CredentialManagementRequest(
+      version, CredentialManagementSubCommand::kGetCredsMetadata,
+      /*params=*/base::nullopt,
+      MakePINAuth(pin_token,
+                  {{static_cast<uint8_t>(
+                      CredentialManagementSubCommand::kGetCredsMetadata)}}));
+}
+
+// static
+CredentialManagementRequest CredentialManagementRequest::ForEnumerateRPsBegin(
+    Version version,
+    base::span<const uint8_t> pin_token) {
+  return CredentialManagementRequest(
+      version, CredentialManagementSubCommand::kEnumerateRPsBegin,
+      /*params=*/base::nullopt,
+      MakePINAuth(pin_token,
+                  {{static_cast<uint8_t>(
+                      CredentialManagementSubCommand::kEnumerateRPsBegin)}}));
+}
+
+// static
+CredentialManagementRequest CredentialManagementRequest::ForEnumerateRPsGetNext(
+    Version version) {
+  return CredentialManagementRequest(
+      version, CredentialManagementSubCommand::kEnumerateRPsGetNextRP,
+      /*params=*/base::nullopt,
+      /*pin_auth=*/base::nullopt);
+}
+
+// static
+CredentialManagementRequest
+CredentialManagementRequest::ForEnumerateCredentialsBegin(
+    Version version,
+    base::span<const uint8_t> pin_token,
+    std::array<uint8_t, kRpIdHashLength> rp_id_hash) {
+  cbor::Value::MapValue params_map;
+  params_map.emplace(
+      static_cast<int>(CredentialManagementRequestParamKey::kRPIDHash),
+      std::move(rp_id_hash));
+  base::Optional<std::vector<uint8_t>> pin_auth_bytes =
+      cbor::Writer::Write(cbor::Value(params_map));
+  DCHECK(pin_auth_bytes);
+  pin_auth_bytes->insert(
+      pin_auth_bytes->begin(),
+      static_cast<uint8_t>(
+          CredentialManagementSubCommand::kEnumerateCredentialsBegin));
+  return CredentialManagementRequest(
+      version, CredentialManagementSubCommand::kEnumerateCredentialsBegin,
+      std::move(params_map), MakePINAuth(pin_token, *pin_auth_bytes));
+}
+
+// static
+CredentialManagementRequest
+CredentialManagementRequest::ForEnumerateCredentialsGetNext(Version version) {
+  return CredentialManagementRequest(
+      version,
+      CredentialManagementSubCommand::kEnumerateCredentialsGetNextCredential,
+      /*params=*/base::nullopt, /*pin_auth=*/base::nullopt);
+}
+
+// static
+CredentialManagementRequest CredentialManagementRequest::ForDeleteCredential(
+    Version version,
+    base::span<const uint8_t> pin_token,
+    std::vector<uint8_t> credential_id) {
+  cbor::Value::MapValue params_map;
+  params_map.emplace(
+      static_cast<int>(CredentialManagementRequestParamKey::kCredentialID),
+      std::move(credential_id));
+  base::Optional<std::vector<uint8_t>> pin_auth_bytes =
+      cbor::Writer::Write(cbor::Value(params_map));
+  DCHECK(pin_auth_bytes);
+  pin_auth_bytes->insert(
+      pin_auth_bytes->begin(),
+      static_cast<uint8_t>(CredentialManagementSubCommand::kDeleteCredential));
+  return CredentialManagementRequest(
+      version, CredentialManagementSubCommand::kDeleteCredential,
+      std::move(params_map), MakePINAuth(pin_token, *pin_auth_bytes));
 }
 
 // static
@@ -117,14 +196,39 @@
 
 // static
 base::Optional<EnumerateRPsResponse> EnumerateRPsResponse::Parse(
-    const base::Optional<cbor::Value>& cbor_response,
-    bool expect_rp_count) {
-  if (!cbor_response || !cbor_response->is_map()) {
+    bool expect_rp_count,
+    const base::Optional<cbor::Value>& cbor_response) {
+  if (!cbor_response) {
+    // Some authenticators send an empty response if there are no RPs (though
+    // the spec doesn't say that).
+    return EnumerateRPsResponse(base::nullopt, base::nullopt, 0);
+  }
+  if (!cbor_response->is_map() || cbor_response->GetMap().empty()) {
     return base::nullopt;
   }
   const cbor::Value::MapValue& response_map = cbor_response->GetMap();
 
-  auto it = response_map.find(
+  size_t rp_count = 0;
+  auto it = response_map.find(cbor::Value(
+      static_cast<int>(CredentialManagementResponseKey::kTotalRPs)));
+  if (!expect_rp_count && it != response_map.end()) {
+    return base::nullopt;
+  }
+  if (expect_rp_count) {
+    if (it == response_map.end() || !it->second.is_unsigned() ||
+        it->second.GetUnsigned() > std::numeric_limits<size_t>::max()) {
+      return base::nullopt;
+    }
+    rp_count = static_cast<size_t>(it->second.GetUnsigned());
+    if (rp_count == 0) {
+      if (response_map.size() != 1) {
+        return base::nullopt;
+      }
+      return EnumerateRPsResponse(base::nullopt, base::nullopt, 0);
+    }
+  }
+
+  it = response_map.find(
       cbor::Value(static_cast<int>(CredentialManagementResponseKey::kRP)));
   if (it == response_map.end()) {
     return base::nullopt;
@@ -146,22 +250,6 @@
   std::array<uint8_t, kRpIdHashLength> rp_id_hash;
   std::copy_n(rp_id_hash_bytes.begin(), kRpIdHashLength, rp_id_hash.begin());
 
-  size_t rp_count = 0;
-  if (!expect_rp_count) {
-    if (response_map.find(cbor::Value(
-            static_cast<int>(CredentialManagementResponseKey::kTotalRPs))) !=
-        response_map.end()) {
-      return base::nullopt;
-    }
-  } else {
-    it = response_map.find(cbor::Value(
-        static_cast<int>(CredentialManagementResponseKey::kTotalRPs)));
-    if (it == response_map.end() || !it->second.is_unsigned() ||
-        it->second.GetUnsigned() > std::numeric_limits<size_t>::max()) {
-      return base::nullopt;
-    }
-    rp_count = static_cast<size_t>(it->second.GetUnsigned());
-  }
   return EnumerateRPsResponse(std::move(*opt_rp), std::move(rp_id_hash),
                               rp_count);
 }
@@ -171,8 +259,8 @@
     default;
 EnumerateRPsResponse::~EnumerateRPsResponse() = default;
 EnumerateRPsResponse::EnumerateRPsResponse(
-    PublicKeyCredentialRpEntity rp_,
-    std::array<uint8_t, kRpIdHashLength> rp_id_hash_,
+    base::Optional<PublicKeyCredentialRpEntity> rp_,
+    base::Optional<std::array<uint8_t, kRpIdHashLength>> rp_id_hash_,
     size_t rp_count_)
     : rp(std::move(rp_)),
       rp_id_hash(std::move(rp_id_hash_)),
@@ -181,9 +269,13 @@
 //  static
 base::Optional<EnumerateCredentialsResponse>
 EnumerateCredentialsResponse::Parse(
-    const base::Optional<cbor::Value>& cbor_response,
-    bool expect_credential_count) {
+    bool expect_credential_count,
+    const base::Optional<cbor::Value>& cbor_response) {
   if (!cbor_response || !cbor_response->is_map()) {
+    // Note that some authenticators may send an empty response if they don't
+    // have a credential for a given RP ID hash (though the spec doesn't say
+    // that). However, that case should not be reached from
+    // CredentialManagementHandler.
     return base::nullopt;
   }
   const cbor::Value::MapValue& response_map = cbor_response->GetMap();
@@ -201,10 +293,14 @@
 
   it = response_map.find(cbor::Value(
       static_cast<int>(CredentialManagementResponseKey::kCredentialID)));
-  if (it == response_map.end() || !it->second.is_bytestring()) {
+  if (it == response_map.end()) {
     return base::nullopt;
   }
-  const std::vector<uint8_t>& credential_id = it->second.GetBytestring();
+  auto opt_credential_id =
+      PublicKeyCredentialDescriptor::CreateFromCBORValue(it->second);
+  if (!opt_credential_id) {
+    return base::nullopt;
+  }
 
   // Ignore the public key's value.
   it = response_map.find(cbor::Value(
@@ -229,8 +325,8 @@
     }
     credential_count = static_cast<size_t>(it->second.GetUnsigned());
   }
-  return EnumerateCredentialsResponse(std::move(*opt_user), credential_id,
-                                      credential_count);
+  return EnumerateCredentialsResponse(
+      std::move(*opt_user), std::move(*opt_credential_id), credential_count);
 }
 
 EnumerateCredentialsResponse::EnumerateCredentialsResponse(
@@ -240,7 +336,7 @@
 EnumerateCredentialsResponse::~EnumerateCredentialsResponse() = default;
 EnumerateCredentialsResponse::EnumerateCredentialsResponse(
     PublicKeyCredentialUserEntity user_,
-    std::vector<uint8_t> credential_id_,
+    PublicKeyCredentialDescriptor credential_id_,
     size_t credential_count_)
     : user(std::move(user_)),
       credential_id(std::move(credential_id_)),
@@ -249,6 +345,10 @@
 AggregatedEnumerateCredentialsResponse::AggregatedEnumerateCredentialsResponse(
     PublicKeyCredentialRpEntity rp_)
     : rp(std::move(rp_)), credentials() {}
+AggregatedEnumerateCredentialsResponse::AggregatedEnumerateCredentialsResponse(
+    AggregatedEnumerateCredentialsResponse&&) = default;
+AggregatedEnumerateCredentialsResponse& AggregatedEnumerateCredentialsResponse::
+operator=(AggregatedEnumerateCredentialsResponse&&) = default;
 AggregatedEnumerateCredentialsResponse::
     ~AggregatedEnumerateCredentialsResponse() = default;
 
diff --git a/device/fido/credential_management.h b/device/fido/credential_management.h
index f6dba0f..cda0cf4 100644
--- a/device/fido/credential_management.h
+++ b/device/fido/credential_management.h
@@ -8,6 +8,7 @@
 #include "base/component_export.h"
 #include "base/optional.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/public_key_credential_descriptor.h"
 #include "device/fido/public_key_credential_rp_entity.h"
 #include "device/fido/public_key_credential_user_entity.h"
 
@@ -81,20 +82,53 @@
   T wrapped_request_;
 };
 
-struct CredentialsMetadataRequest {
+// CredentialManagementRequest is an authenticatorCredentialManagement(0x0a)
+// CTAP2 request. Instances can be obtained via one of the subcommand-specific
+// static factory methods.
+struct CredentialManagementRequest {
   static std::pair<CtapRequestCommand, base::Optional<cbor::Value>>
-  EncodeAsCBOR(const CredentialsMetadataRequest&);
+  EncodeAsCBOR(const CredentialManagementRequest&);
 
-  explicit CredentialsMetadataRequest(std::vector<uint8_t> pin_token);
-  CredentialsMetadataRequest(CredentialsMetadataRequest&&);
-  CredentialsMetadataRequest& operator=(CredentialsMetadataRequest&&);
-  ~CredentialsMetadataRequest();
+  enum Version {
+    kDefault,
+    kPreview,
+  };
 
-  std::vector<uint8_t> pin_token;
+  static CredentialManagementRequest ForGetCredsMetadata(
+      Version version,
+      base::span<const uint8_t> pin_token);
+  static CredentialManagementRequest ForEnumerateRPsBegin(
+      Version version,
+      base::span<const uint8_t> pin_token);
+  static CredentialManagementRequest ForEnumerateRPsGetNext(Version version);
+  static CredentialManagementRequest ForEnumerateCredentialsBegin(
+      Version version,
+      base::span<const uint8_t> pin_token,
+      std::array<uint8_t, kRpIdHashLength> rp_id_hash);
+  static CredentialManagementRequest ForEnumerateCredentialsGetNext(
+      Version version);
+  static CredentialManagementRequest ForDeleteCredential(
+      Version version,
+      base::span<const uint8_t> pin_token,
+      std::vector<uint8_t> credential_id);
+
+  CredentialManagementRequest(CredentialManagementRequest&&);
+  CredentialManagementRequest& operator=(CredentialManagementRequest&&);
+  ~CredentialManagementRequest();
+
+  Version version;
+  CredentialManagementSubCommand subcommand;
+  base::Optional<cbor::Value::MapValue> params;
+  base::Optional<std::array<uint8_t, 16>> pin_auth;
 
  private:
-  CredentialsMetadataRequest(const CredentialsMetadataRequest&) = delete;
-  CredentialsMetadataRequest& operator=(const CredentialsMetadataRequest&) =
+  CredentialManagementRequest() = delete;
+  CredentialManagementRequest(Version version,
+                              CredentialManagementSubCommand subcommand,
+                              base::Optional<cbor::Value::MapValue> params,
+                              base::Optional<std::array<uint8_t, 16>> pin_auth);
+  CredentialManagementRequest(const CredentialManagementRequest&) = delete;
+  CredentialManagementRequest& operator=(const CredentialManagementRequest&) =
       delete;
 };
 
@@ -111,41 +145,42 @@
 
 struct EnumerateRPsResponse {
   static base::Optional<EnumerateRPsResponse> Parse(
-      const base::Optional<cbor::Value>& cbor_response,
-      bool expect_rp_count);
+      bool expect_rp_count,
+      const base::Optional<cbor::Value>& cbor_response);
 
   EnumerateRPsResponse(EnumerateRPsResponse&&);
   EnumerateRPsResponse& operator=(EnumerateRPsResponse&&);
   ~EnumerateRPsResponse();
 
-  PublicKeyCredentialRpEntity rp;
-  std::array<uint8_t, kRpIdHashLength> rp_id_hash;
+  base::Optional<PublicKeyCredentialRpEntity> rp;
+  base::Optional<std::array<uint8_t, kRpIdHashLength>> rp_id_hash;
   size_t rp_count;
 
  private:
-  EnumerateRPsResponse(PublicKeyCredentialRpEntity rp,
-                       std::array<uint8_t, kRpIdHashLength> rp_id_hash,
-                       size_t rp_count);
+  EnumerateRPsResponse(
+      base::Optional<PublicKeyCredentialRpEntity> rp,
+      base::Optional<std::array<uint8_t, kRpIdHashLength>> rp_id_hash,
+      size_t rp_count);
   EnumerateRPsResponse(const EnumerateRPsResponse&) = delete;
   EnumerateRPsResponse& operator=(const EnumerateRPsResponse&) = delete;
 };
 
 struct EnumerateCredentialsResponse {
   static base::Optional<EnumerateCredentialsResponse> Parse(
-      const base::Optional<cbor::Value>& cbor_response,
-      bool expect_credential_count);
+      bool expect_credential_count,
+      const base::Optional<cbor::Value>& cbor_response);
 
   EnumerateCredentialsResponse(EnumerateCredentialsResponse&&);
   EnumerateCredentialsResponse& operator=(EnumerateCredentialsResponse&&);
   ~EnumerateCredentialsResponse();
 
   PublicKeyCredentialUserEntity user;
-  std::vector<uint8_t> credential_id;
+  PublicKeyCredentialDescriptor credential_id;
   size_t credential_count;
 
  private:
   EnumerateCredentialsResponse(PublicKeyCredentialUserEntity user,
-                               std::vector<uint8_t> credential_id,
+                               PublicKeyCredentialDescriptor credential_id,
                                size_t credential_count);
   EnumerateCredentialsResponse(const EnumerateCredentialsResponse&) = delete;
   EnumerateCredentialsResponse& operator=(EnumerateCredentialsResponse&) =
@@ -154,6 +189,10 @@
 
 struct COMPONENT_EXPORT(DEVICE_FIDO) AggregatedEnumerateCredentialsResponse {
   AggregatedEnumerateCredentialsResponse(PublicKeyCredentialRpEntity rp);
+  AggregatedEnumerateCredentialsResponse(
+      AggregatedEnumerateCredentialsResponse&&);
+  AggregatedEnumerateCredentialsResponse& operator=(
+      AggregatedEnumerateCredentialsResponse&&);
   ~AggregatedEnumerateCredentialsResponse();
 
   PublicKeyCredentialRpEntity rp;
diff --git a/device/fido/credential_management_handler.cc b/device/fido/credential_management_handler.cc
index 827aa46..46ac8413 100644
--- a/device/fido/credential_management_handler.cc
+++ b/device/fido/credential_management_handler.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
 #include "components/cbor/values.h"
 #include "components/cbor/writer.h"
 #include "device/fido/fido_authenticator.h"
@@ -20,9 +19,13 @@
 CredentialManagementHandler::CredentialManagementHandler(
     service_manager::Connector* connector,
     const base::flat_set<FidoTransportProtocol>& supported_transports,
-    Delegate* delegate)
+    ReadyCallback ready_callback,
+    GetPINCallback get_pin_callback,
+    FinishedCallback finished_callback)
     : FidoRequestHandlerBase(connector, supported_transports),
-      delegate_(delegate),
+      ready_callback_(std::move(ready_callback)),
+      get_pin_callback_(std::move(get_pin_callback)),
+      finished_callback_(std::move(finished_callback)),
       weak_factory_(this) {
   Start();
 }
@@ -53,13 +56,11 @@
       !(authenticator->Options()->supports_credential_management ||
         authenticator->Options()->supports_credential_management_preview)) {
     state_ = State::kFinished;
-    delegate_->OnError(
-        FidoReturnCode::kAuthenticatorMissingCredentialManagement);
+    std::move(finished_callback_)
+        .Run(FidoReturnCode::kAuthenticatorMissingCredentialManagement);
     return;
   }
 
-  DCHECK(observer()->SupportsPIN());
-
   if (authenticator->Options()->client_pin_availability !=
       AuthenticatorSupportedOptions::ClientPinAvailability::
           kSupportedAndPinSet) {
@@ -67,7 +68,8 @@
     // We should implement in-flow PIN setting, but for now just tell the user
     // to set a PIN themselves.
     state_ = State::kFinished;
-    delegate_->OnError(FidoReturnCode::kAuthenticatorMissingUserVerification);
+    std::move(finished_callback_)
+        .Run(FidoReturnCode::kAuthenticatorMissingUserVerification);
     return;
   }
 
@@ -84,18 +86,19 @@
   DCHECK_EQ(state_, State::kGettingRetries);
   if (status != CtapDeviceResponseCode::kSuccess) {
     state_ = State::kFinished;
-    delegate_->OnError(FidoReturnCode::kAuthenticatorResponseInvalid);
+    std::move(finished_callback_)
+        .Run(FidoReturnCode::kAuthenticatorResponseInvalid);
     return;
   }
   if (response->retries == 0) {
     state_ = State::kFinished;
-    delegate_->OnError(FidoReturnCode::kHardPINBlock);
+    std::move(finished_callback_).Run(FidoReturnCode::kHardPINBlock);
     return;
   }
   state_ = State::kWaitingForPIN;
-  observer()->CollectPIN(response->retries,
-                         base::BindOnce(&CredentialManagementHandler::OnHavePIN,
-                                        weak_factory_.GetWeakPtr()));
+  get_pin_callback_.Run(response->retries,
+                        base::BindOnce(&CredentialManagementHandler::OnHavePIN,
+                                       weak_factory_.GetWeakPtr()));
 }
 
 void CredentialManagementHandler::OnHavePIN(std::string pin) {
@@ -124,7 +127,8 @@
 
   if (status != CtapDeviceResponseCode::kSuccess) {
     state_ = State::kFinished;
-    delegate_->OnError(FidoReturnCode::kAuthenticatorResponseInvalid);
+    std::move(finished_callback_)
+        .Run(FidoReturnCode::kAuthenticatorResponseInvalid);
     return;
   }
 
@@ -163,44 +167,106 @@
         error = FidoReturnCode::kAuthenticatorResponseInvalid;
         break;
     }
-    delegate_->OnError(error);
+    std::move(finished_callback_).Run(error);
     return;
   }
 
-  observer()->FinishCollectPIN();
-  state_ = State::kGettingCredentials;
+  state_ = State::kReady;
+  pin_token_ = response->token();
+  std::move(ready_callback_).Run();
+}
 
+void CredentialManagementHandler::GetCredentials(
+    GetCredentialsCallback callback) {
+  DCHECK(state_ == State::kReady && !get_credentials_callback_);
+  if (!authenticator_) {
+    // AuthenticatorRemoved() may have been called, but the observer would have
+    // seen a FidoAuthenticatorRemoved() call.
+    NOTREACHED();
+    return;
+  }
+  get_credentials_callback_ = std::move(callback);
+  state_ = State::kGettingCredentials;
   authenticator_->GetCredentialsMetadata(
-      response->token(),
+      *pin_token_,
       base::BindOnce(&CredentialManagementHandler::OnCredentialsMetadata,
                      weak_factory_.GetWeakPtr()));
 }
 
+static void OnDeleteCredential(
+    CredentialManagementHandler::DeleteCredentialCallback callback,
+    CtapDeviceResponseCode status,
+    base::Optional<DeleteCredentialResponse> response) {
+  std::move(callback).Run(status);
+}
+
+void CredentialManagementHandler::DeleteCredential(
+    base::span<const uint8_t> credential_id,
+    DeleteCredentialCallback callback) {
+  DCHECK(state_ == State::kReady && !get_credentials_callback_);
+  if (!authenticator_) {
+    // AuthenticatorRemoved() may have been called, but the observer would have
+    // seen a FidoAuthenticatorRemoved() call.
+    NOTREACHED();
+    return;
+  }
+  DCHECK(pin_token_);
+  authenticator_->DeleteCredential(
+      *pin_token_, credential_id,
+      base::BindOnce(&OnDeleteCredential, std::move(callback)));
+}
+
 void CredentialManagementHandler::OnCredentialsMetadata(
     CtapDeviceResponseCode status,
     base::Optional<CredentialsMetadataResponse> response) {
   if (status != CtapDeviceResponseCode::kSuccess) {
-    delegate_->OnError(FidoReturnCode::kAuthenticatorResponseInvalid);
+    state_ = State::kFinished;
+    std::move(get_credentials_callback_)
+        .Run(status, base::nullopt, base::nullopt);
     return;
   }
-  delegate_->OnCredentialMetadata(
-      response->num_existing_credentials,
-      response->num_estimated_remaining_credentials);
+  authenticator_->EnumerateCredentials(
+      *pin_token_,
+      base::BindOnce(&CredentialManagementHandler::OnEnumerateCredentials,
+                     weak_factory_.GetWeakPtr(), std::move(*response)));
+}
+
+void CredentialManagementHandler::OnEnumerateCredentials(
+    CredentialsMetadataResponse metadata_response,
+    CtapDeviceResponseCode status,
+    base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>
+        responses) {
+  if (status != CtapDeviceResponseCode::kSuccess) {
+    state_ = State::kFinished;
+    std::move(get_credentials_callback_)
+        .Run(status, base::nullopt, base::nullopt);
+    return;
+  }
+  state_ = State::kReady;
+  std::move(get_credentials_callback_)
+      .Run(status, std::move(responses),
+           metadata_response.num_estimated_remaining_credentials);
 }
 
 void CredentialManagementHandler::AuthenticatorRemoved(
     FidoDiscoveryBase* discovery,
     FidoAuthenticator* authenticator) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
   FidoRequestHandlerBase::AuthenticatorRemoved(discovery, authenticator);
+  if (authenticator != authenticator_) {
+    return;
+  }
 
-  if (authenticator == authenticator_) {
-    authenticator_ = nullptr;
-    if (state_ == State::kWaitingForPIN) {
-      state_ = State::kFinished;
-      delegate_->OnError(FidoReturnCode::kAuthenticatorRemovedDuringPINEntry);
-    }
+  authenticator_ = nullptr;
+  if (state_ == State::kWaitingForPIN) {
+    state_ = State::kFinished;
+    std::move(finished_callback_)
+        .Run(FidoReturnCode::kAuthenticatorRemovedDuringPINEntry);
+    return;
+  }
+  if (state_ == State::kReady) {
+    std::move(finished_callback_).Run(FidoReturnCode::kSuccess);
+    return;
   }
 }
 
diff --git a/device/fido/credential_management_handler.h b/device/fido/credential_management_handler.h
index 589283cb..b7bad478b 100644
--- a/device/fido/credential_management_handler.h
+++ b/device/fido/credential_management_handler.h
@@ -29,28 +29,40 @@
 
 // CredentialManagementHandler implements the authenticatorCredentialManagement
 // protocol.
+//
+// Public methods on instances of this class may be called only after
+// ReadyCallback has run, but not after FinishedCallback has run.
 class COMPONENT_EXPORT(DEVICE_FIDO) CredentialManagementHandler
     : public FidoRequestHandlerBase {
  public:
-  using GetPINCallback = base::OnceCallback<void(base::Optional<int64_t>)>;
-
-  class Delegate {
-   public:
-    // TODO(martinkr): These should probably be combined, but separating them is
-    // more convenient for development right now.
-    virtual void OnCredentialMetadata(size_t num_existing,
-                                      size_t num_remaining) = 0;
-    virtual void OnCredentialsEnumerated(
-        std::vector<AggregatedEnumerateCredentialsResponse> credentials) = 0;
-    virtual void OnError(FidoReturnCode) = 0;
-  };
+  using DeleteCredentialCallback =
+      base::OnceCallback<void(CtapDeviceResponseCode)>;
+  using FinishedCallback = base::OnceCallback<void(FidoReturnCode)>;
+  using GetCredentialsCallback = base::OnceCallback<void(
+      CtapDeviceResponseCode status,
+      base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>,
+      base::Optional<size_t>)>;
+  using GetPINCallback =
+      base::RepeatingCallback<void(int64_t,
+                                   base::OnceCallback<void(std::string)>)>;
+  using ReadyCallback = base::OnceClosure;
 
   CredentialManagementHandler(
       service_manager::Connector* connector,
       const base::flat_set<FidoTransportProtocol>& supported_transports,
-      Delegate* delegate);
+      ReadyCallback ready_callback,
+      GetPINCallback get_pin_callback,
+      FinishedCallback finished_callback);
   ~CredentialManagementHandler() override;
 
+  // GetCredentials invokes a series of commands to fetch all credentials stored
+  // on the device. The supplied callback receives the status returned by the
+  // device and, if successful, the resident credentials stored and remaining
+  // capacity left on the chosen authenticator.
+  void GetCredentials(GetCredentialsCallback callback);
+  void DeleteCredential(base::span<const uint8_t> credential_id,
+                        DeleteCredentialCallback callback);
+
  private:
   enum class State {
     kWaitingForTouch,
@@ -58,6 +70,7 @@
     kWaitingForPIN,
     kGettingEphemeralKey,
     kGettingPINToken,
+    kReady,
     kGettingMetadata,
     kGettingRP,
     kGettingCredentials,
@@ -81,12 +94,22 @@
   void OnCredentialsMetadata(
       CtapDeviceResponseCode status,
       base::Optional<CredentialsMetadataResponse> response);
+  void OnEnumerateCredentials(
+      CredentialsMetadataResponse metadata_response,
+      CtapDeviceResponseCode status,
+      base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>
+          responses);
 
   SEQUENCE_CHECKER(sequence_checker_);
 
-  Delegate* const delegate_;
   State state_ = State::kWaitingForTouch;
   FidoAuthenticator* authenticator_ = nullptr;
+  base::Optional<std::vector<uint8_t>> pin_token_;
+
+  ReadyCallback ready_callback_;
+  GetPINCallback get_pin_callback_;
+  GetCredentialsCallback get_credentials_callback_;
+  FinishedCallback finished_callback_;
 
   base::WeakPtrFactory<CredentialManagementHandler> weak_factory_;
 
diff --git a/device/fido/credential_management_handler_unittest.cc b/device/fido/credential_management_handler_unittest.cc
index 70cade8..b0c837a 100644
--- a/device/fido/credential_management_handler_unittest.cc
+++ b/device/fido/credential_management_handler_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "device/fido/credential_management_handler.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/fido/credential_management.h"
@@ -27,70 +29,38 @@
 constexpr char kUserName[] = "alice@example.com";
 constexpr char kUserDisplayName[] = "Alice Example <alice@example.com>";
 
-class TestObserver : public FidoRequestHandlerBase::Observer {
- public:
-  TestObserver() {}
-  ~TestObserver() override {}
-
- private:
-  // FidoRequestHandlerBase::Observer:
-  void OnTransportAvailabilityEnumerated(
-      FidoRequestHandlerBase::TransportAvailabilityInfo data) override {}
-  bool EmbedderControlsAuthenticatorDispatch(
-      const FidoAuthenticator&) override {
-    return false;
+class CredentialManagementHandlerTest : public ::testing::Test {
+ protected:
+  std::unique_ptr<CredentialManagementHandler> MakeHandler() {
+    auto handler = std::make_unique<CredentialManagementHandler>(
+        /*connector=*/nullptr,
+        base::flat_set<FidoTransportProtocol>{
+            FidoTransportProtocol::kUsbHumanInterfaceDevice},
+        ready_callback_.callback(),
+        base::BindRepeating(&CredentialManagementHandlerTest::GetPIN,
+                            base::Unretained(this)),
+        finished_callback_.callback());
+    return handler;
   }
-  void BluetoothAdapterPowerChanged(bool is_powered_on) override {}
-  void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator) override {
-  }
-  void FidoAuthenticatorRemoved(base::StringPiece device_id) override {}
-  void FidoAuthenticatorIdChanged(base::StringPiece old_authenticator_id,
-                                  std::string new_authenticator_id) override {}
-  void FidoAuthenticatorPairingModeChanged(base::StringPiece authenticator_id,
-                                           bool is_in_pairing_mode) override {}
-  bool SupportsPIN() const override { return true; }
-  void CollectPIN(
-      base::Optional<int> attempts,
-      base::OnceCallback<void(std::string)> provide_pin_cb) override {
-    std::move(provide_pin_cb).Run(kPIN);
-  }
-  void FinishCollectPIN() override {}
-  void SetMightCreateResidentCredential(bool v) override {}
-};
 
-class TestDelegate : public CredentialManagementHandler::Delegate {
- public:
-  TestDelegate() {}
-  ~TestDelegate() {}
+  void GetPIN(int64_t num_attempts,
+              base::OnceCallback<void(std::string)> provide_pin) {
+    std::move(provide_pin).Run(kPIN);
+  }
 
-  test::StatusAndValuesCallbackReceiver<CtapDeviceResponseCode, size_t, size_t>
-      on_credential_metadata;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  test::TestCallbackReceiver<> ready_callback_;
   test::StatusAndValuesCallbackReceiver<
-      std::vector<AggregatedEnumerateCredentialsResponse>>
-      on_credentials_enumerated;
-  test::ValueCallbackReceiver<FidoReturnCode> on_error;
-
- private:
-  // CredentialManagementHandler::Delegate
-  void OnCredentialMetadata(size_t num_existing,
-                            size_t num_remaining) override {
-    on_credential_metadata.callback().Run(CtapDeviceResponseCode::kSuccess,
-                                          num_existing, num_remaining);
-  }
-  void OnCredentialsEnumerated(
-      std::vector<AggregatedEnumerateCredentialsResponse> credentials)
-      override {
-    on_credentials_enumerated.callback().Run(std::move(credentials));
-  }
-  void OnError(FidoReturnCode error) override {
-    on_error.callback().Run(error);
-  }
+      CtapDeviceResponseCode,
+      base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>,
+      base::Optional<size_t>>
+      get_credentials_callback_;
+  test::ValueCallbackReceiver<CtapDeviceResponseCode> delete_callback_;
+  test::ValueCallbackReceiver<FidoReturnCode> finished_callback_;
 };
 
-TEST(CredentialManagementHandlerTest, Test) {
-  base::test::ScopedTaskEnvironment scoped_task_environment(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
-
+TEST_F(CredentialManagementHandlerTest, Test) {
   ScopedVirtualFidoDevice virtual_device;
   VirtualCtap2Device::Config ctap_config;
   ctap_config.pin_support = true;
@@ -104,23 +74,29 @@
   ASSERT_TRUE(virtual_device.mutable_state()->InjectResidentKey(
       kCredentialID, kRPID, kUserID, kUserName, kUserDisplayName));
 
-  TestDelegate delegate;
-  CredentialManagementHandler handler(
-      /*connector=*/nullptr, {FidoTransportProtocol::kUsbHumanInterfaceDevice},
-      &delegate);
-  TestObserver observer;
-  handler.set_observer(&observer);
+  auto handler = MakeHandler();
+  ready_callback_.WaitForCallback();
 
-  scoped_task_environment.FastForwardUntilNoTasksRemain();
+  handler->GetCredentials(get_credentials_callback_.callback());
+  get_credentials_callback_.WaitForCallback();
 
-  EXPECT_FALSE(delegate.on_error.was_called())
-      << "error " << static_cast<int>(delegate.on_error.value());
-  EXPECT_TRUE(delegate.on_credential_metadata.was_called());
-  EXPECT_EQ(delegate.on_credential_metadata.value<0>(), 1u);
-  EXPECT_EQ(delegate.on_credential_metadata.value<1>(), 99u);
+  auto result = get_credentials_callback_.TakeResult();
+  ASSERT_EQ(std::get<0>(result), CtapDeviceResponseCode::kSuccess);
+  auto opt_response = std::move(std::get<1>(result));
+  ASSERT_TRUE(opt_response);
+  EXPECT_EQ(opt_response->size(), 1u);
+  auto num_remaining = std::get<2>(result);
+  ASSERT_TRUE(num_remaining);
+  EXPECT_EQ(*num_remaining, 99u);
 
-  // TODO(martinkr): This should be true but is not yet implemented.
-  EXPECT_FALSE(delegate.on_credentials_enumerated.was_called());
+  handler->DeleteCredential(
+      opt_response->front().credentials.front().credential_id.id(),
+      delete_callback_.callback());
+
+  delete_callback_.WaitForCallback();
+  ASSERT_EQ(CtapDeviceResponseCode::kSuccess, delete_callback_.value());
+  EXPECT_EQ(virtual_device.mutable_state()->registrations.size(), 0u);
+  EXPECT_FALSE(finished_callback_.was_called());
 }
 
 }  // namespace
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc
index 920408f..1b6acf1 100644
--- a/device/fido/fido_device_authenticator.cc
+++ b/device/fido/fido_device_authenticator.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "device/fido/authenticator_supported_options.h"
+#include "device/fido/credential_management.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/ctap_make_credential_request.h"
 #include "device/fido/features.h"
@@ -309,43 +310,182 @@
 void FidoDeviceAuthenticator::GetCredentialsMetadata(
     base::span<const uint8_t> pin_token,
     GetCredentialsMetadataCallback callback) {
-  if (!Options()->supports_credential_management) {
-    DCHECK(Options()->supports_credential_management_preview);
-    operation_ = std::make_unique<Ctap2DeviceOperation<
-        CredentialManagementPreviewRequestAdapter<CredentialsMetadataRequest>,
-        CredentialsMetadataResponse>>(
-        device_.get(),
-        CredentialManagementPreviewRequestAdapter<CredentialsMetadataRequest>(
-            CredentialsMetadataRequest(
-                fido_parsing_utils::Materialize(pin_token))),
-        std::move(callback),
-        base::BindOnce(&CredentialsMetadataResponse::Parse),
-        /*string_fixup_predicate=*/nullptr);
-    operation_->Start();
-    return;
-  }
+  DCHECK(Options()->supports_credential_management ||
+         Options()->supports_credential_management_preview);
 
-  operation_ = std::make_unique<Ctap2DeviceOperation<
-      CredentialsMetadataRequest, CredentialsMetadataResponse>>(
+  operation_ =
+      std::make_unique<Ctap2DeviceOperation<CredentialManagementRequest,
+                                            CredentialsMetadataResponse>>(
+          device_.get(),
+          CredentialManagementRequest::ForGetCredsMetadata(
+              Options()->supports_credential_management
+                  ? CredentialManagementRequest::kDefault
+                  : CredentialManagementRequest::kPreview,
+              pin_token),
+          std::move(callback),
+          base::BindOnce(&CredentialsMetadataResponse::Parse),
+          /*string_fixup_predicate=*/nullptr);
+  operation_->Start();
+}
+
+struct FidoDeviceAuthenticator::EnumerateCredentialsState {
+  EnumerateCredentialsState() = default;
+  EnumerateCredentialsState(EnumerateCredentialsState&&) = default;
+  EnumerateCredentialsState& operator=(EnumerateCredentialsState&&) = default;
+
+  std::vector<uint8_t> pin_token;
+  bool is_first_rp = true;
+  bool is_first_credential = true;
+  size_t rp_count;
+  size_t current_rp_credential_count;
+
+  FidoDeviceAuthenticator::EnumerateCredentialsCallback callback;
+  std::vector<AggregatedEnumerateCredentialsResponse> responses;
+};
+
+void FidoDeviceAuthenticator::EnumerateCredentials(
+    base::span<const uint8_t> pin_token,
+    EnumerateCredentialsCallback callback) {
+  DCHECK(Options()->supports_credential_management ||
+         Options()->supports_credential_management_preview);
+
+  EnumerateCredentialsState state;
+  state.pin_token = fido_parsing_utils::Materialize(pin_token);
+  state.callback = std::move(callback);
+
+  operation_ = std::make_unique<
+      Ctap2DeviceOperation<CredentialManagementRequest, EnumerateRPsResponse>>(
       device_.get(),
-      CredentialsMetadataRequest(fido_parsing_utils::Materialize(pin_token)),
-      std::move(callback), base::BindOnce(&CredentialsMetadataResponse::Parse),
+      CredentialManagementRequest::ForEnumerateRPsBegin(
+          Options()->supports_credential_management
+              ? CredentialManagementRequest::kDefault
+              : CredentialManagementRequest::kPreview,
+          pin_token),
+      base::BindOnce(&FidoDeviceAuthenticator::OnEnumerateRPsDone,
+                     weak_factory_.GetWeakPtr(), std::move(state)),
+      base::BindOnce(&EnumerateRPsResponse::Parse, /*expect_rp_count=*/true),
       // TODO(martinkr): implement utf-8 fixup and add a test for it.
       /*string_fixup_predicate=*/nullptr);
   operation_->Start();
 }
 
-void FidoDeviceAuthenticator::EnumerateCredentials(
-    base::span<const uint8_t> pin_token,
-    EnumerateCredentialsCallback callback) {
-  NOTREACHED();  // TODO: implement
+void FidoDeviceAuthenticator::OnEnumerateRPsDone(
+    EnumerateCredentialsState state,
+    CtapDeviceResponseCode status,
+    base::Optional<EnumerateRPsResponse> response) {
+  if (status != CtapDeviceResponseCode::kSuccess) {
+    std::move(state.callback).Run(status, base::nullopt);
+    return;
+  }
+  if (state.is_first_rp) {
+    if (response->rp_count == 0) {
+      std::move(state.callback).Run(status, std::move(state.responses));
+      return;
+    }
+    state.rp_count = response->rp_count;
+    state.is_first_rp = false;
+  }
+  DCHECK(response->rp);
+  DCHECK(response->rp_id_hash);
+
+  state.is_first_credential = true;
+  state.responses.emplace_back(std::move(*response->rp));
+
+  auto request = CredentialManagementRequest::ForEnumerateCredentialsBegin(
+      Options()->supports_credential_management
+          ? CredentialManagementRequest::kDefault
+          : CredentialManagementRequest::kPreview,
+      state.pin_token, std::move(*response->rp_id_hash));
+  operation_ =
+      std::make_unique<Ctap2DeviceOperation<CredentialManagementRequest,
+                                            EnumerateCredentialsResponse>>(
+          device_.get(), std::move(request),
+          base::BindOnce(&FidoDeviceAuthenticator::OnEnumerateCredentialsDone,
+                         weak_factory_.GetWeakPtr(), std::move(state)),
+          base::BindOnce(&EnumerateCredentialsResponse::Parse,
+                         /*expect_credential_count=*/true),
+          // TODO(martinkr): implement utf-8 fixup and add a test for it.
+          /*string_fixup_predicate=*/nullptr);
+  operation_->Start();
+}
+
+void FidoDeviceAuthenticator::OnEnumerateCredentialsDone(
+    EnumerateCredentialsState state,
+    CtapDeviceResponseCode status,
+    base::Optional<EnumerateCredentialsResponse> response) {
+  if (status != CtapDeviceResponseCode::kSuccess) {
+    std::move(state.callback).Run(status, base::nullopt);
+    return;
+  }
+  if (state.is_first_credential) {
+    state.current_rp_credential_count = response->credential_count;
+    state.is_first_credential = false;
+  }
+  state.responses.back().credentials.emplace_back(std::move(*response));
+
+  if (state.responses.back().credentials.size() <
+      state.current_rp_credential_count) {
+    operation_ =
+        std::make_unique<Ctap2DeviceOperation<CredentialManagementRequest,
+                                              EnumerateCredentialsResponse>>(
+            device_.get(),
+            CredentialManagementRequest::ForEnumerateCredentialsGetNext(
+                Options()->supports_credential_management
+                    ? CredentialManagementRequest::kDefault
+                    : CredentialManagementRequest::kPreview),
+            base::BindOnce(&FidoDeviceAuthenticator::OnEnumerateCredentialsDone,
+                           weak_factory_.GetWeakPtr(), std::move(state)),
+            base::BindOnce(&EnumerateCredentialsResponse::Parse,
+                           /*expect_credential_count=*/false),
+            // TODO(martinkr): implement utf-8 fixup and add a test for it.
+            /*string_fixup_predicate=*/nullptr);
+    operation_->Start();
+    return;
+  }
+
+  if (state.responses.size() < state.rp_count) {
+    operation_ =
+        std::make_unique<Ctap2DeviceOperation<CredentialManagementRequest,
+                                              EnumerateRPsResponse>>(
+            device_.get(),
+            CredentialManagementRequest::ForEnumerateRPsGetNext(
+                Options()->supports_credential_management
+                    ? CredentialManagementRequest::kDefault
+                    : CredentialManagementRequest::kPreview),
+            base::BindOnce(&FidoDeviceAuthenticator::OnEnumerateRPsDone,
+                           weak_factory_.GetWeakPtr(), std::move(state)),
+            base::BindOnce(&EnumerateRPsResponse::Parse,
+                           /*expect_rp_count=*/false),
+            // TODO(martinkr): implement utf-8 fixup and add a test for it.
+            /*string_fixup_predicate=*/nullptr);
+    operation_->Start();
+    return;
+  }
+
+  std::move(state.callback)
+      .Run(CtapDeviceResponseCode::kSuccess, std::move(state.responses));
+  return;
 }
 
 void FidoDeviceAuthenticator::DeleteCredential(
     base::span<const uint8_t> pin_token,
     base::span<const uint8_t> credential_id,
     DeleteCredentialCallback callback) {
-  NOTREACHED();  // TODO: implement
+  DCHECK(Options()->supports_credential_management ||
+         Options()->supports_credential_management_preview);
+
+  operation_ =
+      std::make_unique<Ctap2DeviceOperation<CredentialManagementRequest,
+                                            DeleteCredentialResponse>>(
+          device_.get(),
+          CredentialManagementRequest::ForDeleteCredential(
+              Options()->supports_credential_management
+                  ? CredentialManagementRequest::kDefault
+                  : CredentialManagementRequest::kPreview,
+              pin_token, fido_parsing_utils::Materialize(credential_id)),
+          std::move(callback), base::BindOnce(&DeleteCredentialResponse::Parse),
+          /*string_fixup_predicate=*/nullptr);
+  operation_->Start();
 }
 
 void FidoDeviceAuthenticator::Reset(ResetCallback callback) {
diff --git a/device/fido/fido_device_authenticator.h b/device/fido/fido_device_authenticator.h
index f7d12a9d..08bf6f9 100644
--- a/device/fido/fido_device_authenticator.h
+++ b/device/fido/fido_device_authenticator.h
@@ -23,6 +23,7 @@
 
 struct CtapGetAssertionRequest;
 struct CtapMakeCredentialRequest;
+struct EnumerateRPsResponse;
 class FidoDevice;
 class FidoTask;
 
@@ -106,6 +107,15 @@
  private:
   void InitializeAuthenticatorDone(base::OnceClosure callback);
 
+  struct EnumerateCredentialsState;
+  void OnEnumerateRPsDone(EnumerateCredentialsState state,
+                          CtapDeviceResponseCode status,
+                          base::Optional<EnumerateRPsResponse> response);
+  void OnEnumerateCredentialsDone(
+      EnumerateCredentialsState state,
+      CtapDeviceResponseCode status,
+      base::Optional<EnumerateCredentialsResponse> response);
+
   const std::unique_ptr<FidoDevice> device_;
   base::Optional<AuthenticatorSupportedOptions> options_;
   std::unique_ptr<FidoTask> task_;
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 287c7df..734b5edb 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -33,6 +33,7 @@
 #include "third_party/boringssl/src/include/openssl/digest.h"
 #include "third_party/boringssl/src/include/openssl/ec.h"
 #include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
 #include "third_party/boringssl/src/include/openssl/hmac.h"
 #include "third_party/boringssl/src/include/openssl/mem.h"
 #include "third_party/boringssl/src/include/openssl/obj.h"
@@ -66,15 +67,14 @@
 }
 
 // CheckPINToken returns true iff |pin_auth| is a valid authentication of
-// |client_data_hash| given that the PIN token in effect is |pin_token|.
+// |data| given that the PIN token in effect is |pin_token|.
 bool CheckPINToken(base::span<const uint8_t> pin_token,
                    base::span<const uint8_t> pin_auth,
-                   base::span<const uint8_t> client_data_hash) {
+                   base::span<const uint8_t> data) {
   uint8_t calculated_pin_auth[SHA256_DIGEST_LENGTH];
   unsigned hmac_bytes;
-  CHECK(HMAC(EVP_sha256(), pin_token.data(), pin_token.size(),
-             client_data_hash.data(), client_data_hash.size(),
-             calculated_pin_auth, &hmac_bytes));
+  CHECK(HMAC(EVP_sha256(), pin_token.data(), pin_token.size(), data.data(),
+             data.size(), calculated_pin_auth, &hmac_bytes));
   DCHECK_EQ(sizeof(calculated_pin_auth), static_cast<size_t>(hmac_bytes));
 
   return pin_auth.size() == 16 &&
@@ -1254,8 +1254,9 @@
     if (!registration.second.is_resident) {
       continue;
     }
-    DCHECK(!registration.second.is_u2f && registration.second.user &&
-           registration.second.rp);
+    DCHECK(!registration.second.is_u2f);
+    DCHECK(registration.second.user);
+    DCHECK(registration.second.rp);
     if (!base::ContainsKey(rp_ids, registration.second.rp->rp_id())) {
       mutable_state()->pending_rps.push_back(*registration.second.rp);
     }
@@ -1281,12 +1282,16 @@
             *registration.second.user));
     response_map.emplace(
         static_cast<int>(CredentialManagementResponseKey::kCredentialID),
-        registration.first);
+        PublicKeyCredentialDescriptor(CredentialType::kPublicKey,
+                                      registration.first)
+            .ConvertToCBOR());
     std::string public_key;
-    CHECK(registration.second.private_key->ExportRawPublicKey(&public_key));
+    EC_KEY* ec_key =
+        EVP_PKEY_get0_EC_KEY(registration.second.private_key->key());
+    CHECK(ec_key != nullptr);
     response_map.emplace(
         static_cast<int>(CredentialManagementResponseKey::kPublicKey),
-        ConstructECPublicKey(public_key)->EncodeAsCOSEKey());
+        pin::EncodeCOSEPublicKey(ec_key));
     mutable_state()->pending_registrations.emplace_back(
         std::move(response_map));
   }
diff --git a/device/fido/virtual_fido_device.cc b/device/fido/virtual_fido_device.cc
index 62a50cb0..81c1b45 100644
--- a/device/fido/virtual_fido_device.cc
+++ b/device/fido/virtual_fido_device.cc
@@ -107,10 +107,10 @@
                                 std::move(application_parameter),
                                 0 /* signature counter */);
   registration.is_resident = true;
-  PublicKeyCredentialUserEntity user(std::move(user_id_bytes));
-  user.name = name;
-  user.display_name = display_name;
-  registration.user = std::move(user);
+  registration.rp = PublicKeyCredentialRpEntity(std::move(relying_party_id));
+  registration.user = PublicKeyCredentialUserEntity(std::move(user_id_bytes));
+  registration.user->name = name;
+  registration.user->display_name = display_name;
 
   bool was_inserted;
   std::tie(std::ignore, was_inserted) = registrations.emplace(
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index 600f13a..a70e178 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -650,7 +650,6 @@
     // Compositor flags
     command_line.AppendSwitch(::switches::kRunAllCompositorStagesBeforeDraw);
     command_line.AppendSwitch(::switches::kDisableNewContentRenderingTimeout);
-    command_line.AppendSwitch(::switches::kEnableSurfaceSynchronization);
     // Ensure that image animations don't resync their animation timestamps when
     // looping back around.
     command_line.AppendSwitch(::switches::kDisableImageAnimationResync);
diff --git a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
index c59f12f2..05a098d 100644
--- a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
+++ b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
@@ -27,11 +27,11 @@
       "app": "cronet_unittests_ios",
       "device type": "iPhone 5s",
       "os": "9.3",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -42,11 +42,11 @@
       "app": "cronet_test",
       "device type": "iPhone 5s",
       "os": "9.3",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -57,11 +57,11 @@
       "app": "cronet_test",
       "device type": "iPad Retina",
       "os": "9.3",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -72,11 +72,11 @@
       "app": "cronet_test",
       "device type": "iPhone 5s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -87,11 +87,11 @@
       "app": "cronet_test",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -102,11 +102,11 @@
       "app": "cronet_test",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -117,11 +117,11 @@
       "app": "cronet_test",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.fyi/ios-simulator.json b/ios/build/bots/chromium.fyi/ios-simulator.json
index 0691392..5104fe4 100644
--- a/ios/build/bots/chromium.fyi/ios-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios-simulator.json
@@ -21,11 +21,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -40,11 +40,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -59,11 +59,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -78,11 +78,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -97,11 +97,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -116,11 +116,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-              "host os": "Mac-10.13.6"
+              "host os": "Mac-10.14.4"
           }],
           "60": [{
               "host os": "Mac-10.14.3"
@@ -135,11 +135,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -154,11 +154,11 @@
       "device type": "iPhone 6s",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.fyi/ios12-beta-simulator.json b/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
index efcaf67fc..fdba38f 100644
--- a/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
@@ -19,11 +19,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -35,11 +35,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -51,11 +51,11 @@
       "device type": "iPhone 6 Plus",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -67,11 +67,11 @@
       "device type": "iPhone 5s",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -83,11 +83,11 @@
       "device type": "iPad Pro",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -99,11 +99,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -115,11 +115,11 @@
       "device type": "iPhone 6 Plus",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -131,11 +131,11 @@
       "device type": "iPad Air",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -147,11 +147,11 @@
       "device type": "iPhone 5s",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -163,11 +163,11 @@
       "device type": "iPhone 6s Plus",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -179,11 +179,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -195,11 +195,11 @@
       "device type": "iPhone 5s",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -211,11 +211,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xcode build version": "10o45e",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
index f93493f..5bf6d51 100644
--- a/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
@@ -28,11 +28,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -46,11 +46,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -63,11 +63,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -81,11 +81,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -98,11 +98,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPhone 7",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -116,11 +116,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone 7",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -133,11 +133,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPhone 7",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -151,11 +151,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone 7",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -168,11 +168,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -186,11 +186,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -203,11 +203,11 @@
       "include": "eg_cq_tests_ios12_simulator_fyi_experiment.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -221,11 +221,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
index f441b09..b9b8937 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
@@ -22,11 +22,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -38,11 +38,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -54,11 +54,11 @@
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -70,11 +70,11 @@
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -86,11 +86,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -102,11 +102,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -118,11 +118,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -134,11 +134,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -150,11 +150,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -166,11 +166,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.mac/ios-simulator.json b/ios/build/bots/chromium.mac/ios-simulator.json
index ef943ce..ff45062 100644
--- a/ios/build/bots/chromium.mac/ios-simulator.json
+++ b/ios/build/bots/chromium.mac/ios-simulator.json
@@ -23,11 +23,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -39,11 +39,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -55,11 +55,11 @@
       "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -71,11 +71,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -87,11 +87,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -103,11 +103,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -119,11 +119,11 @@
       "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -135,11 +135,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -151,11 +151,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.mac/ios-slimnav.json b/ios/build/bots/chromium.mac/ios-slimnav.json
index dd0f4ee2..caabc6206 100644
--- a/ios/build/bots/chromium.mac/ios-slimnav.json
+++ b/ios/build/bots/chromium.mac/ios-slimnav.json
@@ -21,11 +21,11 @@
       ],
       "device type": "iPhone 6s Plus",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -40,11 +40,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -59,11 +59,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -78,11 +78,11 @@
       ],
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -97,11 +97,11 @@
       ],
       "device type": "iPhone 6s Plus",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -116,11 +116,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -135,11 +135,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -154,11 +154,11 @@
       ],
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -173,11 +173,11 @@
       ],
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -195,11 +195,11 @@
       "shards": 3,
       "xcode parallelization": true,
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -215,11 +215,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -235,11 +235,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -255,11 +255,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -275,11 +275,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -295,11 +295,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -315,11 +315,11 @@
       "device type": "iPad Air 2",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -337,11 +337,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -357,11 +357,11 @@
       "xctest": true,
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -377,11 +377,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -397,11 +397,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -417,11 +417,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -437,11 +437,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -457,11 +457,11 @@
       "device type": "iPad Air 2",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -479,11 +479,11 @@
       "shards": 3,
       "xcode parallelization": true,
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -499,11 +499,11 @@
       "xctest": true,
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -519,11 +519,11 @@
       "device type": "iPhone X",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -539,11 +539,11 @@
       "device type": "iPhone X",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -559,11 +559,11 @@
       "device type": "iPhone X",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -579,11 +579,11 @@
       "device type": "iPhone X",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -599,11 +599,11 @@
       "device type": "iPhone X",
       "os": "11.4",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -621,11 +621,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -641,11 +641,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -661,11 +661,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -681,11 +681,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -701,11 +701,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -721,11 +721,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -741,11 +741,11 @@
       "device type": "iPhone X",
       "os": "12.1",
       "xctest": true,
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -760,11 +760,11 @@
       ],
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -779,11 +779,11 @@
       ],
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/build/bots/chromium.mac/ios12-sdk-simulator.json b/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
index eb23bc0..19ae2c0 100644
--- a/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
+++ b/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
@@ -23,11 +23,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -38,11 +38,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -53,11 +53,11 @@
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -68,11 +68,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -83,11 +83,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -98,11 +98,11 @@
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -113,11 +113,11 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -128,11 +128,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -143,11 +143,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -158,11 +158,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -173,11 +173,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -188,11 +188,11 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -203,11 +203,11 @@
       "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -218,11 +218,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "12.1",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
@@ -233,11 +233,11 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "11.4",
-      "host os": "Mac-10.14.4",
+      "host os": "Mac-10.13.6",
       "pool":"Chrome",
       "optional_dimensions": {
           "60": [{
-            "host os": "Mac-10.13.6"
+            "host os": "Mac-10.14.4"
           }],
           "120": [{
             "host os": "Mac-10.14.3"
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 2f83fbd..432d595 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -575,6 +575,12 @@
      flag_descriptions::kSendTabToSelfBroadcastName,
      flag_descriptions::kSendTabToSelfBroadcastDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(send_tab_to_self::kSendTabToSelfBroadcast)},
+    {"autofill-use-mobile-label-disambiguation",
+     flag_descriptions::kAutofillUseMobileLabelDisambiguationName,
+     flag_descriptions::kAutofillUseMobileLabelDisambiguationDescription,
+     flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(
+         autofill::features::kAutofillUseMobileLabelDisambiguation)},
 };
 
 // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index 0a98500..437d8fc3 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -42,6 +42,12 @@
     "When enabled, shows the Google Pay logo animation when showing payments"
     "credit card suggestions in downstream keyboard accessory";
 
+const char kAutofillUseMobileLabelDisambiguationName[] =
+    "Autofill Uses Mobile Label Disambiguation";
+const char kAutofillUseMobileLabelDisambiguationDescription[] =
+    "When enabled, Autofill suggestions' labels are displayed using a "
+    "mobile-friendly format.";
+
 extern const char kBreakpadNoDelayInitialUploadName[] =
     "Remove delay on initial crash upload";
 extern const char kBreakpadNoDelayInitialUploadDescription[] =
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index 08509f0..af9543e 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -29,6 +29,11 @@
 extern const char kAutofillDownstreamUseGooglePayBrandingOniOSName[];
 extern const char kAutofillDownstreamUseGooglePayBrandingOniOSDescription[];
 
+// Title and description for the flag that controls whether Autofill's
+// suggestions' labels are formatting with a mobile-friendly approach.
+extern const char kAutofillUseMobileLabelDisambiguationName[];
+extern const char kAutofillUseMobileLabelDisambiguationDescription[];
+
 // Title and description for the flag to control if initial uploading of crash
 // reports is delayed.
 extern const char kBreakpadNoDelayInitialUploadName[];
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h
index 461e93c..f75a09a1 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h
@@ -24,9 +24,6 @@
  public:
   ~IOSChromePasswordManagerInfoBarDelegate() override;
 
-  // Updates the credentials being saved with |username| and |password|.
-  void UpdateCredentials(NSString* username, NSString* password);
-
   // Getter for the message displayed in addition to the title. If no message
   // was set, this returns an empty string.
   NSString* GetDetailsMessageText() const;
@@ -40,9 +37,6 @@
   // The URL host for which the credentials are being saved for.
   NSString* GetURLHostText() const;
 
-  // The title for the InfobarModal being presented.
-  virtual NSString* GetInfobarModalTitleText() const;
-
   // Sets the dispatcher for this delegate.
   void set_dispatcher(id<ApplicationCommands> dispatcher);
 
@@ -67,13 +61,13 @@
   }
 
  private:
-  // ConfirmInfoBarDelegate implementation.
-  int GetIconId() const override;
-
   // The password_manager::PasswordFormManager managing the form we're asking
   // the user about, and should save as per their decision.
   std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save_;
 
+  // ConfirmInfoBarDelegate implementation.
+  int GetIconId() const override;
+
   // Used to track the results we get from the info bar.
   password_manager::metrics_util::UIDismissalReason infobar_response_;
 
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
index 5cad56c..c9f22e3 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
@@ -9,7 +9,6 @@
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
-#include "components/password_manager/core/browser/password_ui_utils.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -31,16 +30,6 @@
       infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION),
       is_sync_user_(is_sync_user) {}
 
-void IOSChromePasswordManagerInfoBarDelegate::UpdateCredentials(
-    NSString* username,
-    NSString* password) {
-  const base::string16 username_string = base::SysNSStringToUTF16(username);
-  const base::string16 password_string = base::SysNSStringToUTF16(password);
-  UpdatePasswordFormUsernameAndPassword(username_string, password_string,
-                                        form_to_save_.get());
-  form_to_save()->Save();
-}
-
 NSString* IOSChromePasswordManagerInfoBarDelegate::GetDetailsMessageText()
     const {
   return is_sync_user_ ? l10n_util::GetNSString(IDS_SAVE_PASSWORD_FOOTER) : @"";
@@ -60,12 +49,6 @@
   return base::SysUTF8ToNSString(form_to_save_->GetOrigin().host());
 }
 
-NSString* IOSChromePasswordManagerInfoBarDelegate::GetInfobarModalTitleText()
-    const {
-  NOTREACHED() << "Subclass must implement.";
-  return @"";
-}
-
 void IOSChromePasswordManagerInfoBarDelegate::set_dispatcher(
     id<ApplicationCommands> dispatcher) {
   dispatcher_ = dispatcher;
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
index 6bae92e..913498d 100644
--- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
@@ -20,27 +20,44 @@
 // password_manager::PasswordFormManager and move it to a
 // IOSChromeSavePasswordInfoBarDelegate while the user makes up their mind
 // with the "save password" infobar.
+// If |password_update| is true the delegate will use "Update" related strings,
+// and should Update the credentials instead of Saving new ones.
 class IOSChromeSavePasswordInfoBarDelegate
     : public IOSChromePasswordManagerInfoBarDelegate {
  public:
   IOSChromeSavePasswordInfoBarDelegate(
       bool is_sync_user,
+      bool password_update,
       std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save);
 
   ~IOSChromeSavePasswordInfoBarDelegate() override;
 
+  // InfoBarDelegate implementation
   bool ShouldExpire(const NavigationDetails& details) const override;
 
- private:
   // ConfirmInfoBarDelegate implementation.
-  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   base::string16 GetMessageText() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
 
-  // IOSChromePasswordManagerInfoBarDelegate implementation.
-  NSString* GetInfobarModalTitleText() const override;
+  // Updates the credentials being saved with |username| and |password|.
+  void UpdateCredentials(NSString* username, NSString* password);
+
+  // true if password is being updated at the moment the InfobarModal is
+  // created.
+  bool IsPasswordUpdate() const;
+
+  // The title for the InfobarModal being presented.
+  NSString* GetInfobarModalTitleText() const;
+
+ private:
+  // ConfirmInfoBarDelegate implementation.
+  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+
+  // true if password is being updated at the moment the InfobarModal is
+  // created.
+  bool password_update_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(IOSChromeSavePasswordInfoBarDelegate);
 };
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
index 35946a5..41e74e2 100644
--- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
@@ -7,11 +7,13 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "base/strings/sys_string_conversions.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager_constants.h"
+#include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
@@ -26,9 +28,11 @@
 
 IOSChromeSavePasswordInfoBarDelegate::IOSChromeSavePasswordInfoBarDelegate(
     bool is_sync_user,
+    bool password_update,
     std::unique_ptr<PasswordFormManagerForUI> form_manager)
     : IOSChromePasswordManagerInfoBarDelegate(is_sync_user,
-                                              std::move(form_manager)) {
+                                              std::move(form_manager)),
+      password_update_(password_update) {
   form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown(
       form_to_save()->GetCredentialSource(),
       password_manager::metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING);
@@ -46,6 +50,9 @@
 }
 
 base::string16 IOSChromeSavePasswordInfoBarDelegate::GetMessageText() const {
+  if (IsInfobarUIRebootEnabled() && IsPasswordUpdate()) {
+    return l10n_util::GetStringUTF16(IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD);
+  }
   return l10n_util::GetStringUTF16(
       IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT);
 }
@@ -53,16 +60,29 @@
 NSString* IOSChromeSavePasswordInfoBarDelegate::GetInfobarModalTitleText()
     const {
   DCHECK(IsInfobarUIRebootEnabled());
-  return l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_TITLE);
+  return l10n_util::GetNSString(
+      IsPasswordUpdate() ? IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD_TITLE
+                         : IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_TITLE);
 }
 
 base::string16 IOSChromeSavePasswordInfoBarDelegate::GetButtonLabel(
     InfoBarButton button) const {
   if (IsInfobarUIRebootEnabled()) {
-    return l10n_util::GetStringUTF16(
-        (button == BUTTON_OK)
-            ? IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON
-            : IDS_IOS_PASSWORD_MANAGER_MODAL_BLACKLIST_BUTTON);
+    switch (button) {
+      case BUTTON_OK:
+        return l10n_util::GetStringUTF16(
+            IsPasswordUpdate() ? IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON
+                               : IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON);
+      case BUTTON_CANCEL: {
+        return IsPasswordUpdate()
+                   ? base::string16()
+                   : l10n_util::GetStringUTF16(
+                         IDS_IOS_PASSWORD_MANAGER_MODAL_BLACKLIST_BUTTON);
+      }
+      case BUTTON_NONE:
+        NOTREACHED();
+        return base::string16();
+    }
   } else {
     return l10n_util::GetStringUTF16(
         (button == BUTTON_OK) ? IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON
@@ -74,11 +94,13 @@
   DCHECK(form_to_save());
   form_to_save()->Save();
   set_infobar_response(password_manager::metrics_util::CLICKED_SAVE);
+  password_update_ = true;
   return true;
 }
 
 bool IOSChromeSavePasswordInfoBarDelegate::Cancel() {
   DCHECK(form_to_save());
+  DCHECK(!password_update_);
   form_to_save()->PermanentlyBlacklist();
   set_infobar_response(password_manager::metrics_util::CLICKED_NEVER);
   return true;
@@ -88,3 +110,18 @@
     const NavigationDetails& details) const {
   return !details.is_redirect && ConfirmInfoBarDelegate::ShouldExpire(details);
 }
+
+void IOSChromeSavePasswordInfoBarDelegate::UpdateCredentials(
+    NSString* username,
+    NSString* password) {
+  DCHECK(IsInfobarUIRebootEnabled());
+  const base::string16 username_string = base::SysNSStringToUTF16(username);
+  const base::string16 password_string = base::SysNSStringToUTF16(password);
+  UpdatePasswordFormUsernameAndPassword(username_string, password_string,
+                                        form_to_save());
+}
+
+bool IOSChromeSavePasswordInfoBarDelegate::IsPasswordUpdate() const {
+  DCHECK(IsInfobarUIRebootEnabled());
+  return password_update_;
+}
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
index 1f9e441..5e99efb4 100644
--- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
@@ -67,9 +67,6 @@
   bool Cancel() override;
   base::string16 GetLinkText() const override;
 
-  // IOSChromePasswordManagerInfoBarDelegate implementation.
-  NSString* GetInfobarModalTitleText() const override;
-
   // The credential that should be displayed in the infobar, and for which the
   // password will be updated.
   base::string16 selected_account_;
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
index e8c696f..9a8b416 100644
--- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
@@ -17,8 +17,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/infobars/infobar.h"
 #import "ios/chrome/browser/passwords/update_password_infobar_controller.h"
-#import "ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.h"
-#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -41,20 +39,12 @@
       is_sync_user, std::move(form_manager)));
   delegate->set_dispatcher(dispatcher);
 
-  if (IsInfobarUIRebootEnabled()) {
-    InfobarPasswordCoordinator* coordinator =
-        [[InfobarPasswordCoordinator alloc]
-            initWithInfoBarDelegate:delegate.get()];
-    infobar_manager->AddInfoBar(
-        std::make_unique<InfoBarIOS>(coordinator, std::move(delegate)));
-  } else {
-    UpdatePasswordInfoBarController* controller =
-        [[UpdatePasswordInfoBarController alloc]
-            initWithBaseViewController:baseViewController
-                       infoBarDelegate:delegate.get()];
-    infobar_manager->AddInfoBar(
-        std::make_unique<InfoBarIOS>(controller, std::move(delegate)));
-  }
+  UpdatePasswordInfoBarController* controller =
+      [[UpdatePasswordInfoBarController alloc]
+          initWithBaseViewController:baseViewController
+                     infoBarDelegate:delegate.get()];
+  infobar_manager->AddInfoBar(
+      std::make_unique<InfoBarIOS>(controller, std::move(delegate)));
 }
 
 IOSChromeUpdatePasswordInfoBarDelegate::
@@ -102,26 +92,14 @@
                    IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD);
 }
 
-NSString* IOSChromeUpdatePasswordInfoBarDelegate::GetInfobarModalTitleText()
-    const {
-  DCHECK(IsInfobarUIRebootEnabled());
-  return l10n_util::GetNSString(IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD_TITLE);
-}
-
 int IOSChromeUpdatePasswordInfoBarDelegate::GetButtons() const {
   return BUTTON_OK;
 }
 
 base::string16 IOSChromeUpdatePasswordInfoBarDelegate::GetButtonLabel(
     InfoBarButton button) const {
-  if (IsInfobarUIRebootEnabled()) {
-    return (button == BUTTON_OK) ? l10n_util::GetStringUTF16(
-                                       IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON)
-                                 : base::string16();
-  } else {
-    DCHECK_EQ(BUTTON_OK, button);
-    return l10n_util::GetStringUTF16(IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON);
-  }
+  DCHECK_EQ(BUTTON_OK, button);
+  return l10n_util::GetStringUTF16(IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON);
 }
 
 bool IOSChromeUpdatePasswordInfoBarDelegate::Accept() {
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 7214109..a875afb 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -680,7 +680,7 @@
   switch (type) {
     case PasswordInfoBarType::SAVE: {
       auto delegate = std::make_unique<IOSChromeSavePasswordInfoBarDelegate>(
-          isSyncUser, std::move(form));
+          isSyncUser, /*password_update*/ false, std::move(form));
       delegate->set_dispatcher(self.dispatcher);
 
       if (IsInfobarUIRebootEnabled()) {
@@ -698,11 +698,24 @@
       }
       break;
     }
-    case PasswordInfoBarType::UPDATE:
-      IOSChromeUpdatePasswordInfoBarDelegate::Create(
-          isSyncUser, infoBarManager, std::move(form), self.baseViewController,
-          self.dispatcher);
+    case PasswordInfoBarType::UPDATE: {
+      if (IsInfobarUIRebootEnabled()) {
+        auto delegate = std::make_unique<IOSChromeSavePasswordInfoBarDelegate>(
+            isSyncUser, /*password_update*/ true, std::move(form));
+        delegate->set_dispatcher(self.dispatcher);
+        InfobarPasswordCoordinator* coordinator =
+            [[InfobarPasswordCoordinator alloc]
+                initWithInfoBarDelegate:delegate.get()];
+        infoBarManager->AddInfoBar(
+            std::make_unique<InfoBarIOS>(coordinator, std::move(delegate)));
+
+      } else {
+        IOSChromeUpdatePasswordInfoBarDelegate::Create(
+            isSyncUser, infoBarManager, std::move(form),
+            self.baseViewController, self.dispatcher);
+      }
       break;
+    }
   }
 }
 
diff --git a/ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.mm b/ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.mm
index 89d89f7..c666187a 100644
--- a/ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.mm
+++ b/ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.mm
@@ -7,8 +7,10 @@
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
+#include "components/sync/device_info/device_info_sync_service.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
+#import "ios/chrome/browser/sync/device_info_sync_service_factory.h"
 #include "ios/chrome/browser/sync/model_type_store_service_factory.h"
 #include "ios/chrome/common/channel_info.h"
 
@@ -38,6 +40,7 @@
           BrowserStateDependencyManager::GetInstance()) {
   DependsOn(ModelTypeStoreServiceFactory::GetInstance());
   DependsOn(ios::HistoryServiceFactory::GetInstance());
+  DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
 }
 
 SendTabToSelfSyncServiceFactory::~SendTabToSelfSyncServiceFactory() {}
@@ -56,6 +59,11 @@
       ios::HistoryServiceFactory::GetForBrowserState(
           browser_state, ServiceAccessType::EXPLICIT_ACCESS);
 
+  syncer::DeviceInfoTracker* device_info_tracker =
+      DeviceInfoSyncServiceFactory::GetForBrowserState(browser_state)
+          ->GetDeviceInfoTracker();
+
   return std::make_unique<SendTabToSelfSyncService>(
-      GetChannel(), std::move(store_factory), history_service);
+      GetChannel(), std::move(store_factory), history_service,
+      device_info_tracker);
 }
diff --git a/ios/chrome/browser/ui/alert_view_controller/alert_view_controller.mm b/ios/chrome/browser/ui/alert_view_controller/alert_view_controller.mm
index 54bc7090..af54c4b 100644
--- a/ios/chrome/browser/ui/alert_view_controller/alert_view_controller.mm
+++ b/ios/chrome/browser/ui/alert_view_controller/alert_view_controller.mm
@@ -31,25 +31,30 @@
 constexpr CGFloat kMinimumHeight = 30;
 constexpr CGFloat kMinimumMargin = 4;
 
+// Inset at the top of the alert. Is always present.
+constexpr CGFloat kAlertMarginTop = 22;
+// Space before the actions and everything else.
+constexpr CGFloat kAlertActionsSpacing = 12;
+
 // Insets for the content in the alert view.
-constexpr CGFloat kTitleInsetTop = 20;
+constexpr CGFloat kTitleInsetTop = 0;
 constexpr CGFloat kTitleInsetLeading = 20;
-constexpr CGFloat kTitleInsetBottom = 4;
+constexpr CGFloat kTitleInsetBottom = 9;
 constexpr CGFloat kTitleInsetTrailing = 20;
 
-constexpr CGFloat kMessageInsetTop = 4;
+constexpr CGFloat kMessageInsetTop = 0;
 constexpr CGFloat kMessageInsetLeading = 20;
-constexpr CGFloat kMessageInsetBottom = 10;
+constexpr CGFloat kMessageInsetBottom = 6;
 constexpr CGFloat kMessageInsetTrailing = 20;
 
-constexpr CGFloat kButtonInsetTop = 20;
+constexpr CGFloat kButtonInsetTop = 13;
 constexpr CGFloat kButtonInsetLeading = 20;
-constexpr CGFloat kButtonInsetBottom = 20;
+constexpr CGFloat kButtonInsetBottom = 13;
 constexpr CGFloat kButtonInsetTrailing = 20;
 
-constexpr CGFloat kTextfieldStackInsetTop = 10;
+constexpr CGFloat kTextfieldStackInsetTop = 12;
 constexpr CGFloat kTextfieldStackInsetLeading = 12;
-constexpr CGFloat kTextfieldStackInsetBottom = 20;
+constexpr CGFloat kTextfieldStackInsetBottom = 0;
 constexpr CGFloat kTextfieldStackInsetTrailing = 12;
 
 constexpr CGFloat kTextfieldInset = 8;
@@ -197,7 +202,10 @@
   stackView.axis = UILayoutConstraintAxisVertical;
   stackView.translatesAutoresizingMaskIntoConstraints = NO;
   [self.contentView addSubview:stackView];
-  AddSameConstraints(stackView, self.contentView);
+
+  ChromeDirectionalEdgeInsets stackViewInsets =
+      ChromeDirectionalEdgeInsetsMake(kAlertMarginTop, 0, 0, 0);
+  AddSameConstraintsWithInsets(stackView, self.contentView, stackViewInsets);
 
   if (self.title.length) {
     UILabel* titleLabel = [[UILabel alloc] init];
@@ -302,6 +310,12 @@
     }
   }
 
+  UIView* lastArrangedView = stackView.arrangedSubviews.lastObject;
+  if (lastArrangedView) {
+    [stackView setCustomSpacing:kAlertActionsSpacing
+                      afterView:lastArrangedView];
+  }
+
   self.buttonAlertActionsDictionary = [[NSMutableDictionary alloc] init];
   for (AlertAction* action in self.actions) {
     GrayHighlightButton* button = [[GrayHighlightButton alloc] init];
diff --git a/ios/chrome/browser/ui/infobars/badge/infobar_badge_button.mm b/ios/chrome/browser/ui/infobars/badge/infobar_badge_button.mm
index cd0d6d27..3801c38 100644
--- a/ios/chrome/browser/ui/infobars/badge/infobar_badge_button.mm
+++ b/ios/chrome/browser/ui/infobars/badge/infobar_badge_button.mm
@@ -85,9 +85,13 @@
     self.hidden = !display;
   };
   if (animated) {
+    // Shrink badge to nothing before animating it's expansion back to original
+    // scale.
+    self.transform = CGAffineTransformMakeScale(0, 0);
+    changeBadgeDisplay();
     [UIView animateWithDuration:kButtonAnimationDuration
                      animations:^{
-                       changeBadgeDisplay();
+                       self.transform = CGAffineTransformIdentity;
                      }];
 
   } else {
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
index 4840af6..46dc91e 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
@@ -193,7 +193,7 @@
 
 #pragma mark InfobarModalDelegate
 
-- (void)modalInfobarButtonWasPressed:(UIButton*)sender {
+- (void)modalInfobarButtonWasAccepted:(id)sender {
   [self performInfobarAction];
   [self.badgeDelegate infobarWasAccepted];
   [self dismissInfobarModal:sender animated:YES completion:nil];
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.h b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.h
index 22d2983..c75846b 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.h
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.h
@@ -7,13 +7,13 @@
 
 #import "ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h"
 
-class IOSChromePasswordManagerInfoBarDelegate;
+class IOSChromeSavePasswordInfoBarDelegate;
 
 // Coordinator that creates and manages the PasswordInfobar.
 @interface InfobarPasswordCoordinator : InfobarCoordinator
 
 - (instancetype)initWithInfoBarDelegate:
-    (IOSChromePasswordManagerInfoBarDelegate*)passwordInfoBarDelegate
+    (IOSChromeSavePasswordInfoBarDelegate*)passwordInfoBarDelegate
     NS_DESIGNATED_INITIALIZER;
 
 @end
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
index 28b1551d..cfb41c31 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -6,7 +6,7 @@
 
 #include "base/strings/sys_string_conversions.h"
 #include "ios/chrome/browser/infobars/infobar_controller_delegate.h"
-#import "ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h"
+#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h"
 #import "ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator_implementation.h"
@@ -23,7 +23,7 @@
 
 // Delegate that holds the Infobar information and actions.
 @property(nonatomic, readonly)
-    IOSChromePasswordManagerInfoBarDelegate* passwordInfoBarDelegate;
+    IOSChromeSavePasswordInfoBarDelegate* passwordInfoBarDelegate;
 // InfobarBannerViewController owned by this Coordinator.
 @property(nonatomic, strong) InfobarBannerViewController* bannerViewController;
 // InfobarPasswordTableViewController owned by this Coordinator.
@@ -39,7 +39,7 @@
 @synthesize modalViewController = _modalViewController;
 
 - (instancetype)initWithInfoBarDelegate:
-    (IOSChromePasswordManagerInfoBarDelegate*)passwordInfoBarDelegate {
+    (IOSChromeSavePasswordInfoBarDelegate*)passwordInfoBarDelegate {
   self = [super initWithInfoBarDelegate:passwordInfoBarDelegate];
   if (self) {
     _passwordInfoBarDelegate = passwordInfoBarDelegate;
@@ -132,13 +132,14 @@
 - (void)updateCredentialsWithUsername:(NSString*)username
                              password:(NSString*)password {
   self.passwordInfoBarDelegate->UpdateCredentials(username, password);
-  [self.badgeDelegate infobarWasAccepted];
-  [self dismissInfobarModal:self animated:YES completion:nil];
+  [self modalInfobarButtonWasAccepted:self];
 }
 
 - (void)neverSaveCredentialsForCurrentSite {
   self.passwordInfoBarDelegate->Cancel();
-  [self dismissInfobarModal:self animated:YES completion:nil];
+  // Completely remove the Infobar along with its badge after blacklisting the
+  // Website.
+  [self detachView];
 }
 
 - (void)presentPasswordSettings {
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
index 3ece0749..88d296d 100644
--- a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
@@ -17,8 +17,9 @@
                    animated:(BOOL)animated
                  completion:(ProceduralBlock)completion;
 
-// Called when the InfobarModal "Accept" button was pressed.
-- (void)modalInfobarButtonWasPressed:(UIButton*)sender;
+// Called when the InfobarModal was Accepted. Meaning it will perform the main
+// action.
+- (void)modalInfobarButtonWasAccepted:(id)sender;
 
 @end
 
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
index 7667bcb..b31a9efa 100644
--- a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
@@ -205,7 +205,7 @@
 - (void)saveCredentialsButtonWasPressed:(UIButton*)sender {
   [self.infobarModalDelegate
       updateCredentialsWithUsername:self.usernameItem.textFieldValue
-                           password:self.passwordItem.textFieldValue];
+                           password:self.unmaskedPassword];
 }
 
 @end
diff --git a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm
index e0e15e1..5b5065e 100644
--- a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm
+++ b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm
@@ -130,7 +130,7 @@
 
 #pragma mark InfobarModalDelegate
 
-- (void)modalInfobarButtonWasPressed:(UIButton*)sender {
+- (void)modalInfobarButtonWasAccepted:(id)sender {
   [self dismissInfobarModal:sender animated:YES completion:nil];
 }
 
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm
index fb63d6b8..99cddba 100644
--- a/ios/web/app/web_main_loop.mm
+++ b/ios/web/app/web_main_loop.mm
@@ -18,7 +18,6 @@
 #include "base/power_monitor/power_monitor_device_source.h"
 #include "base/process/process_metrics.h"
 #include "base/task/post_task.h"
-#include "base/task/thread_pool/scheduler_worker_pool_params.h"
 #include "base/task/thread_pool/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #import "ios/web/net/cookie_notification_bridge.h"
diff --git a/ios/web/public/global_state/ios_global_state.mm b/ios/web/public/global_state/ios_global_state.mm
index 13fcb44d15..cf45518 100644
--- a/ios/web/public/global_state/ios_global_state.mm
+++ b/ios/web/public/global_state/ios_global_state.mm
@@ -36,12 +36,12 @@
   constexpr int kReclaimTimeForeground = 30;
 
   return base::ThreadPool::InitParams(
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(
               kMinBackgroundThreads, kMaxBackgroundThreads,
               kCoreMultiplierBackgroundThreads, kOffsetBackgroundThreads),
           base::TimeDelta::FromSeconds(kReclaimTimeBackground)),
-      base::SchedulerWorkerPoolParams(
+      base::ThreadGroupParams(
           base::RecommendedMaxNumberOfThreadsInPool(
               kMinForegroundThreads, kMaxForegroundThreads,
               kCoreMultiplierForegroundThreads, kOffsetForegroundThreads),
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index 4ab5a244..ecbb510 100644
--- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -12,7 +12,6 @@
   "//chromeos/typemaps.gni",
   "//chromeos/components/multidevice/mojom/typemaps.gni",
   "//chromeos/services/network_config/public/mojom/typemaps.gni",
-  "//chromeos/services/power/public/mojom/typemaps.gni",
   "//chromeos/services/secure_channel/public/mojom/typemaps.gni",
   "//components/arc/common/typemaps.gni",
   "//components/chromeos_camera/common/typemaps.gni",
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 964803d..8bb0522 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -783,7 +783,7 @@
         return "std::numeric_limits<float>::quiet_NaN()"
 
     if (kind is not None and mojom.IsFloatKind(kind)):
-        return token if token.isdigit() else token + "f";
+      return token if token.isdigit() else token + "f"
 
     # Per C++11, 2.14.2, the type of an integer literal is the first of the
     # corresponding list in Table 6 in which its value can be represented. In
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index 423c1fd2..5c6cf45d 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -49,7 +49,7 @@
       return ('{\n%s\n}' % (',\n'.join('    %s: %s' % (
           Repr(key, as_ref).replace('\n', '\n    '),
           Repr(val, as_ref).replace('\n', '\n    '))
-          for key, val in obj.iteritems())))
+          for key, val in obj.items())))
   else:
     return repr(obj)
 
@@ -70,10 +70,8 @@
     return '    %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace(
         '\n', '\n    '))
 
-  return '%s(\n%s\n)' % (
-      obj.__class__.__name__,
-      ',\n'.join(ReprIndent(name, as_ref)
-                 for (name, as_ref) in names.iteritems()))
+  return '%s(\n%s\n)' % (obj.__class__.__name__, ',\n'.join(
+      ReprIndent(name, as_ref) for (name, as_ref) in names.items()))
 
 
 class Kind(object):
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
index c9285d9..16d643e 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
@@ -247,12 +247,12 @@
 def _Import(module, import_module):
   # Copy the struct kinds from our imports into the current module.
   importable_kinds = (mojom.Struct, mojom.Union, mojom.Enum, mojom.Interface)
-  for kind in import_module.kinds.itervalues():
+  for kind in import_module.kinds.values():
     if (isinstance(kind, importable_kinds) and
         kind.module.path == import_module.path):
       module.kinds[kind.spec] = kind
   # Ditto for values.
-  for value in import_module.values.itervalues():
+  for value in import_module.values.values():
     if value.module.path == import_module.path:
       module.values[value.GetSpec()] = value
 
diff --git a/mojo/public/tools/chrome_ipc/generate_mojom.py b/mojo/public/tools/chrome_ipc/generate_mojom.py
index b15e50b3..68cc0fa 100755
--- a/mojo/public/tools/chrome_ipc/generate_mojom.py
+++ b/mojo/public/tools/chrome_ipc/generate_mojom.py
@@ -95,11 +95,11 @@
     yield 'type_mappings = [\n  %s\n]' % '\n  '.join(new_mappings)
 
   def _format_new_mappings(self, namespace):
-    for native, mojom in self._new_custom_mappings.iteritems():
+    for native, mojom in self._new_custom_mappings.items():
       yield '"%s.%s=::%s",' % (namespace, mojom, native)
 
   def format_new_types(self):
-    for native_type, typename in self._new_custom_mappings.iteritems():
+    for native_type, typename in self._new_custom_mappings.items():
       if native_type in self._enums:
         yield '[Native]\nenum %s;\n' % typename
       else:
@@ -353,7 +353,7 @@
     for m in self._get_messages():
       grouped_messages.setdefault(m.group, []).append(m)
     self._typemaps.load_typemaps()
-    for interface, messages in grouped_messages.iteritems():
+    for interface, messages in grouped_messages.items():
       self._interface_definitions.append(self._format_interface(interface,
                                                                 messages))
 
diff --git a/net/base/features.cc b/net/base/features.cc
index 527667d..2811e0e 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -22,6 +22,9 @@
 const base::Feature kEnforceTLS13Downgrade{"EnforceTLS13Downgrade",
                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kEnableTLS13EarlyData{"EnableTLS13EarlyData",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kNetworkQualityEstimator{"NetworkQualityEstimator",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/net/base/features.h b/net/base/features.h
index 1a862ee6..fd6f3074 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -24,6 +24,9 @@
 // with some buggy non-compliant TLS-terminating proxies.
 NET_EXPORT extern const base::Feature kEnforceTLS13Downgrade;
 
+// Enables TLS 1.3 early data.
+NET_EXPORT extern const base::Feature kEnableTLS13EarlyData;
+
 // Enables optimizing the network quality estimation algorithms in network
 // quality estimator (NQE).
 NET_EXPORT extern const base::Feature kNetworkQualityEstimator;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 8ef12ea5..f14d716 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -18,6 +18,7 @@
 #include "base/trace_event/memory_dump_request_args.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "base/values.h"
+#include "net/base/features.h"
 #include "net/dns/host_resolver.h"
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_response_body_drainer.h"
@@ -95,7 +96,6 @@
       time_func(&base::TimeTicks::Now),
       enable_http2_alternative_service(false),
       enable_websocket_over_http2(false),
-      enable_early_data(false),
       enable_quic(false),
       enable_quic_proxies_for_https_urls(false),
       quic_max_packet_length(quic::kDefaultMaxPacketSize),
@@ -138,6 +138,8 @@
       http_09_on_non_default_ports_enabled(false),
       disable_idle_sockets_close_on_memory_pressure(false) {
   quic_supported_versions.push_back(quic::QUIC_VERSION_43);
+  enable_early_data =
+      base::FeatureList::IsEnabled(features::kEnableTLS13EarlyData);
 }
 
 HttpNetworkSession::Params::Params(const Params& other) = default;
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index ea4dad8c..a7346f4 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -572,9 +572,9 @@
   auto sequenced_task_runner = base::CreateSequencedTaskRunnerWithTraits({});
 
   // Since we cannot use StartFetchAndWait(), which runs a nested RunLoop owned
-  // by the Delegate, on a SchedulerWorker Sequence, this test is split into
-  // two Callbacks, both run on |sequenced_task_runner_|. The test main thread
-  // then runs its own RunLoop, which the second of the Callbacks will quit.
+  // by the Delegate, in the ThreadPool, this test is split into two Callbacks,
+  // both run on |sequenced_task_runner_|. The test main thread then runs its
+  // own RunLoop, which the second of the Callbacks will quit.
   base::RunLoop run_loop;
 
   // Actually start the test fetch, on the Sequence.
diff --git a/services/service_manager/README.md b/services/service_manager/README.md
index 2af79b6..fdbd36d 100644
--- a/services/service_manager/README.md
+++ b/services/service_manager/README.md
@@ -197,7 +197,7 @@
 
  private:
   // service_manager::Service:
-  void OnBindInterface(const service_mangaer::BindSourceInfo& source,
+  void OnBindInterface(const service_manager::BindSourceInfo& source,
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override {
     if (interface_name == mojom::BlockAllocator::Name_) {
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 46b2401..789762f 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -29,10 +29,7 @@
 
 # External-facing config for dependent code.
 config("skia_config") {
-  include_dirs = [
-    "//third_party/skia",
-    "//third_party/skia/third_party/skcms",
-  ]
+  include_dirs = [ "//third_party/skia" ]
   if (enable_vulkan) {
     include_dirs += [
       "//third_party/vulkan/include",
@@ -195,8 +192,9 @@
   }
 
   public = [
-    "//third_party/skia/third_party/skcms/skcms.h",
+    "//third_party/skia/include/third_party/skcms/skcms.h",
   ]
+  include_dirs = [ "//third_party/skia/include/third_party/skcms" ]
   sources =
       rebase_path(skcms_sources, ".", "//third_party/skia/third_party/skcms")
 }
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 53bb516..4c005ce 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -52,10 +52,8 @@
       {
         "args": [
           "-v",
-          "--browser=exact",
+          "--browser=android-chrome",
           "--upload-results",
-          "--browser-executable=../../out/Release/bin/monochrome_64_32_bundle",
-          "--device=android",
           "--run-ref-build",
           "--test-shard-map-filename=android-pixel2-perf_map.json"
         ],
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 71447aef..3a2fe2be 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -44,7 +44,6 @@
     "snappy_compress_fuzzer.cc",
   ]
   deps = [
-    "//base",
     "//third_party/snappy:snappy",
   ]
   seed_corpus = "//third_party/snappy/src/testdata"
diff --git a/testing/libfuzzer/fuzzers/snappy_compress_fuzzer.cc b/testing/libfuzzer/fuzzers/snappy_compress_fuzzer.cc
index ad1ca974..e7dc95c 100644
--- a/testing/libfuzzer/fuzzers/snappy_compress_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/snappy_compress_fuzzer.cc
@@ -2,20 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/logging.h"
 #include "third_party/snappy/src/snappy.h"
 
+#define FUZZING_ASSERT(condition)                                      \
+  if (!(condition)) {                                                  \
+    fprintf(stderr, "%s\n", "Fuzzing Assertion Failure: " #condition); \
+    abort();                                                           \
+  }
+
 // Entry point for LibFuzzer.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   const char* uncompressed = reinterpret_cast<const char*>(data);
   std::string compressed;
   snappy::Compress(uncompressed, size, &compressed);
-  CHECK(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
+  FUZZING_ASSERT(
+      snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
 
   std::string uncompressed_after_compress;
-  CHECK(snappy::Uncompress(compressed.data(), compressed.size(),
-                           &uncompressed_after_compress));
-  CHECK_EQ(uncompressed_after_compress, std::string(uncompressed, size));
+  FUZZING_ASSERT(snappy::Uncompress(compressed.data(), compressed.size(),
+                                    &uncompressed_after_compress));
+  FUZZING_ASSERT(uncompressed_after_compress ==
+                 std::string(uncompressed, size));
 
   return 0;
 }
diff --git a/third_party/blink/public/mojom/portal/portal.mojom b/third_party/blink/public/mojom/portal/portal.mojom
index 4819ef2d..07c20cce 100644
--- a/third_party/blink/public/mojom/portal/portal.mojom
+++ b/third_party/blink/public/mojom/portal/portal.mojom
@@ -6,10 +6,13 @@
 
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
+import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 import "url/mojom/origin.mojom";
 
-// The Portal interface is used by the renderer to interact with the Portal.
+// The Portal interface is used by the HTMLPortalElement in the outer renderer
+// process to interact with the browser side implementation of a portal
+// (content::Portal). It is 1:1 with PortalClient (defined below).
 interface Portal {
   // Navigates the portal to |url|.
   Navigate(url.mojom.Url url);
@@ -18,6 +21,29 @@
   Activate(TransferableMessage data) => (bool was_adopted);
 
   // Sends message to the browser process, where it can be forwarded to the
-  // portal's main frame.
-  PostMessage(TransferableMessage message, url.mojom.Origin? target_origin);
+  // portal's main frame. |targetOrigin| indicates which origin the message can
+  // be delivered to, and if null, it indicates that the message can be
+  // delivered to any origin.
+  PostMessageToGuest(TransferableMessage message, url.mojom.Origin? target_origin);
+};
+
+// The PortalClient interface is used by the browser side implementation of a
+// portal to communicate with its host HTMLPortalElement in the outer renderer
+// process. It is 1:1 with Portal (defined above).
+interface PortalClient {
+  // Forwards message sent from the portal's guest to the portal's host
+  // HTMLPortalElement.
+  ForwardMessageFromGuest(string message,
+                          url.mojom.Origin source_origin,
+                          url.mojom.Origin? target_origin);
+};
+
+// Used by blink::PortalHost in the inner renderer process to communicate with
+// the browser side representation of the portal (content::Portal).
+interface PortalHost {
+  // Sends message to the browser process, from where it can be delivered to
+  // the portal's host HTMLPortalElement. |targetOrigin| indicates which origin
+  // the message can be delivered to, and if null, it indicates that the message
+  // can be delivered to any origin.
+  PostMessageToHost(string message, url.mojom.Origin? target_origin);
 };
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 4059e8f..8acc8fd 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2276,9 +2276,10 @@
   kV8RTCQuicTransport_SendDatagram_Method = 2869,
   kV8RTCQuicTransport_ReceiveDatagrams_Method = 2870,
   kCSSValueContainStyle = 2871,
-  kWebShareContainingFiles = 2872,
-  kWebShareWithoutFiles = 2873,
-  kWebShareCancelled = 2874,
+  kWebShareSuccessfulContainingFiles = 2872,
+  kWebShareSuccessfulWithoutFiles = 2873,
+  kWebShareUnsuccessfulContainingFiles = 2874,
+  kWebShareUnsuccessfulWithoutFiles = 2875,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/mojom/webshare/OWNERS b/third_party/blink/public/mojom/webshare/OWNERS
index 691beec..ad55720 100644
--- a/third_party/blink/public/mojom/webshare/OWNERS
+++ b/third_party/blink/public/mojom/webshare/OWNERS
@@ -1,3 +1,4 @@
+ericwilligers@chromium.org
 mgiuca@chromium.org
 sammc@chromium.org
 
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 8e5bc436..a2fdbaf7 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -236,6 +236,7 @@
   BLINK_PLATFORM_EXPORT static void EnableSignedExchangeSubresourcePrefetch(
       bool);
   BLINK_PLATFORM_EXPORT static void EnableIdleDetection(bool);
+  BLINK_PLATFORM_EXPORT static void EnableSkipTouchEventFilter(bool);
 
  private:
   WebRuntimeFeatures();
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 641a24b..8f34337 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -628,18 +628,21 @@
   // Portals -------------------------------------------------------------
 
   // Dispatches an event when a Portal gets activated. |portal_token| is the
-  // portal's unique identifier, and the message pipe |portal_pipe| is the
-  // portal's mojo interface. |data| is an optional message sent together with
-  // the portal's activation.
+  // portal's unique identifier, the message pipe |portal_pipe| is the
+  // portal's mojo interface, and the message pipe |portal_client_pipe| is
+  // a mojo interface to communicate back with the caller of the portal's
+  // mojo interface. |data| is an optional message sent together with the
+  // portal's activation.
   using OnPortalActivatedCallback = base::OnceCallback<void(bool)>;
   virtual void OnPortalActivated(
       const base::UnguessableToken& portal_token,
       mojo::ScopedInterfaceEndpointHandle portal_pipe,
+      mojo::ScopedInterfaceEndpointHandle portal_client_pipe,
       TransferableMessage data,
       OnPortalActivatedCallback callback) = 0;
 
-  // Forwards message to the PortalHost associated with frame.
-  virtual void ForwardMessageToPortalHost(
+  // Forwards message to the PortalHost object exposed by the frame.
+  virtual void ForwardMessageFromHost(
       TransferableMessage message,
       const WebSecurityOrigin& source_origin,
       const base::Optional<WebSecurityOrigin>& target_origin) = 0;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 41851298..dd31111 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -238,7 +238,8 @@
 
   // Request the creation of a new portal.
   virtual std::pair<WebRemoteFrame*, base::UnguessableToken> CreatePortal(
-      mojo::ScopedInterfaceEndpointHandle pipe) {
+      mojo::ScopedInterfaceEndpointHandle request_pipe,
+      mojo::ScopedInterfaceEndpointHandle client_pipe) {
     return std::pair<WebRemoteFrame*, base::UnguessableToken>(
         nullptr, base::UnguessableToken());
   }
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn
index 4230eeae..48a76712 100644
--- a/third_party/blink/renderer/core/css/BUILD.gn
+++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -444,8 +444,6 @@
     "pseudo_style_request.h",
     "remote_font_face_source.cc",
     "remote_font_face_source.h",
-    "resolver/animated_style_builder.cc",
-    "resolver/animated_style_builder.h",
     "resolver/css_property_priority.h",
     "resolver/css_to_style_map.cc",
     "resolver/css_to_style_map.h",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index f85710b..4697aef 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -124,15 +124,15 @@
     // - interpolable
     // The interpolable flag indicates whether a property can be animated
     // smoothly. If this flag is set, the property should also be added to the
-    // switch statements in AnimatedStyleBuilder, CSSPropertyEquality and
-    // CSSAnimatableValueFactory.
-    // - inherited
-    // The property will inherit by default if no value is specified, typically
-    // mentioned in specifications as "Inherited: yes"
+    // switch statements in CSSPropertyEquality and CSSInterpolationTypesMap.
     interpolable: {
       default: false,
       valid_type: "bool",
     },
+
+    // - inherited
+    // The property will inherit by default if no value is specified, typically
+    // mentioned in specifications as "Inherited: yes"
     inherited: {
       default: false,
       valid_type: "bool",
diff --git a/third_party/blink/renderer/core/css/resolver/animated_style_builder.cc b/third_party/blink/renderer/core/css/resolver/animated_style_builder.cc
deleted file mode 100644
index ff7eb3b..0000000
--- a/third_party/blink/renderer/core/css/resolver/animated_style_builder.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/css/resolver/animated_style_builder.h"
-
-#include "third_party/blink/renderer/core/animation/animatable/animatable_double.h"
-#include "third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h"
-#include "third_party/blink/renderer/core/animation/animatable/animatable_transform.h"
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
-#include "third_party/blink/renderer/core/style/computed_style.h"
-
-#include <type_traits>
-
-namespace blink {
-
-void AnimatedStyleBuilder::ApplyProperty(CSSPropertyID property,
-                                         ComputedStyle& style,
-                                         const AnimatableValue* value) {
-#if DCHECK_IS_ON()
-  DCHECK(CSSProperty::Get(property).IsInterpolable());
-#endif
-  switch (property) {
-    case CSSPropertyID::kOpacity:
-      // Avoiding a value of 1 forces a layer to be created.
-      style.SetOpacity(clampTo<float>(ToAnimatableDouble(value)->ToDouble(), 0,
-                                      nextafterf(1, 0)));
-      return;
-    case CSSPropertyID::kTransform: {
-      const TransformOperations& operations =
-          ToAnimatableTransform(value)->GetTransformOperations();
-      // FIXME: This normalization (handling of 'none') should be performed at
-      // input in AnimatableValueFactory.
-      if (operations.size() == 0) {
-        style.SetTransform(TransformOperations(true));
-        return;
-      }
-      double source_zoom = ToAnimatableTransform(value)->Zoom();
-      double destination_zoom = style.EffectiveZoom();
-      style.SetTransform(source_zoom == destination_zoom
-                             ? operations
-                             : operations.Zoom(destination_zoom / source_zoom));
-      return;
-    }
-    case CSSPropertyID::kFilter:
-      style.SetFilter(ToAnimatableFilterOperations(value)->Operations());
-      return;
-
-    default:
-      NOTREACHED();
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/animated_style_builder.h b/third_party/blink/renderer/core/css/resolver/animated_style_builder.h
deleted file mode 100644
index 196c1b6..0000000
--- a/third_party/blink/renderer/core/css/resolver/animated_style_builder.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ANIMATED_STYLE_BUILDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ANIMATED_STYLE_BUILDER_H_
-
-#include "third_party/blink/renderer/core/css/css_property_names.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class AnimatableValue;
-class ComputedStyle;
-
-class AnimatedStyleBuilder {
-  STATIC_ONLY(AnimatedStyleBuilder);
-
- public:
-  static void ApplyProperty(CSSPropertyID,
-                            ComputedStyle&,
-                            const AnimatableValue*);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_ANIMATED_STYLE_BUILDER_H_
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 1d839914..37d81a9b 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -62,7 +62,6 @@
 #include "third_party/blink/renderer/core/css/part_names.h"
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
 #include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
-#include "third_party/blink/renderer/core/css/resolver/animated_style_builder.h"
 #include "third_party/blink/renderer/core/css/resolver/css_variable_animator.h"
 #include "third_party/blink/renderer/core/css/resolver/css_variable_resolver.h"
 #include "third_party/blink/renderer/core/css/resolver/match_result.h"
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index 143962ec..5554a9b 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -357,6 +357,8 @@
   void Trace(blink::Visitor*) override;
   const char* NameInHeapSnapshot() const override { return "StyleEngine"; }
 
+  bool InDomRemoval() const { return in_dom_removal_; }
+
  private:
   // FontSelectorClient implementation.
   void FontsNeedUpdate(FontSelector*) override;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 02ecb3e..3786273 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1891,4 +1891,39 @@
   }
 }
 
+// Via HTMLFormControlElement, it's possible to enter
+// Node::MarkAncestorsWithChildNeedsStyleRecalc for nodes which have
+// isConnected==true, but an ancestor with isConnected==false. This is because
+// we mark the ancestor chain for style recalc via HTMLFormElement::
+// InvalidateDefaultButtonStyle while the subtree disconnection
+// is taking place.
+TEST_F(StyleEngineTest, NoCrashWhenMarkingPartiallyRemovedSubtree) {
+  GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+    <style>
+      #foo:default {} /* Needed to enter Element::PseudoStateChanged */
+    </style>
+    <form id="form">
+      <div id="outer">
+        <button>
+        <div id="inner"></div>
+      </div>
+    </form>
+  )HTML");
+  UpdateAllLifecyclePhases();
+
+  Element* form = GetDocument().getElementById("form");
+  Element* outer = GetDocument().getElementById("outer");
+  Element* inner = GetDocument().getElementById("inner");
+  ASSERT_TRUE(form);
+  ASSERT_TRUE(outer);
+  ASSERT_TRUE(inner);
+
+  // Add some more buttons, to give InvalidateDefaultButtonStyle
+  // something to do when the original <button> is removed.
+  inner->SetInnerHTMLFromString("<button><button>");
+  UpdateAllLifecyclePhases();
+
+  form->removeChild(outer);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_traversal_root.cc b/third_party/blink/renderer/core/css/style_traversal_root.cc
index e26118ec..0347c82 100644
--- a/third_party/blink/renderer/core/css/style_traversal_root.cc
+++ b/third_party/blink/renderer/core/css/style_traversal_root.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/core/css/style_traversal_root.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/node_traversal.h"
 
 namespace blink {
 
@@ -21,7 +23,19 @@
     return;
   }
 
-  DCHECK(root_node_);
+  if (!root_node_) {
+    // When removing elements in a <form> subtree, we can reach this
+    // point without a root node, because we can synchronously mark
+    // nodes for recalc in a partially disconnected tree via
+    // HTMLFormElement::InvalidateDefaultButtonStyle. These DCHECKs
+    // are in place to prevent this unfortunate situation in other
+    // circumstances.
+#if DCHECK_IS_ON()
+    DCHECK(!IsConnectedToDocument(*dirty_node));
+    DCHECK(dirty_node->GetDocument().GetStyleEngine().InDomRemoval());
+#endif  // DCHECK_IS_ON()
+    return;
+  }
 #if DCHECK_IS_ON()
   DCHECK(Parent(*dirty_node));
   DCHECK(!IsDirty(*Parent(*dirty_node)));
@@ -54,4 +68,16 @@
   Clear();
 }
 
+#if DCHECK_IS_ON()
+bool StyleTraversalRoot::IsConnectedToDocument(Node& node) const {
+  if (node.IsDocumentNode())
+    return true;
+  for (Node& parent : NodeTraversal::AncestorsOf(node)) {
+    if (parent.IsDocumentNode())
+      return true;
+  }
+  return false;
+}
+#endif  // DCHECK_IS_ON()
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_traversal_root.h b/third_party/blink/renderer/core/css/style_traversal_root.h
index 2b46beb..3f83e14 100644
--- a/third_party/blink/renderer/core/css/style_traversal_root.h
+++ b/third_party/blink/renderer/core/css/style_traversal_root.h
@@ -71,6 +71,10 @@
  private:
   friend class StyleTraversalRootTestImpl;
 
+#if DCHECK_IS_ON()
+  bool IsConnectedToDocument(Node&) const;
+#endif  // DCHECK_IS_ON()
+
   // The current root for dirty nodes.
   Member<Node> root_node_;
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index d9e7436..03d86ba6 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -164,9 +164,9 @@
     if (!parsed_size) {
       return GetRejectedPromise(script_state, rejection_names::kInvalidOptions);
     }
-    locked_frame_rect_ = LayoutRect(LayoutPoint(), *parsed_size);
+    locked_content_logical_size_ = *parsed_size;
   } else {
-    locked_frame_rect_ = LayoutRect();
+    locked_content_logical_size_ = LayoutSize();
   }
 
   // We always reschedule a timeout task even if we're not starting a new
@@ -182,6 +182,13 @@
   if (IsLocked())
     return GetResolvedPromise(script_state);
 
+  // We might be committing (which means we're already unlocked for the purposes
+  // of the above check. We resolve the commit, since rejecting it seems wrong.
+  // TODO(vmpstr): We could also reject this, but then script would have no way
+  // to avoid this rejection (since at the time acquire is called, locked
+  // property is false).
+  FinishCommitResolver(kResolve);
+
   update_budget_.reset();
 
   // If we're already connected then we need to ensure that we update our layout
@@ -200,8 +207,11 @@
 
     acquire_resolver_ =
         MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+    is_horizontal_writing_mode_ = true;
     if (auto* layout_object = element_->GetLayoutObject()) {
-      layout_object->SetNeedsLayout(layout_invalidation_reason::kDisplayLock);
+      layout_object->SetNeedsLayoutAndPrefWidthsRecalc(
+          layout_invalidation_reason::kDisplayLock);
+      is_horizontal_writing_mode_ = layout_object->IsHorizontalWritingMode();
     }
     MarkPaintLayerNeedsRepaint();
     ScheduleAnimation();
@@ -247,7 +257,11 @@
   // If we're already committing and it's not because of activation,
   // we would already have the commit promise and should just return it.
   if (commit_resolver_) {
-    DCHECK(state_ == kUpdating || state_ == kCommitting);
+    // When we perform an updateAndCommit(), we schedule a StartCommit() via a
+    // task. While that task is in flight, our state could still be locked. It,
+    // of course, can also be updating or committing if that's what we are
+    // currently doing. So the only state we can't be in is kUnlocked.
+    DCHECK(state_ != kUnlocked);
     return commit_resolver_->Promise();
   }
 
@@ -275,9 +289,8 @@
   // If we're in a state where a co-operative update doesn't make sense (e.g. we
   // haven't acquired the lock, or we're already sync committing), then do
   // whatever commit() would do.
-  if (state_ == kCommitting || !ConnectedToView()) {
+  if (state_ == kCommitting || !ConnectedToView())
     return commit(script_state);
-  }
 
   // If we have a commit resolver already, return it.
   if (commit_resolver_) {
@@ -364,6 +377,9 @@
 
     if (blocked_style_traversal_type_ == kStyleUpdateSelf)
       blocked_style_traversal_type_ = kStyleUpdateNotRequired;
+    auto* layout_object = element_->GetLayoutObject();
+    is_horizontal_writing_mode_ =
+        !layout_object || layout_object->IsHorizontalWritingMode();
     return;
   }
 
@@ -378,13 +394,16 @@
     update_budget_->DidPerformPhase(DisplayLockBudget::Phase::kStyle);
 }
 
-bool DisplayLockContext::ShouldLayout() const {
-  return update_forced_ || state_ > kUpdating ||
+bool DisplayLockContext::ShouldLayout(LifecycleTarget target) const {
+  return target == kSelf || update_forced_ || state_ > kUpdating ||
          (state_ == kUpdating && update_budget_->ShouldPerformPhase(
                                      DisplayLockBudget::Phase::kLayout));
 }
 
-void DisplayLockContext::DidLayout() {
+void DisplayLockContext::DidLayout(LifecycleTarget target) {
+  if (target == kSelf)
+    return;
+
   if (state_ == kUpdating)
     update_budget_->DidPerformPhase(DisplayLockBudget::Phase::kLayout);
 }
@@ -448,23 +467,9 @@
     FinishCommitResolver(kReject, rejection_names::kContainmentNotSatisfied);
     state_ = should_stay_locked ? kLocked : kUnlocked;
   }
-}
 
-DisplayLockContext::ScopedPendingFrameRect
-DisplayLockContext::GetScopedPendingFrameRect() {
-  if (state_ >= kCommitting)
-    return ScopedPendingFrameRect(nullptr);
-
-  DCHECK(element_->GetLayoutObject() && element_->GetLayoutBox());
-  element_->GetLayoutBox()->SetFrameRectForDisplayLock(pending_frame_rect_);
-  return ScopedPendingFrameRect(this);
-}
-
-void DisplayLockContext::NotifyPendingFrameRectScopeEnded() {
-  DCHECK(element_->GetLayoutObject() && element_->GetLayoutBox());
-  DCHECK(locked_frame_rect_);
-  pending_frame_rect_ = element_->GetLayoutBox()->FrameRect();
-  element_->GetLayoutBox()->SetFrameRectForDisplayLock(*locked_frame_rect_);
+  if (auto* layout_object = element_->GetLayoutObject())
+    is_horizontal_writing_mode_ = layout_object->IsHorizontalWritingMode();
 }
 
 DisplayLockContext::ScopedForcedUpdate
@@ -537,20 +542,8 @@
   MarkAncestorsForPrePaintIfNeeded();
   MarkPaintLayerNeedsRepaint();
 
-  // We also need to commit the pending frame rect at this point.
-  bool frame_rect_changed =
-      ToLayoutBox(layout_object)->FrameRect() != pending_frame_rect_;
-
-  // If the frame rect hasn't actually changed then we don't need to do
-  // anything. Other than wait for commit to happen
-  if (!frame_rect_changed)
-    return;
-
-  // Set the pending frame rect as the new one, and ensure to schedule a layout
-  // for just the box itself. Note that we use the non-display locked version to
-  // ensure all the hooks are property invoked.
-  ToLayoutBox(layout_object)->SetFrameRect(pending_frame_rect_);
-  layout_object->SetNeedsLayout(layout_invalidation_reason::kDisplayLock);
+  layout_object->SetNeedsLayoutAndPrefWidthsRecalc(
+      layout_invalidation_reason::kDisplayLock);
 }
 
 void DisplayLockContext::StartUpdateIfNeeded() {
@@ -723,7 +716,7 @@
     FinishAcquireResolver(kResolve);
     // TODO(vmpstr): When size: auto is supported, we need to get the size from
     // the layout object here.
-    DCHECK(locked_frame_rect_);
+    DCHECK(locked_content_logical_size_);
     // Fallthrough here in case we're already updating.
   }
 
@@ -789,9 +782,8 @@
   // locked, but it's important to update IsSelfCollapsingBlock property on
   // the parent so that it's up to date. This property is updated during
   // layout.
-  if (auto* parent = element_->GetLayoutObject()->Parent()) {
+  if (auto* parent = element_->GetLayoutObject()->Parent())
     parent->SetNeedsLayout(layout_invalidation_reason::kDisplayLock);
-  }
 }
 
 void DisplayLockContext::ScheduleAnimation() {
@@ -864,21 +856,6 @@
 // Scoped objects implementation
 // -----------------------------------------------
 
-DisplayLockContext::ScopedPendingFrameRect::ScopedPendingFrameRect(
-    DisplayLockContext* context)
-    : context_(context) {}
-
-DisplayLockContext::ScopedPendingFrameRect::ScopedPendingFrameRect(
-    ScopedPendingFrameRect&& other)
-    : context_(other.context_) {
-  other.context_ = nullptr;
-}
-
-DisplayLockContext::ScopedPendingFrameRect::~ScopedPendingFrameRect() {
-  if (context_)
-    context_->NotifyPendingFrameRectScopeEnded();
-}
-
 DisplayLockContext::ScopedForcedUpdate::ScopedForcedUpdate(
     DisplayLockContext* context)
     : context_(context) {}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index 8d95e8a7..30e996a 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -67,22 +67,6 @@
     kStyleUpdateDescendants
   };
 
-  // See GetScopedPendingFrameRect() for description.
-  class ScopedPendingFrameRect {
-    STACK_ALLOCATED();
-
-   public:
-    ScopedPendingFrameRect(ScopedPendingFrameRect&&);
-    ~ScopedPendingFrameRect();
-
-   private:
-    friend class DisplayLockContext;
-
-    ScopedPendingFrameRect(DisplayLockContext*);
-
-    UntracedMember<DisplayLockContext> context_ = nullptr;
-  };
-
   // See GetScopedForcedUpdate() for description.
   class CORE_EXPORT ScopedForcedUpdate {
     DISALLOW_NEW();
@@ -124,8 +108,8 @@
   // Lifecycle observation / state functions.
   bool ShouldStyle(LifecycleTarget) const;
   void DidStyle(LifecycleTarget);
-  bool ShouldLayout() const;
-  void DidLayout();
+  bool ShouldLayout(LifecycleTarget) const;
+  void DidLayout(LifecycleTarget);
   bool ShouldPrePaint() const;
   void DidPrePaint();
   bool ShouldPaint() const;
@@ -142,20 +126,13 @@
   bool ShouldCommitForActivation() const;
 
   // Returns true if this lock is locked. Note from the outside perspective, the
-  // lock is locked any time the state is not kUnlocked.
-  bool IsLocked() const { return state_ != kUnlocked; }
+  // lock is locked any time the state is not kUnlocked or kCommitting.
+  bool IsLocked() const { return state_ != kUnlocked && state_ != kCommitting; }
 
   // Called when the layout tree is attached. This is used to verify
   // containment.
   void DidAttachLayoutTree();
 
-  // Returns a ScopedPendingFrameRect object which exposes the pending layout
-  // frame rect to LayoutBox. This is used to ensure that children of the locked
-  // element use the pending layout frame to update the size of the element.
-  // After the scoped object is destroyed, the previous frame rect is restored
-  // and the pending one is stored in the context until it is needed.
-  ScopedPendingFrameRect GetScopedPendingFrameRect();
-
   // Returns a ScopedForcedUpdate object which for the duration of its lifetime
   // will allow updates to happen on this element's subtree. For the element
   // itself, the frame rect will still be the same as at the time the lock was
@@ -191,9 +168,13 @@
     needs_prepaint_subtree_walk_ = true;
   }
 
-  const LayoutRect& GetLockedFrameRect() const {
-    DCHECK(locked_frame_rect_);
-    return *locked_frame_rect_;
+  LayoutUnit GetLockedContentLogicalWidth() const {
+    return is_horizontal_writing_mode_ ? locked_content_logical_size_->Width()
+                                       : locked_content_logical_size_->Height();
+  }
+  LayoutUnit GetLockedContentLogicalHeight() const {
+    return is_horizontal_writing_mode_ ? locked_content_logical_size_->Height()
+                                       : locked_content_logical_size_->Width();
   }
 
  private:
@@ -240,10 +221,6 @@
   bool IsElementDirtyForLayout() const;
   bool IsElementDirtyForPrePaint() const;
 
-  // When ScopedPendingFrameRect is destroyed, it calls this function. See
-  // GetScopedPendingFrameRect() for more information.
-  void NotifyPendingFrameRectScopeEnded();
-
   // When ScopedForcedUpdate is destroyed, it calls this function. See
   // GetScopedForcedUpdate() for more information.
   void NotifyForcedUpdateScopeEnded();
@@ -306,8 +283,7 @@
   HeapHashSet<Member<Element>> whitespace_reattach_set_;
 
   StateChangeHelper state_;
-  LayoutRect pending_frame_rect_;
-  base::Optional<LayoutRect> locked_frame_rect_;
+  base::Optional<LayoutSize> locked_content_logical_size_;
 
   bool update_forced_ = false;
   bool activatable_ = false;
@@ -317,6 +293,7 @@
 
   bool needs_effective_allowed_touch_action_update_ = false;
   bool needs_prepaint_subtree_walk_ = false;
+  bool is_horizontal_writing_mode_ = true;
 
   TaskHandle timeout_task_handle_;
 };
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index 14cb849..1138e9e7 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -162,7 +162,8 @@
       element->GetDisplayLockContext()->ShouldStyle(DisplayLockContext::kSelf));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
 
@@ -276,7 +277,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
@@ -295,7 +297,8 @@
 
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldPaint());
 
   UpdateAllLifecyclePhasesForTest();
@@ -355,7 +358,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
@@ -378,7 +382,8 @@
 
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldPaint());
 
   UpdateAllLifecyclePhasesForTest();
@@ -445,7 +450,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
@@ -741,7 +747,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
@@ -838,7 +845,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
@@ -862,7 +870,8 @@
 
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_TRUE(element->GetDisplayLockContext()->ShouldPaint());
 
   UpdateAllLifecyclePhasesForTest();
@@ -928,11 +937,11 @@
     container->getDisplayLockForBindings()->commit(script_state);
   }
 
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
+  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
+  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
   EXPECT_FALSE(host->DisplayLockPreventsActivation());
-  EXPECT_TRUE(container->DisplayLockPreventsActivation());
-  EXPECT_TRUE(slotted->DisplayLockPreventsActivation());
+  EXPECT_FALSE(container->DisplayLockPreventsActivation());
+  EXPECT_FALSE(slotted->DisplayLockPreventsActivation());
 
   UpdateAllLifecyclePhasesForTest();
 
@@ -979,7 +988,8 @@
   // Sanity checks to ensure the element is locked.
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
       DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
+  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout(
+      DisplayLockContext::kChildren));
   EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
diff --git a/third_party/blink/renderer/core/events/portal_activate_event.cc b/third_party/blink/renderer/core/events/portal_activate_event.cc
index ad1d0b3..d766640 100644
--- a/third_party/blink/renderer/core/events/portal_activate_event.cc
+++ b/third_party/blink/renderer/core/events/portal_activate_event.cc
@@ -22,12 +22,15 @@
     LocalFrame* frame,
     const base::UnguessableToken& predecessor_portal_token,
     mojom::blink::PortalAssociatedPtr predecessor_portal_ptr,
+    mojom::blink::PortalClientAssociatedRequest
+        predecessor_portal_client_request,
     scoped_refptr<SerializedScriptValue> data,
     MessagePortArray* ports,
     OnPortalActivatedCallback callback) {
   return MakeGarbageCollected<PortalActivateEvent>(
       frame->GetDocument(), predecessor_portal_token,
       std::move(predecessor_portal_ptr),
+      std::move(predecessor_portal_client_request),
       SerializedScriptValue::Unpack(std::move(data)), ports,
       std::move(callback));
 }
@@ -42,6 +45,8 @@
     Document* document,
     const base::UnguessableToken& predecessor_portal_token,
     mojom::blink::PortalAssociatedPtr predecessor_portal_ptr,
+    mojom::blink::PortalClientAssociatedRequest
+        predecessor_portal_client_request,
     UnpackedSerializedScriptValue* data,
     MessagePortArray* ports,
     OnPortalActivatedCallback callback)
@@ -52,6 +57,8 @@
       document_(document),
       predecessor_portal_token_(predecessor_portal_token),
       predecessor_portal_ptr_(std::move(predecessor_portal_ptr)),
+      predecessor_portal_client_request_(
+          std::move(predecessor_portal_client_request)),
       data_(data),
       ports_(ports),
       on_portal_activated_callback_(std::move(callback)) {}
@@ -122,8 +129,8 @@
   }
 
   HTMLPortalElement* portal = MakeGarbageCollected<HTMLPortalElement>(
-      *document_, predecessor_portal_token_,
-      std::move(predecessor_portal_ptr_));
+      *document_, predecessor_portal_token_, std::move(predecessor_portal_ptr_),
+      std::move(predecessor_portal_client_request_));
   std::move(on_portal_activated_callback_).Run(true);
   return portal;
 }
diff --git a/third_party/blink/renderer/core/events/portal_activate_event.h b/third_party/blink/renderer/core/events/portal_activate_event.h
index 5a53b69..60afce12 100644
--- a/third_party/blink/renderer/core/events/portal_activate_event.h
+++ b/third_party/blink/renderer/core/events/portal_activate_event.h
@@ -37,6 +37,8 @@
       LocalFrame* frame,
       const base::UnguessableToken& predecessor_portal_token,
       mojom::blink::PortalAssociatedPtr predecessor_portal_ptr,
+      mojom::blink::PortalClientAssociatedRequest
+          predecessor_portal_client_request,
       scoped_refptr<SerializedScriptValue> data,
       MessagePortArray* ports,
       OnPortalActivatedCallback callback);
@@ -48,6 +50,8 @@
   PortalActivateEvent(Document* document,
                       const base::UnguessableToken& predecessor_portal_token,
                       mojom::blink::PortalAssociatedPtr predecessor_portal_ptr,
+                      mojom::blink::PortalClientAssociatedRequest
+                          predecessor_portal_client_request,
                       UnpackedSerializedScriptValue* data,
                       MessagePortArray*,
                       OnPortalActivatedCallback callback);
@@ -70,6 +74,8 @@
   Member<Document> document_;
   base::UnguessableToken predecessor_portal_token_;
   mojom::blink::PortalAssociatedPtr predecessor_portal_ptr_;
+  mojom::blink::PortalClientAssociatedRequest
+      predecessor_portal_client_request_;
 
   // Set if this came from a serialized value.
   Member<UnpackedSerializedScriptValue> data_;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index ae5eed7..e5a29c2 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -845,8 +845,10 @@
 std::pair<RemoteFrame*, base::UnguessableToken>
 LocalFrameClientImpl::CreatePortal(
     HTMLPortalElement* portal,
-    mojom::blink::PortalAssociatedRequest request) {
-  return web_frame_->CreatePortal(portal, std::move(request));
+    mojom::blink::PortalAssociatedRequest request,
+    mojom::blink::PortalClientAssociatedPtrInfo client) {
+  return web_frame_->CreatePortal(portal, std::move(request),
+                                  std::move(client));
 }
 
 RemoteFrame* LocalFrameClientImpl::AdoptPortal(HTMLPortalElement* portal) {
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index fc14e2e..018ca7c 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -182,7 +182,8 @@
                           HTMLFrameOwnerElement*) override;
   std::pair<RemoteFrame*, base::UnguessableToken> CreatePortal(
       HTMLPortalElement*,
-      mojom::blink::PortalAssociatedRequest) override;
+      mojom::blink::PortalAssociatedRequest,
+      mojom::blink::PortalClientAssociatedPtrInfo) override;
   RemoteFrame* AdoptPortal(HTMLPortalElement*) override;
   WebPluginContainerImpl* CreatePlugin(HTMLPlugInElement&,
                                        const KURL&,
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 123f8cb..1e61fa7 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -291,7 +291,8 @@
   // identifies the portal.
   virtual std::pair<RemoteFrame*, base::UnguessableToken> CreatePortal(
       HTMLPortalElement*,
-      mojom::blink::PortalAssociatedRequest) = 0;
+      mojom::blink::PortalAssociatedRequest,
+      mojom::blink::PortalClientAssociatedPtrInfo) = 0;
 
   // Adopts the predecessor |portal|. The HTMLPortalElement must have been
   // created by adopting the predecessor in the PortalActivateEvent, and have a
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 412e755..1a1fc054 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -211,6 +211,7 @@
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 #include "third_party/blink/renderer/core/html/plugin_document.h"
 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
+#include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
 #include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
 #include "third_party/blink/renderer/core/html/portal/portal_host.h"
 #include "third_party/blink/renderer/core/html_names.h"
@@ -1834,8 +1835,9 @@
 
 std::pair<RemoteFrame*, base::UnguessableToken> WebLocalFrameImpl::CreatePortal(
     HTMLPortalElement* portal,
-    mojom::blink::PortalAssociatedRequest request) {
-  auto pair = client_->CreatePortal(request.PassHandle());
+    mojom::blink::PortalAssociatedRequest request,
+    mojom::blink::PortalClientAssociatedPtrInfo client) {
+  auto pair = client_->CreatePortal(request.PassHandle(), client.PassHandle());
   WebRemoteFrameImpl* portal_frame = ToWebRemoteFrameImpl(pair.first);
   portal_frame->InitializeCoreFrame(*GetFrame()->GetPage(), portal,
                                     g_null_atom);
@@ -2582,12 +2584,14 @@
 void WebLocalFrameImpl::OnPortalActivated(
     const base::UnguessableToken& portal_token,
     mojo::ScopedInterfaceEndpointHandle portal_pipe,
+    mojo::ScopedInterfaceEndpointHandle portal_client_pipe,
     TransferableMessage data,
     OnPortalActivatedCallback callback) {
-  GetFrame()->GetPage()->SetInsidePortal(false);
-
   LocalDOMWindow* window = GetFrame()->DomWindow();
 
+  DOMWindowPortalHost::portalHost(*window)->OnPortalActivated();
+  GetFrame()->GetPage()->SetInsidePortal(false);
+
   auto blink_data = ToBlinkTransferableMessage(std::move(data));
   DCHECK(!blink_data.locked_agent_cluster_id)
       << "portal activation is always cross-agent-cluster and should be "
@@ -2599,6 +2603,8 @@
       frame_.Get(), portal_token,
       mojom::blink::PortalAssociatedPtr(mojom::blink::PortalAssociatedPtrInfo(
           std::move(portal_pipe), mojom::blink::Portal::Version_)),
+      mojom::blink::PortalClientAssociatedRequest(
+          std::move(portal_client_pipe)),
       std::move(blink_data.message), ports, std::move(callback));
 
   ThreadDebugger* debugger = MainThreadDebugger::Instance();
@@ -2610,7 +2616,7 @@
   event->DetachPortalIfNotAdopted();
 }
 
-void WebLocalFrameImpl::ForwardMessageToPortalHost(
+void WebLocalFrameImpl::ForwardMessageFromHost(
     TransferableMessage message,
     const WebSecurityOrigin& source_origin,
     const base::Optional<WebSecurityOrigin>& target_origin) {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index c6d881e..f788435 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -306,9 +306,10 @@
                                 const WebMediaPlayerAction&) override;
   void OnPortalActivated(const base::UnguessableToken& portal_token,
                          mojo::ScopedInterfaceEndpointHandle portal_pipe,
+                         mojo::ScopedInterfaceEndpointHandle portal_client_pipe,
                          TransferableMessage data,
                          OnPortalActivatedCallback callback) override;
-  void ForwardMessageToPortalHost(
+  void ForwardMessageFromHost(
       TransferableMessage message,
       const WebSecurityOrigin& source_origin,
       const base::Optional<WebSecurityOrigin>& target_origin) override;
@@ -379,7 +380,8 @@
                                HTMLFrameOwnerElement*);
   std::pair<RemoteFrame*, base::UnguessableToken> CreatePortal(
       HTMLPortalElement*,
-      mojom::blink::PortalAssociatedRequest);
+      mojom::blink::PortalAssociatedRequest,
+      mojom::blink::PortalClientAssociatedPtrInfo);
   RemoteFrame* AdoptPortal(HTMLPortalElement*);
 
   void DidChangeContentsSize(const IntSize&);
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index b2024905..e1a7c93f 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -34,7 +34,7 @@
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap_options.h"
 #include "third_party/blink/renderer/platform/graphics/color_behavior.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 #include "v8/include/v8.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/canvas/image_data_test.cc b/third_party/blink/renderer/core/html/canvas/image_data_test.cc
index ec976c7..2bec5d0 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data_test.cc
@@ -8,7 +8,7 @@
 #include "third_party/blink/renderer/platform/geometry/int_size.h"
 #include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/blink/renderer/core/html/html_embed_element.cc b/third_party/blink/renderer/core/html/html_embed_element.cc
index 3b65677..e186d4e9 100644
--- a/third_party/blink/renderer/core/html/html_embed_element.cc
+++ b/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -106,6 +106,10 @@
 
 void HTMLEmbedElement::ParseAttribute(
     const AttributeModificationParams& params) {
+  // Changing an attribute may change the content, type of content, layout
+  // object type, or all of the above. Not safe to re-use through reattach.
+  SetDisposeView();
+
   if (params.name == kTypeAttr) {
     SetServiceType(params.new_value.LowerASCII());
     wtf_size_t pos = service_type_.Find(";");
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc
index d09d26c34..011671b 100644
--- a/third_party/blink/renderer/core/html/html_plugin_element.cc
+++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -354,7 +354,7 @@
   // since there's no telling what's going to happen next, and it wouldn't be
   // safe to keep it.
   if (!context.performing_reattach)
-    dispose_view_ = true;
+    SetDisposeView();
 
   ResetInstance();
 
@@ -756,7 +756,7 @@
   SetForceReattachLayoutTree();
 
   // Make sure that we don't attempt to re-use the view through re-attachment.
-  dispose_view_ = true;
+  SetDisposeView();
 }
 
 void HTMLPlugInElement::UpdateServiceTypeIfEmpty() {
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.h b/third_party/blink/renderer/core/html/html_plugin_element.h
index 8eb47b5..47f9874 100644
--- a/third_party/blink/renderer/core/html/html_plugin_element.h
+++ b/third_party/blink/renderer/core/html/html_plugin_element.h
@@ -146,6 +146,10 @@
     UpdateServiceTypeIfEmpty();
   }
 
+  // Set when the current view cannot be re-used on reattach. This is the case
+  // e.g. when attributes (e.g. src) change.
+  void SetDisposeView() { dispose_view_ = true; }
+
   String service_type_;
   String url_;
   KURL loaded_url_;
diff --git a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc
index b86b3154..9b449d37 100644
--- a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc
+++ b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.cc
@@ -13,12 +13,17 @@
 
 // static
 PortalHost* DOMWindowPortalHost::portalHost(LocalDOMWindow& window) {
+  if (ShouldExposePortalHost(window))
+    return &PortalHost::From(window);
+  return nullptr;
+}
+
+// static
+bool DOMWindowPortalHost::ShouldExposePortalHost(const LocalDOMWindow& window) {
   // The portal host is only exposed in the main frame of a page
   // embedded in a portal.
-  if (!window.GetFrame() || !window.GetFrame()->IsMainFrame() ||
-      !window.GetFrame()->GetPage()->InsidePortal())
-    return nullptr;
-  return &PortalHost::From(window);
+  return window.GetFrame() && window.GetFrame()->IsMainFrame() &&
+         window.GetFrame()->GetPage()->InsidePortal();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h
index 96e0154..87794ad6 100644
--- a/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h
+++ b/third_party/blink/renderer/core/html/portal/dom_window_portal_host.h
@@ -15,6 +15,7 @@
 class CORE_EXPORT DOMWindowPortalHost {
  public:
   static PortalHost* portalHost(LocalDOMWindow& window);
+  static bool ShouldExposePortalHost(const LocalDOMWindow& window);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
index 9424c06..e4602b3 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -32,6 +33,7 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
@@ -39,10 +41,12 @@
 HTMLPortalElement::HTMLPortalElement(
     Document& document,
     const base::UnguessableToken& portal_token,
-    mojom::blink::PortalAssociatedPtr portal_ptr)
+    mojom::blink::PortalAssociatedPtr portal_ptr,
+    mojom::blink::PortalClientAssociatedRequest portal_client_request)
     : HTMLFrameOwnerElement(html_names::kPortalTag, document),
       portal_token_(portal_token),
-      portal_ptr_(std::move(portal_ptr)) {}
+      portal_ptr_(std::move(portal_ptr)),
+      portal_client_binding_(this, std::move(portal_client_request)) {}
 
 HTMLPortalElement::~HTMLPortalElement() {}
 
@@ -71,6 +75,7 @@
     portal_token_ = base::UnguessableToken();
   }
   portal_ptr_.reset();
+  portal_client_binding_.Close();
 }
 
 namespace {
@@ -267,7 +272,25 @@
   if (exception_state.HadException())
     return;
 
-  portal_ptr_->PostMessage(std::move(transferable_message), target_origin);
+  portal_ptr_->PostMessageToGuest(std::move(transferable_message),
+                                  target_origin);
+}
+
+void HTMLPortalElement::ForwardMessageFromGuest(
+    const String& message,
+    const scoped_refptr<const SecurityOrigin>& source_origin,
+    const scoped_refptr<const SecurityOrigin>& target_origin) {
+  if (!portal_ptr_)
+    return;
+
+  if (target_origin && !target_origin->IsSameSchemeHostPort(
+                           GetExecutionContext()->GetSecurityOrigin())) {
+    return;
+  }
+
+  MessageEvent* event =
+      MessageEvent::Create(message, source_origin->ToString());
+  DispatchEvent(*event);
 }
 
 HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto(
@@ -295,9 +318,11 @@
         WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
     DocumentPortals::From(GetDocument()).OnPortalInserted(this);
   } else {
+    mojom::blink::PortalClientAssociatedPtr client;
+    portal_client_binding_.Bind(mojo::MakeRequest(&client));
     std::tie(portal_frame_, portal_token_) =
         GetDocument().GetFrame()->Client()->CreatePortal(
-            this, mojo::MakeRequest(&portal_ptr_));
+            this, mojo::MakeRequest(&portal_ptr_), client.PassInterface());
     portal_ptr_.set_connection_error_handler(
         WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
     DocumentPortals::From(GetDocument()).OnPortalInserted(this);
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h
index 331fd841..fc12c5ae 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.h
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_
 
 #include "base/unguessable_token.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -24,7 +25,8 @@
 // activated using script. The portal element is still under development and not
 // part of the HTML standard. It can be enabled by passing
 // --enable-features=Portals. See also https://github.com/WICG/portals.
-class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement {
+class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement,
+                                      public mojom::blink::PortalClient {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -33,7 +35,9 @@
   explicit HTMLPortalElement(
       Document& document,
       const base::UnguessableToken& portal_token = base::UnguessableToken(),
-      mojom::blink::PortalAssociatedPtr portal_ptr = nullptr);
+      mojom::blink::PortalAssociatedPtr portal_ptr = nullptr,
+      mojom::blink::PortalClientAssociatedRequest portal_client_request =
+          nullptr);
   ~HTMLPortalElement() override;
 
   // ScriptWrappable overrides.
@@ -51,6 +55,12 @@
                    const WindowPostMessageOptions* options,
                    ExceptionState& exception_state);
 
+  // blink::mojom::PortalClient implementation
+  void ForwardMessageFromGuest(
+      const String& message,
+      const scoped_refptr<const SecurityOrigin>& source_origin,
+      const scoped_refptr<const SecurityOrigin>& target_origin) override;
+
   const base::UnguessableToken& GetToken() const { return portal_token_; }
 
   FrameOwnerElementType OwnerType() const override {
@@ -94,6 +104,7 @@
   bool is_activating_ = false;
 
   mojom::blink::PortalAssociatedPtr portal_ptr_;
+  mojo::AssociatedBinding<mojom::blink::PortalClient> portal_client_binding_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.cc b/third_party/blink/renderer/core/html/portal/portal_host.cc
index 1dc6169..ac97354 100644
--- a/third_party/blink/renderer/core/html/portal/portal_host.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_host.cc
@@ -4,11 +4,17 @@
 
 #include "third_party/blink/renderer/core/html/portal/portal_host.h"
 
+#include <utility>
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/user_activation.h"
+#include "third_party/blink/renderer/core/frame/window_post_message_options.h"
+#include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
 #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -49,6 +55,44 @@
   return this;
 }
 
+Document* PortalHost::GetDocument() const {
+  return To<Document>(GetExecutionContext());
+}
+
+void PortalHost::OnPortalActivated() {
+  portal_host_ptr_.reset();
+}
+
+void PortalHost::postMessage(const String& message,
+                             const String& target_origin,
+                             Vector<ScriptValue>& transfer,
+                             ExceptionState& exception_state) {
+  WindowPostMessageOptions* options = WindowPostMessageOptions::Create();
+  options->setTargetOrigin(target_origin);
+  if (!transfer.IsEmpty())
+    options->setTransfer(transfer);
+  postMessage(message, options, exception_state);
+}
+
+void PortalHost::postMessage(const String& message,
+                             const WindowPostMessageOptions* options,
+                             ExceptionState& exception_state) {
+  if (!DOMWindowPortalHost::ShouldExposePortalHost(*GetSupplementable())) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kInvalidStateError,
+        "The document is no longer inside a portal");
+    return;
+  }
+
+  scoped_refptr<const SecurityOrigin> target_origin;
+  if (options->targetOrigin() == "/")
+    target_origin = GetDocument()->GetSecurityOrigin();
+  else if (options->targetOrigin() != "*")
+    target_origin = SecurityOrigin::CreateFromString(options->targetOrigin());
+
+  GetPortalHostInterface().PostMessageToHost(message, target_origin);
+}
+
 void PortalHost::ReceiveMessage(
     BlinkTransferableMessage message,
     scoped_refptr<const SecurityOrigin> source_origin,
@@ -79,4 +123,15 @@
     debugger->ExternalAsyncTaskFinished(message.sender_stack_trace_id);
 }
 
+mojom::blink::PortalHost& PortalHost::GetPortalHostInterface() {
+  if (!portal_host_ptr_) {
+    DCHECK(GetDocument()->GetFrame());
+    GetDocument()
+        ->GetFrame()
+        ->GetRemoteNavigationAssociatedInterfaces()
+        ->GetInterface(&portal_host_ptr_);
+  }
+  return *portal_host_ptr_;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.h b/third_party/blink/renderer/core/html/portal/portal_host.h
index 1ba227f..aa11630 100644
--- a/third_party/blink/renderer/core/html/portal/portal_host.h
+++ b/third_party/blink/renderer/core/html/portal/portal_host.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_HOST_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_HOST_H_
 
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
 #include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
@@ -12,9 +13,12 @@
 
 namespace blink {
 
+class Document;
 class ExecutionContext;
 class LocalDOMWindow;
+class ScriptValue;
 class SecurityOrigin;
+class WindowPostMessageOptions;
 
 class CORE_EXPORT PortalHost : public EventTargetWithInlineData,
                                public Supplement<LocalDOMWindow> {
@@ -34,9 +38,28 @@
   ExecutionContext* GetExecutionContext() const override;
   PortalHost* ToPortalHost() override;
 
+  Document* GetDocument() const;
+
+  // Called immediately before dispatching the onactivate event.
+  void OnPortalActivated();
+
+  // idl implementation
+  void postMessage(const String& message,
+                   const String& target_origin,
+                   Vector<ScriptValue>& transfer,
+                   ExceptionState& exception_state);
+  void postMessage(const String& message,
+                   const WindowPostMessageOptions* options,
+                   ExceptionState& exception_state);
+
   void ReceiveMessage(BlinkTransferableMessage message,
                       scoped_refptr<const SecurityOrigin> source_origin,
                       scoped_refptr<const SecurityOrigin> target_origin);
+
+ private:
+  mojom::blink::PortalHost& GetPortalHostInterface();
+
+  mojom::blink::PortalHostAssociatedPtr portal_host_ptr_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/portal_host.idl b/third_party/blink/renderer/core/html/portal/portal_host.idl
index 2cf4048..364f233 100644
--- a/third_party/blink/renderer/core/html/portal/portal_host.idl
+++ b/third_party/blink/renderer/core/html/portal/portal_host.idl
@@ -5,4 +5,9 @@
 // https://wicg.github.io/portals/#the-portalhost-interface
 
 [Exposed=Window, RuntimeEnabled=Portals]
-interface PortalHost : EventTarget {};
+interface PortalHost : EventTarget {
+  [RaisesException] void postMessage(DOMString message, DOMString targetOrigin,
+                                     optional sequence<object> transfer = []);
+  [RaisesException] void postMessage(DOMString message,
+                                     optional WindowPostMessageOptions options);
+};
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 6ee2025..6fb99485a1 100644
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -293,11 +293,13 @@
   if (auto* context = element->GetDisplayLockContext()) {
     if (context->IsLocked()) {
       // If it's a locked element, use the values from the locked frame rect.
-      const LayoutRect& locked_rect = context->GetLockedFrameRect();
-      element_info->setString("nodeWidth",
-                              String::Number((double)locked_rect.Width()));
-      element_info->setString("nodeHeight",
-                              String::Number((double)locked_rect.Height()));
+      // TODO(vmpstr): Verify that these values are correct here.
+      element_info->setString(
+          "nodeWidth",
+          String::Number(context->GetLockedContentLogicalWidth().ToDouble()));
+      element_info->setString(
+          "nodeHeight",
+          String::Number(context->GetLockedContentLogicalHeight().ToDouble()));
     }
     return element_info;
   }
diff --git a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
index d029132..d46ddf1 100644
--- a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
@@ -493,6 +493,7 @@
     return false;
 
   return !child.ShouldApplySizeContainment() &&
+         !child.DisplayLockInducesSizeContainment() &&
          MainAxisOverflowForChild(child) == EOverflow::kVisible;
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index d363f50..a499f8c4 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -419,26 +419,6 @@
 
   LayoutAnalyzer::Scope analyzer(*this);
 
-  base::Optional<DisplayLockContext::ScopedPendingFrameRect>
-      scoped_pending_frame_rect;
-  if (auto* context = GetDisplayLockContext()) {
-    // In a display locked element, we might be prevented from doing layout in
-    // which case we should abort.
-    if (LayoutBlockedByDisplayLock()) {
-      // TODO(vmpstr): This is probably wrong, we need to do full self-layout
-      // here, but for now just update our frame rect.
-      SetFrameRect(context->GetLockedFrameRect());
-      return;
-    }
-    // If we're display locked, then our layout should go into a pending frame
-    // rect without updating the frame rect visible to the ancestors. The
-    // following scoped object provides this functionality: it puts in place the
-    // (previously updated) pending frame rect. When the object is destroyed, it
-    // saves the pending frame rect in the DisplayLockContext and restores the
-    // frame rect that was in place at the time the lock was acquired.
-    scoped_pending_frame_rect.emplace(context->GetScopedPendingFrameRect());
-  }
-
   bool needs_scroll_anchoring =
       HasOverflowClip() && GetScrollableArea()->ShouldPerformScrollAnchoring();
   if (needs_scroll_anchoring)
@@ -456,7 +436,6 @@
     ClearLayoutOverflow();
 
   height_available_to_children_changed_ = false;
-  NotifyDisplayLockDidLayout();
 }
 
 bool LayoutBlock::WidthAvailableToChildrenHasChanged() {
@@ -500,6 +479,9 @@
 }
 
 void LayoutBlock::AddLayoutOverflowFromChildren() {
+  if (DisplayLockInducesSizeContainment())
+    return;
+
   if (ChildrenInline())
     To<LayoutBlockFlow>(this)->AddLayoutOverflowFromInlineChildren();
   else
@@ -696,6 +678,9 @@
         return false;
     }
 
+    if (LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
+      return false;
+
     TextAutosizer::LayoutScope text_autosizer_layout_scope(this);
 
     // Lay out positioned descendants or objects that just need to recompute
@@ -829,6 +814,9 @@
 
 void LayoutBlock::LayoutPositionedObjects(bool relayout_children,
                                           PositionedLayoutBehavior info) {
+  if (LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
+    return;
+
   TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
   if (!positioned_descendants)
     return;
@@ -1457,6 +1445,13 @@
     LayoutUnit& max_logical_width) const {
   int scrollbar_width = ScrollbarLogicalWidth();
 
+  if (DisplayLockInducesSizeContainment()) {
+    min_logical_width = max_logical_width =
+        LayoutUnit(scrollbar_width) +
+        GetDisplayLockContext()->GetLockedContentLogicalWidth();
+    return;
+  }
+
   // Size-contained elements don't consider their contents for preferred sizing.
   if (ShouldApplySizeContainment()) {
     // For multicol containers we need the column gaps. So allow descending into
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index 468a994..42c37aa 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -444,6 +444,9 @@
   DCHECK(NeedsLayout());
   DCHECK(IsInlineBlockOrInlineTable() || !IsInline());
 
+  if (LayoutBlockedByDisplayLock(DisplayLockContext::kSelf))
+    return;
+
   if (RuntimeEnabledFeatures::TrackLayoutPassesPerBlockEnabled())
     IncrementLayoutPassCount();
 
@@ -537,8 +540,10 @@
   if (IsHTMLDialogElement(GetNode()) && IsOutOfFlowPositioned())
     PositionDialog();
 
-  ClearNeedsLayout();
+  // Only clear child dirty bits, if we allowed child layout.
+  ClearNeedsLayout(!LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
   UpdateIsSelfCollapsing();
+  NotifyDisplayLockDidLayout(DisplayLockContext::kSelf);
 }
 
 DISABLE_CFI_PERF
@@ -599,6 +604,9 @@
                                      SubtreeLayoutScope& layout_scope) {
   ResetLayout();
 
+  if (LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
+    return;
+
   LayoutUnit before_edge = BorderBefore() + PaddingBefore();
   LayoutUnit after_edge = BorderAfter() + PaddingAfter();
 
@@ -619,6 +627,8 @@
   if (LowestFloatLogicalBottom() > (LogicalHeight() - after_edge) &&
       CreatesNewFormattingContext())
     SetLogicalHeight(LowestFloatLogicalBottom() + after_edge);
+
+  NotifyDisplayLockDidLayout(DisplayLockContext::kChildren);
 }
 
 void LayoutBlockFlow::AddOverhangingFloatsFromChildren(
@@ -2377,7 +2387,8 @@
 
 bool LayoutBlockFlow::MustDiscardMarginBeforeForChild(
     const LayoutBox& child) const {
-  DCHECK(!child.SelfNeedsLayout() || child.LayoutBlockedByDisplayLock());
+  DCHECK(!child.SelfNeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kSelf));
   if (!child.IsWritingModeRoot()) {
     auto* child_layout_block = DynamicTo<LayoutBlockFlow>(&child);
     return child_layout_block ? child_layout_block->MustDiscardMarginBefore()
@@ -2400,7 +2411,8 @@
 
 bool LayoutBlockFlow::MustDiscardMarginAfterForChild(
     const LayoutBox& child) const {
-  DCHECK(!child.SelfNeedsLayout() || child.LayoutBlockedByDisplayLock());
+  DCHECK(!child.SelfNeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kSelf));
   if (!child.IsWritingModeRoot()) {
     auto* child_layout_block = DynamicTo<LayoutBlockFlow>(&child);
     return child_layout_block ? child_layout_block->MustDiscardMarginAfter()
@@ -2442,7 +2454,8 @@
 
 bool LayoutBlockFlow::MustSeparateMarginBeforeForChild(
     const LayoutBox& child) const {
-  DCHECK(!child.SelfNeedsLayout() || child.LayoutBlockedByDisplayLock());
+  DCHECK(!child.SelfNeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kSelf));
   const ComputedStyle& child_style = child.StyleRef();
   if (!child.IsWritingModeRoot())
     return child_style.MarginBeforeCollapse() == EMarginCollapse::kSeparate;
@@ -2455,7 +2468,8 @@
 
 bool LayoutBlockFlow::MustSeparateMarginAfterForChild(
     const LayoutBox& child) const {
-  DCHECK(!child.SelfNeedsLayout() || child.LayoutBlockedByDisplayLock());
+  DCHECK(!child.SelfNeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kSelf));
   const ComputedStyle& child_style = child.StyleRef();
   if (!child.IsWritingModeRoot())
     return child_style.MarginAfterCollapse() == EMarginCollapse::kSeparate;
@@ -4902,7 +4916,9 @@
 
 const NGOffsetMapping* LayoutBlockFlow::GetOffsetMapping() const {
   DCHECK(!IsLayoutNGObject());
-  CHECK(!NeedsLayout());
+  CHECK(!SelfNeedsLayout());
+  CHECK(!NeedsLayout() ||
+        LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
   return rare_data_ ? rare_data_->offset_mapping_.get() : nullptr;
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 5246db39..0db5093 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -508,7 +508,7 @@
   DCHECK(NeedsLayout());
   LayoutAnalyzer::Scope analyzer(*this);
 
-  if (LayoutBlockedByDisplayLock())
+  if (LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
     return;
 
   LayoutObject* child = SlowFirstChild();
@@ -525,7 +525,7 @@
   }
   UpdateAfterLayout();
   ClearNeedsLayout();
-  NotifyDisplayLockDidLayout();
+  NotifyDisplayLockDidLayout(DisplayLockContext::kChildren);
 }
 
 // ClientWidth and ClientHeight represent the interior of an object excluding
@@ -2907,10 +2907,16 @@
 DISABLE_CFI_PERF
 void LayoutBox::ComputeLogicalWidth(
     LogicalExtentComputedValues& computed_values) const {
-  computed_values.extent_ =
-      ShouldApplySizeContainment()
-          ? BorderAndPaddingLogicalWidth() + ScrollbarLogicalWidth()
-          : LogicalWidth();
+  if (DisplayLockInducesSizeContainment()) {
+    computed_values.extent_ =
+        BorderAndPaddingLogicalWidth() + ScrollbarLogicalWidth() +
+        GetDisplayLockContext()->GetLockedContentLogicalWidth();
+  } else if (ShouldApplySizeContainment()) {
+    computed_values.extent_ =
+        BorderAndPaddingLogicalWidth() + ScrollbarLogicalWidth();
+  } else {
+    computed_values.extent_ = LogicalWidth();
+  }
   computed_values.position_ = LogicalLeft();
   computed_values.margins_.start_ = MarginStart();
   computed_values.margins_.end_ = MarginEnd();
@@ -3399,10 +3405,15 @@
 
 void LayoutBox::ComputeLogicalHeight(
     LogicalExtentComputedValues& computed_values) const {
-  LayoutUnit height =
-      ShouldApplySizeContainment()
-          ? BorderAndPaddingLogicalHeight() + ScrollbarLogicalHeight()
-          : LogicalHeight();
+  LayoutUnit height;
+  if (DisplayLockInducesSizeContainment()) {
+    height = BorderAndPaddingLogicalHeight() + ScrollbarLogicalHeight() +
+             GetDisplayLockContext()->GetLockedContentLogicalHeight();
+  } else if (ShouldApplySizeContainment()) {
+    height = BorderAndPaddingLogicalHeight() + ScrollbarLogicalHeight();
+  } else {
+    height = LogicalHeight();
+  }
   ComputeLogicalHeight(height, LogicalTop(), computed_values);
 }
 
@@ -3535,12 +3546,20 @@
 }
 
 LayoutUnit LayoutBox::ComputeLogicalHeightWithoutLayout() const {
-  // TODO(cbiesinger): We should probably return something other than just
-  // border + padding, but for now we have no good way to do anything else
-  // without layout, so we just use that.
   LogicalExtentComputedValues computed_values;
-  ComputeLogicalHeight(BorderAndPaddingLogicalHeight(), LayoutUnit(),
-                       computed_values);
+
+  if (!SelfNeedsLayout() && DisplayLockInducesSizeContainment()) {
+    ComputeLogicalHeight(
+        BorderAndPaddingLogicalHeight() +
+            GetDisplayLockContext()->GetLockedContentLogicalHeight(),
+        LayoutUnit(), computed_values);
+  } else {
+    // TODO(cbiesinger): We should probably return something other than just
+    // border + padding, but for now we have no good way to do anything else
+    // without layout, so we just use that.
+    ComputeLogicalHeight(BorderAndPaddingLogicalHeight(), LayoutUnit(),
+                         computed_values);
+  }
   return computed_values.extent_;
 }
 
@@ -5384,7 +5403,8 @@
 void LayoutBox::MarkChildForPaginationRelayoutIfNeeded(
     LayoutBox& child,
     SubtreeLayoutScope& layout_scope) {
-  DCHECK(!child.NeedsLayout());
+  DCHECK(!child.NeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
   LayoutState* layout_state = View()->GetLayoutState();
 
   if (layout_state->PaginationStateChanged() ||
@@ -5669,7 +5689,7 @@
       (Parent() && IsWritingModeRoot()) ||
       (IsOutOfFlowPositioned() &&
        StyleRef().GetPosition() == EPosition::kFixed) ||
-      ShouldApplySizeContainment())
+      ShouldApplySizeContainment() || DisplayLockInducesSizeContainment())
     return kForbidBreaks;
 
   EBreakInside break_value = BreakInside();
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index e723b72..c4739e62 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -392,14 +392,6 @@
     SetLocation(rect.Location());
     SetSize(rect.Size());
   }
-  // Similar to SetFrameRect(), except it avoids notifying other code about size
-  // and location changes. This should only be used from a DisplayLockContext to
-  // temporarily put in place a pending frame rect which is restored at the end
-  // of layout. Code outside of layout should not observe location or size
-  // changes.
-  void SetFrameRectForDisplayLock(const LayoutRect& rect) {
-    frame_rect_ = rect;
-  }
 
   // Note that those functions have their origin at this box's CSS border box.
   // As such their location doesn't account for 'top'/'left'. About its
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
index 2291e0d..4798dbb 100644
--- a/third_party/blink/renderer/core/layout/layout_embedded_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -111,7 +111,7 @@
 
 void LayoutEmbeddedObject::ComputeIntrinsicSizingInfo(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
-  DCHECK(!ShouldApplySizeContainment());
+  DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
   FrameView* frame_view = ChildFrameView();
   if (frame_view && frame_view->GetIntrinsicSizingInfo(intrinsic_sizing_info)) {
     // Handle zoom & vertical writing modes here, as the embedded document
diff --git a/third_party/blink/renderer/core/layout/layout_fieldset.cc b/third_party/blink/renderer/core/layout/layout_fieldset.cc
index 91dba64..3db99ab1 100644
--- a/third_party/blink/renderer/core/layout/layout_fieldset.cc
+++ b/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -35,7 +35,7 @@
 void LayoutFieldset::ComputePreferredLogicalWidths() {
   LayoutBlockFlow::ComputePreferredLogicalWidths();
   // Size-contained elements don't consider their contents for preferred sizing.
-  if (ShouldApplySizeContainment())
+  if (ShouldApplySizeContainment() || DisplayLockInducesSizeContainment())
     return;
 
   if (LayoutBox* legend = FindInFlowLegend()) {
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index d587071..1b0a5ffb 100644
--- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -68,6 +68,12 @@
     LayoutUnit& min_logical_width,
     LayoutUnit& max_logical_width) const {
   LayoutUnit scrollbar_width(ScrollbarLogicalWidth());
+  if (DisplayLockInducesSizeContainment()) {
+    min_logical_width = max_logical_width =
+        scrollbar_width +
+        GetDisplayLockContext()->GetLockedContentLogicalWidth();
+    return;
+  }
   if (ShouldApplySizeContainment()) {
     max_logical_width = scrollbar_width;
     min_logical_width = scrollbar_width;
@@ -498,10 +504,14 @@
   DCHECK(MainAxisIsInlineAxis(child));
   if (NeedToStretchChildLogicalHeight(child)) {
     LayoutUnit child_intrinsic_content_logical_height;
-    if (!child.ShouldApplySizeContainment()) {
+    if (child.DisplayLockInducesSizeContainment()) {
+      child_intrinsic_content_logical_height =
+          child.GetDisplayLockContext()->GetLockedContentLogicalHeight();
+    } else if (!child.ShouldApplySizeContainment()) {
       child_intrinsic_content_logical_height =
           child.IntrinsicContentLogicalHeight();
     }
+
     LayoutUnit child_intrinsic_logical_height =
         child_intrinsic_content_logical_height +
         child.ScrollbarLogicalHeight() + child.BorderAndPaddingLogicalHeight();
@@ -769,7 +779,9 @@
 }
 
 void LayoutFlexibleBox::CacheChildMainSize(const LayoutBox& child) {
-  DCHECK(!child.NeedsLayout());
+  DCHECK(!child.SelfNeedsLayout());
+  DCHECK(!child.NeedsLayout() ||
+         child.LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
   LayoutUnit main_size;
   if (MainAxisIsInlineAxis(child)) {
     main_size = child.MaxPreferredLogicalWidth();
@@ -848,6 +860,11 @@
   } else {
     if (child.ShouldApplySizeContainment())
       return LayoutUnit();
+    // The needed value here is the logical height. This value does not include
+    // the border/scrollbar/padding size, so we can just return the locked value
+    // directly.
+    if (child.DisplayLockInducesSizeContainment())
+      return child.GetDisplayLockContext()->GetLockedContentLogicalHeight();
 
     if (child_layout_type == kNeverLayout)
       return LayoutUnit();
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc
index a03d251..e1e73aad 100644
--- a/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -501,6 +501,7 @@
   min_logical_width = scrollbar_width;
   max_logical_width = scrollbar_width;
 
+  // TODO(crbug.com/953915): Handle display-locked grid sizing.
   if (ShouldApplySizeContainment())
     return;
 
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc
index aa835f6..a686a19 100644
--- a/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -348,7 +348,7 @@
 
 void LayoutImage::ComputeIntrinsicSizingInfo(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
-  DCHECK(!ShouldApplySizeContainment());
+  DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
   if (!OverrideIntrinsicSizingInfo(intrinsic_sizing_info)) {
     if (SVGImage* svg_image = EmbeddedSVGImage()) {
       svg_image->GetIntrinsicSizingInfo(intrinsic_sizing_info);
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
index 8921d48b..2ba1a85 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -1343,6 +1343,7 @@
   LayoutUnit gap_extra((column_count - 1) *
                        ColumnGap(*multicol_style, LayoutUnit()));
 
+  DCHECK(!MultiColumnBlockFlow()->DisplayLockInducesSizeContainment());
   if (MultiColumnBlockFlow()->ShouldApplySizeContainment()) {
     min_preferred_logical_width_ = max_preferred_logical_width_ = LayoutUnit();
     ClearPreferredLogicalWidthsDirty();
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
index 965bced..fafa632 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
@@ -109,6 +109,7 @@
   // the flow thread to calculate the correct preferred width (to honor
   // column-count, column-width and column-gap). Since spanner placeholders are
   // siblings of the flow thread, we need this check.
+  // TODO(crbug.com/953919): What should we return for display-locked content?
   if (MultiColumnBlockFlow()->ShouldApplySizeContainment())
     return LayoutUnit();
   return layout_object_in_flow_thread_->MinPreferredLogicalWidth();
@@ -117,6 +118,7 @@
 LayoutUnit LayoutMultiColumnSpannerPlaceholder::MaxPreferredLogicalWidth()
     const {
   // See above.
+  // TODO(crbug.com/953919): What should we return for display-locked content?
   if (MultiColumnBlockFlow()->ShouldApplySizeContainment())
     return LayoutUnit();
   return layout_object_in_flow_thread_->MaxPreferredLogicalWidth();
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index e80e58f9..0969debd 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -980,11 +980,15 @@
       return;
 
     // Note that if the last element we processed was blocked by a display lock,
-    // then we can return and stop the dirty bit propagation. Note that it's not
-    // enough to check |object|, since the element that is actually locked needs
-    // its child bits set properly, we need to go one more iteration after that.
-    if (last->LayoutBlockedByDisplayLock())
+    // and the reason we're propagating a change is that a subtree needed layout
+    // (ie self doesn't need layout), then we can return and stop the dirty bit
+    // propagation. Note that it's not enough to check |object|, since the
+    // element that is actually locked needs its child bits set properly, we
+    // need to go one more iteration after that.
+    if (!last->SelfNeedsLayout() &&
+        last->LayoutBlockedByDisplayLock(DisplayLockContext::kChildren)) {
       return;
+    }
 
     // Don't mark the outermost object of an unrooted subtree. That object will
     // be marked when the subtree is added to the document.
@@ -1078,6 +1082,8 @@
 
 #if DCHECK_IS_ON()
 void LayoutObject::CheckBlockPositionedObjectsNeedLayout() {
+  if (LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
+    return;
   DCHECK(!NeedsLayout());
 
   auto* layout_block = DynamicTo<LayoutBlock>(this);
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index c5558e9..1dc9b93e 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -395,15 +395,18 @@
 
   void AssertLaidOut() const {
 #ifndef NDEBUG
-    if (NeedsLayout() && !LayoutBlockedByDisplayLock())
+    if (NeedsLayout() &&
+        !LayoutBlockedByDisplayLock(DisplayLockContext::kChildren))
       ShowLayoutTreeForThis();
 #endif
-    SECURITY_DCHECK(!NeedsLayout() || LayoutBlockedByDisplayLock());
+    SECURITY_DCHECK(!NeedsLayout() ||
+                    LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
   }
 
   void AssertSubtreeIsLaidOut() const {
     for (const LayoutObject* layout_object = this; layout_object;
-         layout_object = layout_object->LayoutBlockedByDisplayLock()
+         layout_object = layout_object->LayoutBlockedByDisplayLock(
+                             DisplayLockContext::kChildren)
                              ? layout_object->NextInPreOrderAfterChildren()
                              : layout_object->NextInPreOrder()) {
       layout_object->AssertLaidOut();
@@ -1231,10 +1234,12 @@
       MarkingBehavior = kMarkContainerChain,
       SubtreeLayoutScope* = nullptr);
 
-  void ClearNeedsLayoutWithoutPaintInvalidation();
+  void ClearNeedsLayoutWithoutPaintInvalidation(
+      bool clear_child_dirty_bits = true);
   // |ClearNeedsLayout()| calls |SetShouldCheckForPaintInvalidation()|.
-  void ClearNeedsLayout();
-  void ClearNeedsLayoutWithFullPaintInvalidation();
+  void ClearNeedsLayout(bool clear_child_dirty_bits = true);
+  void ClearNeedsLayoutWithFullPaintInvalidation(
+      bool clear_child_dirty_bits = true);
 
   void SetChildNeedsLayout(MarkingBehavior = kMarkContainerChain,
                            SubtreeLayoutScope* = nullptr);
@@ -2249,9 +2254,15 @@
     bitfields_.SetOutlineMayBeAffectedByDescendants(b);
   }
 
-  bool LayoutBlockedByDisplayLock() const {
+  bool LayoutBlockedByDisplayLock(
+      DisplayLockContext::LifecycleTarget target) const {
     auto* context = GetDisplayLockContext();
-    return context && !context->ShouldLayout();
+    return context && !context->ShouldLayout(target);
+  }
+
+  bool DisplayLockInducesSizeContainment() const {
+    auto* context = GetDisplayLockContext();
+    return context && context->IsLocked();
   }
 
   bool PrePaintBlockedByDisplayLock() const {
@@ -2455,9 +2466,9 @@
   LayoutSize OffsetFromScrollableContainer(const LayoutObject*,
                                            bool ignore_scroll_offset) const;
 
-  void NotifyDisplayLockDidLayout() {
+  void NotifyDisplayLockDidLayout(DisplayLockContext::LifecycleTarget target) {
     if (auto* context = GetDisplayLockContext())
-      context->DidLayout();
+      context->DidLayout(target);
   }
 
   bool BackgroundIsKnownToBeObscured() const {
@@ -3112,19 +3123,23 @@
   SetShouldDoFullPaintInvalidation();
 }
 
-inline void LayoutObject::ClearNeedsLayoutWithoutPaintInvalidation() {
+inline void LayoutObject::ClearNeedsLayoutWithoutPaintInvalidation(
+    bool clear_child_dirty_bits) {
   // Set flags for later stages/cycles.
   SetEverHadLayout();
 
   // Clear needsLayout flags.
   SetSelfNeedsLayoutForStyle(false);
   SetSelfNeedsLayoutForAvailableSpace(false);
-  SetPosChildNeedsLayout(false);
-  SetNeedsSimplifiedNormalFlowLayout(false);
-  SetNormalChildNeedsLayout(false);
   SetNeedsPositionedMovementLayout(false);
   SetAncestorLineBoxDirty(false);
 
+  if (clear_child_dirty_bits) {
+    SetPosChildNeedsLayout(false);
+    SetNormalChildNeedsLayout(false);
+    SetNeedsSimplifiedNormalFlowLayout(false);
+  }
+
 #if DCHECK_IS_ON()
   CheckBlockPositionedObjectsNeedLayout();
 #endif
@@ -3132,13 +3147,14 @@
   SetScrollAnchorDisablingStyleChanged(false);
 }
 
-inline void LayoutObject::ClearNeedsLayout() {
-  ClearNeedsLayoutWithoutPaintInvalidation();
+inline void LayoutObject::ClearNeedsLayout(bool clear_child_dirty_bits) {
+  ClearNeedsLayoutWithoutPaintInvalidation(clear_child_dirty_bits);
   SetShouldCheckForPaintInvalidation();
 }
 
-inline void LayoutObject::ClearNeedsLayoutWithFullPaintInvalidation() {
-  ClearNeedsLayoutWithoutPaintInvalidation();
+inline void LayoutObject::ClearNeedsLayoutWithFullPaintInvalidation(
+    bool clear_child_dirty_bits) {
+  ClearNeedsLayoutWithoutPaintInvalidation(clear_child_dirty_bits);
   SetShouldDoFullPaintInvalidation();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc
index 3b1fb41..7edc19c 100644
--- a/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -160,6 +160,7 @@
 
 void LayoutReplaced::ComputeIntrinsicSizingInfoForReplacedContent(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
+  // TODO(crbug.com/953925): How should we size display-locked replaced content?
   if (ShouldApplySizeContainment()) {
     intrinsic_sizing_info.size = FloatSize();
     return;
@@ -658,7 +659,7 @@
 
 void LayoutReplaced::ComputeIntrinsicSizingInfo(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
-  DCHECK(!ShouldApplySizeContainment());
+  DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
   intrinsic_sizing_info.size = FloatSize(IntrinsicLogicalWidth().ToFloat(),
                                          IntrinsicLogicalHeight().ToFloat());
 
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
index 36c1b656..4737841 100644
--- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
+++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -13,7 +13,6 @@
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/ref_vector.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/subtree_layout_scope.cc b/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
index 6843f15..561adc5 100644
--- a/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
+++ b/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
@@ -40,7 +40,10 @@
 }
 
 SubtreeLayoutScope::~SubtreeLayoutScope() {
-  CHECK(!root_.NeedsLayout() || root_.LayoutBlockedByDisplayLock());
+  CHECK(!root_.SelfNeedsLayout() ||
+        root_.LayoutBlockedByDisplayLock(DisplayLockContext::kSelf));
+  CHECK(!root_.NeedsLayout() ||
+        root_.LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
 
 #if DCHECK_IS_ON()
   for (auto* layout_object : layout_objects_to_layout_)
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc
index b2a2c59b..c81803b 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -153,8 +153,10 @@
 }
 
 std::pair<RemoteFrame*, base::UnguessableToken>
-EmptyLocalFrameClient::CreatePortal(HTMLPortalElement*,
-                                    mojom::blink::PortalAssociatedRequest) {
+EmptyLocalFrameClient::CreatePortal(
+    HTMLPortalElement*,
+    mojom::blink::PortalAssociatedRequest,
+    mojom::blink::PortalClientAssociatedPtrInfo) {
   return std::pair<RemoteFrame*, base::UnguessableToken>(
       nullptr, base::UnguessableToken());
 }
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 8b35658..240c4b1d 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -335,7 +335,8 @@
   LocalFrame* CreateFrame(const AtomicString&, HTMLFrameOwnerElement*) override;
   std::pair<RemoteFrame*, base::UnguessableToken> CreatePortal(
       HTMLPortalElement*,
-      mojom::blink::PortalAssociatedRequest) override;
+      mojom::blink::PortalAssociatedRequest,
+      mojom::blink::PortalClientAssociatedPtrInfo) override;
   RemoteFrame* AdoptPortal(HTMLPortalElement*) override;
   WebPluginContainerImpl* CreatePlugin(HTMLPlugInElement&,
                                        const KURL&,
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
index 53ae3fd1..5c60e62 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -177,14 +177,17 @@
     return false;
 
   if (event->type() == event_type_names::kKeydown) {
+    interest_element->SetActive(true);
+  } else if (event->type() == event_type_names::kKeyup) {
+    interest_element->SetActive(false);
     if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) {
       interest_element->focus(FocusParams(SelectionBehaviorOnFocus::kReset,
                                           kWebFocusTypeSpatialNavigation,
                                           nullptr));
+      // We need enter to activate links, etc. The click should be after the
+      // focus in case the site transfers focus upon clicking.
+      interest_element->DispatchSimulatedClick(event);
     }
-    interest_element->SetActive(true);
-  } else if (event->type() == event_type_names::kKeyup) {
-    interest_element->SetActive(false);
   }
 
   return true;
diff --git a/third_party/blink/renderer/core/style/applied_text_decoration_list.h b/third_party/blink/renderer/core/style/applied_text_decoration_list.h
index 21301f2..e0624533 100644
--- a/third_party/blink/renderer/core/style/applied_text_decoration_list.h
+++ b/third_party/blink/renderer/core/style/applied_text_decoration_list.h
@@ -6,11 +6,11 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_APPLIED_TEXT_DECORATION_LIST_H_
 
 #include "third_party/blink/renderer/core/style/applied_text_decoration.h"
-#include "third_party/blink/renderer/platform/wtf/ref_vector.h"
 
 namespace blink {
 
-typedef RefVector<AppliedTextDecoration> AppliedTextDecorationList;
+typedef base::RefCountedData<WTF::Vector<AppliedTextDecoration>>
+    AppliedTextDecorationList;
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 55acc69b81..6b3a22a 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1688,7 +1688,7 @@
     return empty;
   }
 
-  return AppliedTextDecorationsInternal()->GetVector();
+  return AppliedTextDecorationsInternal()->data;
 }
 
 static bool HasInitialVariables(const StyleInitialData* initial_data) {
@@ -1925,11 +1925,11 @@
       MutableAppliedTextDecorationsInternal();
 
   if (!list)
-    list = AppliedTextDecorationList::Create();
+    list = base::MakeRefCounted<AppliedTextDecorationList>();
   else if (!list->HasOneRef())
-    list = list->Copy();
+    list = base::MakeRefCounted<AppliedTextDecorationList>(list->data);
 
-  list->push_back(decoration);
+  list->data.push_back(decoration);
 }
 
 void ComputedStyle::OverrideTextDecorationColors(Color override_color) {
@@ -1937,9 +1937,9 @@
       MutableAppliedTextDecorationsInternal();
   DCHECK(list);
   if (!list->HasOneRef())
-    list = list->Copy();
+    list = base::MakeRefCounted<AppliedTextDecorationList>(list->data);
 
-  for (AppliedTextDecoration& decoration : *list)
+  for (AppliedTextDecoration& decoration : list->data)
     decoration.SetColor(override_color);
 }
 
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index cbabbc3..1f2267d 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -172,8 +172,6 @@
   // Needed to allow access to private/protected getters of fields to allow diff
   // generation
   friend class ComputedStyleBase;
-  // Used by Web Animations CSS. Sets the color styles.
-  friend class AnimatedStyleBuilder;
   // Used by Web Animations CSS. Gets visited and unvisited colors separately.
   friend class CSSAnimatableValueFactory;
   // Used by CSS animations. We can't allow them to animate based off visited
diff --git a/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc b/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
index c905828..ff75cab 100644
--- a/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
+++ b/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
 
 #include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
-#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
 #include "third_party/blink/renderer/platform/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/time.h"
 
@@ -44,11 +43,7 @@
           FROM_HERE,
           WTF::Bind(
               [](base::WeakPtr<WorkerAnimationFrameProvider> provider) {
-                ExecutionContext* context = provider->context_;
-                Performance* performance =
-                    WorkerGlobalScopePerformance::performance(
-                        *To<WorkerGlobalScope>(context));
-                double time = performance->now();
+                double time = WTF::CurrentTimeTicksInMilliseconds();
                 // We don't want to expose microseconds residues to users.
                 time = round(time * 60) / 60;
 
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 5a958d2d..721fbdf 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -42,7 +42,7 @@
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkSurface.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 using testing::_;
 using testing::InSequence;
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share.cc b/third_party/blink/renderer/modules/webshare/navigator_share.cc
index ad2db6f..956e0ec7 100644
--- a/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -80,7 +80,7 @@
 class NavigatorShare::ShareClientImpl final
     : public GarbageCollected<ShareClientImpl> {
  public:
-  ShareClientImpl(NavigatorShare*, ScriptPromiseResolver*);
+  ShareClientImpl(NavigatorShare*, bool has_files, ScriptPromiseResolver*);
 
   void Callback(mojom::blink::ShareError);
 
@@ -93,25 +93,31 @@
 
  private:
   WeakMember<NavigatorShare> navigator_;
+  bool has_files_;
   Member<ScriptPromiseResolver> resolver_;
 };
 
 NavigatorShare::ShareClientImpl::ShareClientImpl(
     NavigatorShare* navigator_share,
+    bool has_files,
     ScriptPromiseResolver* resolver)
-    : navigator_(navigator_share), resolver_(resolver) {}
+    : navigator_(navigator_share), has_files_(has_files), resolver_(resolver) {}
 
 void NavigatorShare::ShareClientImpl::Callback(mojom::blink::ShareError error) {
   if (navigator_)
     navigator_->clients_.erase(this);
 
   if (error == mojom::blink::ShareError::OK) {
+    UseCounter::Count(ExecutionContext::From(resolver_->GetScriptState()),
+                      has_files_
+                          ? WebFeature::kWebShareSuccessfulContainingFiles
+                          : WebFeature::kWebShareSuccessfulWithoutFiles);
     resolver_->Resolve();
   } else {
-    if (error == mojom::blink::ShareError::CANCELED) {
-      UseCounter::Count(ExecutionContext::From(resolver_->GetScriptState()),
-                        WebFeature::kWebShareCancelled);
-    }
+    UseCounter::Count(ExecutionContext::From(resolver_->GetScriptState()),
+                      has_files_
+                          ? WebFeature::kWebShareUnsuccessfulContainingFiles
+                          : WebFeature::kWebShareUnsuccessfulWithoutFiles);
     resolver_->Reject(DOMException::Create(
         (error == mojom::blink::ShareError::PERMISSION_DENIED)
             ? DOMExceptionCode::kNotAllowedError
@@ -196,15 +202,16 @@
     DCHECK(service_);
   }
 
+  bool has_files = HasFiles(*share_data);
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ShareClientImpl* client =
-      MakeGarbageCollected<ShareClientImpl>(this, resolver);
+      MakeGarbageCollected<ShareClientImpl>(this, has_files, resolver);
   clients_.insert(client);
   ScriptPromise promise = resolver->Promise();
 
   WTF::Vector<mojom::blink::SharedFilePtr> files;
   uint64_t total_bytes = 0;
-  if (HasFiles(*share_data)) {
+  if (has_files) {
     files.ReserveInitialCapacity(share_data->files().size());
     for (const blink::Member<blink::File>& file : share_data->files()) {
       total_bytes += file->size();
@@ -218,9 +225,6 @@
           DOMExceptionCode::kNotAllowedError, "Permission denied");
       return ScriptPromise::RejectWithDOMException(script_state, error);
     }
-    UseCounter::Count(*doc, WebFeature::kWebShareContainingFiles);
-  } else {
-    UseCounter::Count(*doc, WebFeature::kWebShareWithoutFiles);
   }
 
   service_->Share(
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
index 678b8ec..e4c628a 100644
--- a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
+++ b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
@@ -140,8 +140,21 @@
   EXPECT_EQ(mock_share_service().text(), message);
   EXPECT_EQ(mock_share_service().url(), KURL(url));
   EXPECT_EQ(mock_share_service().files().size(), 0U);
-  EXPECT_TRUE(
-      UseCounter::IsCounted(GetDocument(), WebFeature::kWebShareWithoutFiles));
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kWebShareSuccessfulWithoutFiles));
+}
+
+File* CreateSampleFile(ExecutionContext* context,
+                       const String& file_name,
+                       const String& content_type,
+                       const String& file_contents) {
+  HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString> blob_parts;
+  blob_parts.push_back(ArrayBufferOrArrayBufferViewOrBlobOrUSVString());
+  blob_parts.back().SetUSVString(file_contents);
+
+  FilePropertyBag file_property_bag;
+  file_property_bag.setType(content_type);
+  return File::Create(context, blob_parts, file_name, &file_property_bag);
 }
 
 TEST_F(NavigatorShareTest, ShareFile) {
@@ -149,16 +162,9 @@
   const String content_type = "image/svg+xml";
   const String file_contents = "<svg></svg>";
 
-  HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString> blob_parts;
-  blob_parts.push_back(ArrayBufferOrArrayBufferViewOrBlobOrUSVString());
-  blob_parts.back().SetUSVString(file_contents);
-
-  FilePropertyBag file_property_bag;
-  file_property_bag.setType(content_type);
-
   HeapVector<Member<File>> files;
-  files.push_back(File::Create(ExecutionContext::From(GetScriptState()),
-                               blob_parts, file_name, &file_property_bag));
+  files.push_back(CreateSampleFile(ExecutionContext::From(GetScriptState()),
+                                   file_name, content_type, file_contents));
 
   ShareData share_data;
   share_data.setFiles(files);
@@ -169,8 +175,8 @@
   EXPECT_EQ(mock_share_service().files()[0]->blob->GetType(), content_type);
   EXPECT_EQ(mock_share_service().files()[0]->blob->size(),
             file_contents.length());
-  EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
-                                    WebFeature::kWebShareContainingFiles));
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kWebShareSuccessfulContainingFiles));
 }
 
 TEST_F(NavigatorShareTest, CancelShare) {
@@ -180,8 +186,26 @@
 
   mock_share_service().set_error(mojom::blink::ShareError::CANCELED);
   Share(share_data);
-  EXPECT_TRUE(
-      UseCounter::IsCounted(GetDocument(), WebFeature::kWebShareCancelled));
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kWebShareUnsuccessfulWithoutFiles));
+}
+
+TEST_F(NavigatorShareTest, CancelShareWithFile) {
+  const String file_name = "counts.csv";
+  const String content_type = "text/csv";
+  const String file_contents = "1,2,3";
+
+  HeapVector<Member<File>> files;
+  files.push_back(CreateSampleFile(ExecutionContext::From(GetScriptState()),
+                                   file_name, content_type, file_contents));
+
+  ShareData share_data;
+  share_data.setFiles(files);
+
+  mock_share_service().set_error(mojom::blink::ShareError::CANCELED);
+  Share(share_data);
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kWebShareUnsuccessfulContainingFiles));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 7204efb..899a849 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -656,4 +656,8 @@
   RuntimeEnabledFeatures::SetIdleDetectionEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableSkipTouchEventFilter(bool enable) {
+  RuntimeEnabledFeatures::SetSkipTouchEventFilterEnabled(enable);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
index 965892c8..ae07255f 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc b/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
index 9fa1a52..482341c5 100644
--- a/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
+++ b/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
@@ -6,7 +6,7 @@
 
 #include "base/sys_byteorder.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
index 7d3c185..adc39543 100644
--- a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
+++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
 
 #include "third_party/blink/public/platform/web_screen_info.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
index fd518c3..e198d62 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
@@ -83,7 +83,7 @@
   void BindTexture(GLenum target, GLuint texture) override {
     if (target == GL_TEXTURE_2D)
       state_.active_texture2d_binding = texture;
-    bound_textures_[target] = texture;
+    bound_textures_.insert(target, texture);
   }
 
   void BindFramebuffer(GLenum target, GLuint framebuffer) override {
@@ -207,7 +207,8 @@
                   GLenum type,
                   const void* pixels) override {
     if (target == GL_TEXTURE_2D && !level) {
-      texture_sizes_.Set(bound_textures_[target], IntSize(width, height));
+      texture_sizes_.Set(bound_textures_.find(target)->value,
+                         IntSize(width, height));
     }
   }
 
@@ -233,9 +234,9 @@
   MOCK_METHOD1(BindTexImage2DMock, void(GLint imageId));
   void BindTexImage2DCHROMIUM(GLenum target, GLint image_id) override {
     if (target == kImageCHROMIUMTarget) {
-      texture_sizes_.Set(bound_textures_[target],
-                         image_sizes_.find(image_id)->value);
-      image_to_texture_map_.Set(image_id, bound_textures_[target]);
+      GLuint value = bound_textures_.find(target)->value;
+      texture_sizes_.Set(value, image_sizes_.find(image_id)->value);
+      image_to_texture_map_.Set(image_id, value);
       BindTexImage2DMock(image_id);
     }
   }
@@ -373,7 +374,7 @@
   static constexpr GLuint kImageCHROMIUMTarget = GL_TEXTURE_2D;
 #endif
 
-  std::map<GLenum, GLuint> bound_textures_;
+  HashMap<GLenum, GLuint> bound_textures_;
 
   // State tracked to verify that it is restored correctly.
   struct State {
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc b/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
index 34559425..9fdbf89 100644
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
@@ -35,7 +35,7 @@
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
 #include "third_party/skia/include/effects/SkCornerPathEffect.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 #include <algorithm>
 #include <cmath>
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/third_party/blink/renderer/platform/image-decoders/image_decoder.h
index 550dbca..e723f9d 100644
--- a/third_party/blink/renderer/platform/image-decoders/image_decoder.h
+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.h
@@ -42,7 +42,7 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/time.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 class SkColorSpace;
 
diff --git a/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc b/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
index 2b63ae6e..37abdaf7 100644
--- a/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
+++ b/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
index 89cfad3..40e5fff 100644
--- a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
@@ -41,7 +41,7 @@
 #include <memory>
 
 #include "base/numerics/checked_math.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 
 #if (defined(__ARM_NEON__) || defined(__ARM_NEON))
 #include <arm_neon.h>
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 53a05210..4ea1cf7 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -370,7 +370,7 @@
     },
     {
       name: "CSSPictureInPicture",
-      status: "experimental",
+      status: "stable",
       depends_on: ["PictureInPictureAPI"],
     },
     {
@@ -1351,6 +1351,10 @@
       status: "experimental",
     },
     {
+      name: "SkipTouchEventFilter",
+      settable_from_internals: true,
+    },
+    {
       name: "SmoothScrollJSIntervention",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn
index 734afdbf..e0b0ca0 100644
--- a/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -96,7 +96,6 @@
     "pod_interval_tree.h",
     "pod_red_black_tree.h",
     "ref_counted.h",
-    "ref_vector.h",
     "sanitizers.h",
     "scoped_logger.cc",
     "scoped_logger.h",
diff --git a/third_party/blink/renderer/platform/wtf/ref_vector.h b/third_party/blink/renderer/platform/wtf/ref_vector.h
deleted file mode 100644
index 0f57502..0000000
--- a/third_party/blink/renderer/platform/wtf/ref_vector.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_REF_VECTOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_REF_VECTOR_H_
-
-#include <utility>
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-template <typename T>
-class RefVector : public RefCounted<RefVector<T>> {
- public:
-  static scoped_refptr<RefVector> Create() {
-    return base::AdoptRef(new RefVector<T>);
-  }
-  static scoped_refptr<RefVector> Create(const Vector<T>& vector) {
-    return base::AdoptRef(new RefVector<T>(vector));
-  }
-  static scoped_refptr<RefVector> Create(Vector<T>&& vector) {
-    return base::AdoptRef(new RefVector<T>(std::move(vector)));
-  }
-  scoped_refptr<RefVector> Copy() { return Create(GetVector()); }
-
-  const T& operator[](wtf_size_t i) const { return vector_[i]; }
-  T& operator[](wtf_size_t i) { return vector_[i]; }
-  const T& at(wtf_size_t i) const { return vector_.at(i); }
-  T& at(wtf_size_t i) { return vector_.at(i); }
-
-  T* begin() { return vector_.begin(); }
-  T* end() { return vector_.end(); }
-  const T* begin() const { return vector_.begin(); }
-  const T* end() const { return vector_.end(); }
-
-  bool operator==(const RefVector& o) const { return vector_ == o.vector_; }
-  bool operator!=(const RefVector& o) const { return vector_ != o.vector_; }
-
-  wtf_size_t size() const { return vector_.size(); }
-  bool IsEmpty() const { return !size(); }
-  void push_back(const T& decoration) { vector_.push_back(decoration); }
-  template <typename... Args>
-  T& emplace_back(Args&&... args) {
-    return vector_.emplace_back(std::forward<Args>(args)...);
-  }
-  const Vector<T>& GetVector() const { return vector_; }
-  Vector<T>* GetMutableVector() { return &vector_; }
-
- private:
-  Vector<T> vector_;
-  RefVector() = default;
-  RefVector(const Vector<T>& vector) : vector_(vector) {}
-  RefVector(Vector<T>&& vector) : vector_(vector) {}
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_REF_VECTOR_H_
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 6c1e809b..84df4e3 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -339,15 +339,32 @@
 crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ]
 Bug(none) virtual/disable-blink-gen-property-trees/ [ Skip ]
 crbug.com/917392 virtual/display-lock/display-lock/lock-after-append/acquire-after-resize.html [ Failure ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout-after-commit.html [ Failure ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout.html [ Failure ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-updated-layout.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout-after-commit.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-after-append/measure-updated-layout.html [ Failure ]
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update-and-commit.html [ Timeout ]
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update.html [ Timeout ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-update-measure-remove.html [ Failure ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-forced-layout.html [ Failure ]
-crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-updated-layout.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-before-append/acquire-update-measure-remove.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-before-append/measure-forced-layout.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-before-append/measure-updated-layout.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/acquire-size-used-when-auto-size-border.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/acquire-size-used-when-auto-size.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/flex-row-horizontal-with-grow.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/flex-row-horizontal.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/flex-row-vertical-with-grow.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/flex-row-vertical.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/layout-replaced.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/writing-modes.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/writing-modes-switch.html [ Failure ]
+crbug.com/955533 virtual/display-lock/display-lock/sizing/overflow-auto-with-overflow.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/min-width-respected.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/float-left.html [ Failure ]
 crbug.com/591099 virtual/display-lock/http/tests/devtools/elements/highlight/highlight-display-locked.js [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/writing-modes-inherited-after-append.html [ Failure ]
+crbug.com/917392 virtual/display-lock/display-lock/sizing/max-content-size-ignored.html [ Failure ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Failure Pass ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Pass ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 98a5933..1e6f032 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2316,3 +2316,8 @@
 external/wpt/payment-request/payment-response/retry-method-warnings-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html [ WontFix ]
 [ Retina ] external/wpt/pointerevents/pointerevent_touch-action-span-test_touch-manual.html [ WontFix ]
+external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html [ WontFix ]
+external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html [ WontFix ]
+external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html [ WontFix ]
+external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html [ WontFix ]
+external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index fdd4554..096e243 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -265,6 +265,7 @@
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update.html [ Timeout ]
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update-and-commit.html [ Timeout ]
 crbug.com/933544 virtual/display-lock/display-lock/lock-after-append/acquire-on-composited-layer.html [ Crash Pass ]
+crbug.com/955533 virtual/display-lock/display-lock/sizing/overflow-auto-with-overflow.html [ Failure ]
 crbug.com/882663 http/tests/devtools/elements/highlight/highlight-display-locked.js [ Skip ]
 
 # Sheriff 2018/05/25
@@ -3036,12 +3037,56 @@
 crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac10.11 ] external/wpt/webrtc/no-media-call.html [ Timeout ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-table-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-009-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-table-002-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-012-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-006-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-009-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-015-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-010-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-003-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-table-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-005-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-014-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-002-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-007-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-015-manual.html [ Skip ]
+crbug.com/626703 external/wpt/pointerevents/pointerevent_touch-action-pan-y-css_touch.html [ Timeout ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-003-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-003-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-004-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-006-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-008-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-004-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-003-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-014-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-002-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-010-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-002-manual.html [ Skip ]
+crbug.com/626703 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html [ Timeout ]
+crbug.com/626703 external/wpt/pointerevents/pointerevent_touch-action-none-css_touch.html [ Timeout ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-012-manual.html [ Skip ]
+crbug.com/626703 external/wpt/pointerevents/pointerevent_touch-action-pan-x-css_touch.html [ Timeout ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-005-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-002-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-forms-005-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-005-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-007-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vrl-forms-006-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-001-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-008-manual.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-writing-modes/writing-mode-vlr-table-002-manual.html [ Skip ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-align-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-margin-001.html [ Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-padding-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-margin-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-001.html [ Failure ]
-crbug.com/626703 external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout ]
+crbug.com/626703 external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/line-breaking/line-breaking-017.html [ Failure ]
 crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-button-001.html [ Failure ]
@@ -3051,7 +3096,7 @@
 crbug.com/626703 external/wpt/css/css-lists/li-list-item-counter.html [ Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-snap-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-006.html [ Failure ]
-crbug.com/626703 virtual/omt-worker-fetch/external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout ]
+crbug.com/626703 virtual/omt-worker-fetch/external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-margin-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-pseudo/marker-content-011.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-align-003.html [ Failure ]
@@ -3068,8 +3113,8 @@
 crbug.com/626703 external/wpt/css/css-multicol/multicol-span-all-button-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-multicol/multicol-span-all-button-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-lists/li-value-counter-reset-001.html [ Failure ]
-crbug.com/626703 virtual/outofblink-cors/external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout ]
-crbug.com/626703 external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout ]
+crbug.com/626703 virtual/outofblink-cors/external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout Failure ]
+crbug.com/626703 external/wpt/xhr/event-readystatechange-loaded.any.html [ Timeout Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-margin-002.html [ Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-padding-002.html [ Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-snap-003.html [ Failure ]
@@ -3081,11 +3126,11 @@
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-padding-001.html [ Failure ]
 crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-target-padding-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-snap-003.html [ Failure ]
-crbug.com/626703 virtual/omt-worker-fetch/external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout ]
+crbug.com/626703 virtual/omt-worker-fetch/external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-snap-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scroll-snap/scroll-target-margin-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-005.html [ Failure ]
-crbug.com/626703 virtual/outofblink-cors/external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout ]
+crbug.com/626703 virtual/outofblink-cors/external/wpt/xhr/event-readystatechange-loaded.any.worker.html [ Timeout Failure ]
 crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-button-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/image-min-max-content-intrinsic-size-change-008.html [ Failure ]
 crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-button-002.html [ Failure ]
@@ -6207,7 +6252,6 @@
 crbug.com/948785 [ Debug ] virtual/user-activation-v2/fast/events/pointerevents/pointer-event-consumed-touchstart-in-slop-region.html [ Pass Failure ]
 
 # Sheriff 2019-04-03
-crbug.com/947951 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html [ Pass Failure ]
 crbug.com/949167 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html [ Pass Timeout ]
 crbug.com/949207 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html [ Pass Timeout ]
 crbug.com/949440 [ Mac10.13 Debug ] http/tests/devtools/layers/layers-panel-mouse-events.js [ Pass Crash ]
@@ -6285,3 +6329,6 @@
 crbug.com/946534 [ Mac10.10 Mac10.11 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Pass Failure ]
 crbug.com/948785 [ Debug ] fast/events/pointerevents/pointer-event-consumed-touchstart-in-slop-region.html [ Pass Failure ]
 crbug.com/948785 [ Debug ] virtual/mouseevent_fractional/fast/events/pointerevents/pointer-event-consumed-touchstart-in-slop-region.html [ Pass Failure ]
+
+# Sheriff 2019-05-01
+crbug.com/958347 [ Linux ] external/wpt/editing/run/removeformat.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
index 31f4342..ce2f271 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
@@ -9,10 +9,6 @@
   contain: style layout;
   background: lightblue;
 }
-#small {
-  width: 50px;
-  height: 50px;
-}
 #spacer {
   width: 50px;
   height: 50px;
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves-expected.html
new file mode 100644
index 0000000..cab4e96f
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves-expected.html
@@ -0,0 +1,13 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves.html b/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves.html
new file mode 100644
index 0000000..cd3bb11
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/commit-immediate-acquire-resolves.html
@@ -0,0 +1,49 @@
+<!doctype HTML>
+
+<!--
+Runs an acquire, and calls commit without waiting for the acquire promise.
+-->
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+<div id="container"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    container.displayLock.commit();
+    container.displayLock.acquire({ timeout: Infinity }).then(() => {
+      container.displayLock.commit().then(
+        () => { finishTest("PASS"); },
+        (e) => { finishTest("FAIL " + e.message); });
+    });
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html b/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
index 9164a09a..b6ee881b 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
@@ -30,7 +30,7 @@
     t.step(() => assert_true(container.displayLock.locked, "context after update is locked"));
 
     let commit_promise = container.displayLock.commit();
-    t.step(() => assert_true(container.displayLock.locked, "context during commit is locked"));
+    t.step(() => assert_false(container.displayLock.locked, "context during commit is unlocked"));
 
     await commit_promise;
     t.step(() => assert_false(container.displayLock.locked, "context after commit is unlocked"));
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
index 08df37e..1556bf45 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
@@ -5,8 +5,6 @@
   contain: style layout;
   background: lightgreen;
 }
-#small {
-}
 #large {
   width: 200px;
   height: 200px;
@@ -23,7 +21,7 @@
 }
 </style>
 
-<div id="parent"><div class="contained" id="small"></div></div>
+<div id="parent"><div class="contained" id="small"><div id="large"></div></div></div>
 <div id="spacer"></div>
 
 <script src="../../resources/testharness.js"></script>
@@ -63,7 +61,6 @@
   }
 
   function construct(container) {
-    container.id = "large";
     container.appendChild(createChild("0"));
     container.appendChild(createChild("1"));
     container.appendChild(createChild("2"));
@@ -73,7 +70,7 @@
     let container = document.getElementById("small");
     await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
-    construct(container);
+    construct(document.getElementById("large"));
     measureForced();
 
     container.displayLock.commit();
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
index 8d5da176..b922f66 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
@@ -5,8 +5,6 @@
   contain: style layout;
   background: lightgreen;
 }
-#small {
-}
 #large {
   width: 200px;
   height: 200px;
@@ -23,7 +21,7 @@
 }
 </style>
 
-<div id="parent"><div class="contained" id="small"></div></div>
+<div id="parent"><div class="contained" id="small"><div id="large"></div></div></div>
 <div id="spacer"></div>
 
 <script src="../../resources/testharness.js"></script>
@@ -63,7 +61,6 @@
   }
 
   function construct(container) {
-    container.id = "large";
     container.appendChild(createChild("0"));
     container.appendChild(createChild("1"));
     container.appendChild(createChild("2"));
@@ -73,7 +70,7 @@
     let container = document.getElementById("small");
     await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
-    construct(container);
+    construct(document.getElementById("large"));
     measureForced();
 
     container.displayLock.commit().then(() => {
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
index 166f2dd..e1102f8 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
@@ -5,8 +5,6 @@
   contain: style layout;
   background: lightgreen;
 }
-#small {
-}
 #large {
   width: 200px;
   height: 200px;
@@ -23,7 +21,7 @@
 }
 </style>
 
-<div id="parent"><div class="contained" id="small"></div></div>
+<div id="parent"><div class="contained" id="small"><div id="large"></div></div></div>
 <div id="spacer"></div>
 
 <script src="../../resources/testharness.js"></script>
@@ -39,7 +37,6 @@
   }
 
   function construct(container) {
-    container.id = "large";
     container.appendChild(createChild("0"));
     container.appendChild(createChild("1"));
     container.appendChild(createChild("2"));
@@ -73,7 +70,7 @@
     let container = document.getElementById("small");
     await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
-    construct(container);
+    construct(document.getElementById("large"));
 
     container.displayLock.update().then(() => {
       measureInUpdate();
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html
index 7f3e07c1..1566d85f 100644
--- a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html
@@ -8,9 +8,11 @@
 <style>
 #container {
   contain: style layout;
+  background: lightgreen;
+}
+#sizer {
   width: 100px;
   height: 100px;
-  background: lightgreen;
 }
 .child {
   width: 20px;
@@ -59,9 +61,12 @@
 }
 
 function construct(container) {
-  container.appendChild(createChild("0"));
-  container.appendChild(createChild("1"));
-  container.appendChild(createChild("2"));
+  let sizer = document.createElement("div");
+  sizer.id = "sizer";
+  container.appendChild(sizer);
+  sizer.appendChild(createChild("0"));
+  sizer.appendChild(createChild("1"));
+  sizer.appendChild(createChild("2"));
 }
 
 function runTest() {
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/locked-attribute.html b/third_party/blink/web_tests/display-lock/lock-before-append/locked-attribute.html
index ccf33bb..6e0c136 100644
--- a/third_party/blink/web_tests/display-lock/lock-before-append/locked-attribute.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/locked-attribute.html
@@ -33,7 +33,7 @@
     t.step(() => assert_true(container.displayLock.locked, "context after update is locked"));
 
     let commit_promise = container.displayLock.commit();
-    t.step(() => assert_true(container.displayLock.locked, "context during commit is locked"));
+    t.step(() => assert_false(container.displayLock.locked, "context during commit is unlocked"));
 
     await commit_promise;
     t.step(() => assert_false(container.displayLock.locked, "context after commit is unlocked"));
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html
index 0729b2e7..0fede37 100644
--- a/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html
@@ -9,9 +9,11 @@
 <style>
 #container {
   contain: style layout;
+  background: lightgreen;
+}
+#sizer {
   width: 100px;
   height: 100px;
-  background: lightgreen;
 }
 .child {
   width: 20px;
@@ -66,9 +68,12 @@
   }
 
   function construct(container) {
-    container.appendChild(createChild("0"));
-    container.appendChild(createChild("1"));
-    container.appendChild(createChild("2"));
+    let sizer = document.createElement("div");
+    sizer.id = "sizer";
+    container.appendChild(sizer);
+    sizer.appendChild(createChild("0"));
+    sizer.appendChild(createChild("1"));
+    sizer.appendChild(createChild("2"));
   }
 
   async function runTest() {
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html
index 37e9903..f5a82db 100644
--- a/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html
@@ -9,9 +9,11 @@
 <style>
 #container {
   contain: style layout;
+  background: lightgreen;
+}
+#sizer {
   width: 100px;
   height: 100px;
-  background: lightgreen;
 }
 .child {
   width: 20px;
@@ -41,9 +43,12 @@
   }
 
   function construct(container) {
-    container.appendChild(createChild("0"));
-    container.appendChild(createChild("1"));
-    container.appendChild(createChild("2"));
+    let sizer = document.createElement("div");
+    sizer.id = "sizer";
+    container.appendChild(sizer);
+    sizer.appendChild(createChild("0"));
+    sizer.appendChild(createChild("1"));
+    sizer.appendChild(createChild("2"));
   }
 
   function measureInUpdate() {
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars-expected.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars-expected.html
new file mode 100644
index 0000000..044462a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars-expected.html
@@ -0,0 +1,25 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  visibility: hidden;
+  overflow: scroll;
+  border: 10px solid black;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars.html
new file mode 100644
index 0000000..5fe84aaa
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-and-scrollbars.html
@@ -0,0 +1,42 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  overflow: scroll;
+  border: 10px solid black;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-expected.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-expected.html
new file mode 100644
index 0000000..37112ec
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-expected.html
@@ -0,0 +1,24 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  visibility: hidden;
+  border: 10px solid black;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content-expected.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content-expected.html
new file mode 100644
index 0000000..c8f3cab
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content-expected.html
@@ -0,0 +1,24 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: min-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  visibility: hidden;
+  border: 10px solid black;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content.html
new file mode 100644
index 0000000..b01edda
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border-min-content.html
@@ -0,0 +1,41 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: min-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  border: 10px solid black;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border.html
new file mode 100644
index 0000000..a61afa5
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-border.html
@@ -0,0 +1,41 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  border: 10px solid black;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-expected.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-expected.html
new file mode 100644
index 0000000..fd3180b
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-expected.html
@@ -0,0 +1,22 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars-expected.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars-expected.html
new file mode 100644
index 0000000..f48402a5
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars-expected.html
@@ -0,0 +1,24 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  visibility: hidden;
+  overflow: scroll;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars.html
new file mode 100644
index 0000000..a05eca8
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size-scrollbars.html
@@ -0,0 +1,41 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  overflow: scroll;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size.html b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size.html
new file mode 100644
index 0000000..1ced6176
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/acquire-size-used-when-auto-size.html
@@ -0,0 +1,40 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-expected.html
new file mode 100644
index 0000000..b353867
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-expected.html
@@ -0,0 +1,32 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow-expected.html
new file mode 100644
index 0000000..f8123f1
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow-expected.html
@@ -0,0 +1,34 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  flex-grow: 3;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow.html
new file mode 100644
index 0000000..8f282e4
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal-with-grow.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  flex-grow: 3;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal.html
new file mode 100644
index 0000000..86181217
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-horizontal.html
@@ -0,0 +1,46 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-expected.html
new file mode 100644
index 0000000..5c35a431
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-expected.html
@@ -0,0 +1,32 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow-expected.html
new file mode 100644
index 0000000..2dc267a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow-expected.html
@@ -0,0 +1,34 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  flex-grow: 3;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow.html
new file mode 100644
index 0000000..3e3bc053
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical-with-grow.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  flex-grow: 3;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical.html b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical.html
new file mode 100644
index 0000000..cd11d40
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-column-vertical.html
@@ -0,0 +1,46 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-expected.html
new file mode 100644
index 0000000..5a08b6bd6
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-expected.html
@@ -0,0 +1,32 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow-expected.html
new file mode 100644
index 0000000..1a2cdcb1
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow-expected.html
@@ -0,0 +1,34 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  flex-grow: 3;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow.html
new file mode 100644
index 0000000..53554dd8
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal-with-grow.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  flex-grow: 3;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal.html
new file mode 100644
index 0000000..d4fce2d
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-horizontal.html
@@ -0,0 +1,46 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: horizontal-tb;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-expected.html
new file mode 100644
index 0000000..a8f9f707
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-expected.html
@@ -0,0 +1,32 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow-expected.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow-expected.html
new file mode 100644
index 0000000..425ae927
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow-expected.html
@@ -0,0 +1,34 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  flex-grow: 3;
+}
+#child {
+  width: 12px;
+  height: 34px;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"><div id="child"></div></div>
+  <div class="item"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow.html
new file mode 100644
index 0000000..515ab3a5
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical-with-grow.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  flex-grow: 3;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+  flex-grow: 1;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical.html b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical.html
new file mode 100644
index 0000000..6eddd2b
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/flex-row-vertical.html
@@ -0,0 +1,46 @@
+<!doctype HTML>
+
+<style>
+#flexer {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-around;
+  width: 200px;
+  height: 200px;
+  background: lightgreen;
+  writing-mode: vertical-rl;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+}
+.item {
+  width: 50px;
+  height: 60px;
+  background: blue;
+}
+</style>
+
+<div id="flexer">
+  <div class="item"></div>
+  <div id="container"></div>
+  <div class="item"></div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/float-left-expected.html b/third_party/blink/web_tests/display-lock/sizing/float-left-expected.html
new file mode 100644
index 0000000..f82ffeeb
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/float-left-expected.html
@@ -0,0 +1,24 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  float: left;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+  This is some text.
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/float-left.html b/third_party/blink/web_tests/display-lock/sizing/float-left.html
new file mode 100644
index 0000000..6371794
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/float-left.html
@@ -0,0 +1,42 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  float: left;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+  This is some text.
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/layout-replaced-expected.html b/third_party/blink/web_tests/display-lock/sizing/layout-replaced-expected.html
new file mode 100644
index 0000000..aa30f9a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/layout-replaced-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#border {
+  border: 1px solid blue;
+  width: max-content;
+}
+img {
+  contain: style layout;
+  width: 12px;
+  height: 34px;
+  visibility: hidden;
+}
+</style>
+
+<div id="border">
+  <img src="../../images/blue-100.png">
+</div>
diff --git a/third_party/blink/web_tests/display-lock/sizing/layout-replaced.html b/third_party/blink/web_tests/display-lock/sizing/layout-replaced.html
new file mode 100644
index 0000000..d1da5f7
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/layout-replaced.html
@@ -0,0 +1,33 @@
+<!doctype HTML>
+
+<style>
+#border {
+  border: 1px solid blue;
+  width: max-content;
+}
+img {
+  contain: style layout;
+}
+</style>
+
+<div id="border">
+  <img id="element" src="../../images/blue-100.png">
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let element = document.getElementById("element");
+  element.displayLock.acquire({ timeout: Infinity, size: [12, 34] }).then(finishTest);
+}
+
+window.onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored-expected.html b/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored-expected.html
new file mode 100644
index 0000000..fd3180b
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored-expected.html
@@ -0,0 +1,22 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored.html b/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored.html
new file mode 100644
index 0000000..9f1de2a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/max-content-size-ignored.html
@@ -0,0 +1,41 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  width: max-content;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/min-width-respected-expected.html b/third_party/blink/web_tests/display-lock/sizing/min-width-respected-expected.html
new file mode 100644
index 0000000..747259f8
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/min-width-respected-expected.html
@@ -0,0 +1,23 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  width: 157px;
+}
+#sizer {
+  width: 123px;
+  height: 456px;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="sizer"></div>
+  </div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/min-width-respected.html b/third_party/blink/web_tests/display-lock/sizing/min-width-respected.html
new file mode 100644
index 0000000..041479c
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/min-width-respected.html
@@ -0,0 +1,41 @@
+<!doctype HTML>
+
+<style>
+#border {
+  width: max-content;
+  border: 1px solid green;
+}
+#container {
+  contain: style layout;
+  background: lightblue;
+  min-width: 157px;
+}
+#child {
+  width: 500px;
+  height: 500px;
+  background: red;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div id="child"></div>
+  </div>
+</div>
+
+<script>
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity, size: [123, 456] }).then(finishTest);
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow-expected.html b/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow-expected.html
new file mode 100644
index 0000000..21b212b
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+#border {
+  border: 1px solid black;
+  width: max-content;
+}
+#container {
+  contain: style layout;
+  width: 12px;
+  height: 100px;
+}
+</style>
+
+<div id="border">
+  <div id="container"></div>
+</div>
diff --git a/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow.html b/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow.html
new file mode 100644
index 0000000..3d216ff
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/overflow-auto-with-overflow.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<style>
+#border {
+  border: 1px solid black;
+  width: max-content;
+}
+#container {
+  contain: style layout;
+  height: 100px;
+  overflow: auto;
+}
+.content {
+  width: 50px;
+  height: 50px;
+  margin: 5px;
+  background: pink;
+}
+</style>
+
+<div id="border">
+  <div id="container">
+    <div class="content"></div>
+    <div class="content"></div>
+    <div class="content"></div>
+    <div class="content"></div>
+  </div>
+</div>
+
+<script>
+
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  await document.getElementById("container").displayLock.acquire(
+    { timeout: Infinity, size: [12, 34] }
+  );
+  finishTest();
+}
+
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes-expected.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes-expected.html
new file mode 100644
index 0000000..2ca5e8f0
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+.sized {
+  width: 12px;
+  height: 34px;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+  visibility: hidden;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append-expected.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append-expected.html
new file mode 100644
index 0000000..2ca5e8f0
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+.sized {
+  width: 12px;
+  height: 34px;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+  visibility: hidden;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append.html
new file mode 100644
index 0000000..b4f36199
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes-inherited-after-append.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<style>
+.verticalrl {
+  writing-mode: vertical-rl;
+}
+.verticallr {
+  writing-mode: vertical-lr;
+}
+.horizontaltb {
+  writing-mode: horizontal-tb;
+}
+.sized {
+  width: 100px;
+  height: 200px;
+}
+.box {
+  background: lightblue;
+  contain: style layout;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<template id="template">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</template>
+
+<div class="border verticalrl"></div>
+<div class="border verticalrl"></div>
+<div class="border verticallr"></div>
+<div class="border horizontaltb"></div>
+<div class="border horizontaltb"></div>
+
+<script>
+
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let items = document.getElementsByClassName("border");
+  let template_element = document.importNode(
+    document.getElementById("template").content, true).firstElementChild;
+
+  let promises = []
+  for (let i = 0; i < items.length; ++i) {
+    let clone = template_element.cloneNode(true);
+    promises.push(clone.displayLock.acquire({ timeout: Infinity, size: [12, 34] }));
+    items[i].appendChild(clone);
+  }
+  await Promise.all(promises);
+  finishTest();
+}
+
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch-expected.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch-expected.html
new file mode 100644
index 0000000..2ca5e8f0
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+.sized {
+  width: 12px;
+  height: 34px;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+  visibility: hidden;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+<div class="border">
+    <div class="sized"></div>
+</div>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch.html
new file mode 100644
index 0000000..76f58ea
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes-switch.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<style>
+.verticalrl {
+  writing-mode: vertical-rl;
+}
+.verticallr {
+  writing-mode: vertical-lr;
+}
+.horizontaltb {
+  writing-mode: horizontal-tb;
+}
+.sized {
+  width: 100px;
+  height: 200px;
+}
+.box {
+  background: lightblue;
+  contain: style layout;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<div class="border verticalrl">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border verticalrl">
+  <div class="box horizontaltb">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border verticallr">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border horizontaltb">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border horizontaltb">
+  <div class="box verticalrl">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+
+<script>
+
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let items = document.getElementsByClassName("box");
+  let promises = []
+  for (let i = 0; i < items.length; ++i) {
+    promises.push(items[i].displayLock.acquire({ timeout: Infinity, size: [12, 34] }));
+  }
+  await Promise.all(promises);
+
+  let borders = document.getElementsByClassName("border");
+  for (let i = 0; i < borders.length; ++i) {
+    if (borders[i].classList.contains("horizontaltb")) {
+      borders[i].classList.replace("horizontaltb", "verticalrl");
+    } else {
+      borders[i].classList.replace("verticalrl", "horizontaltb");
+      borders[i].classList.replace("verticallr", "horizontaltb");
+    }
+  }
+
+  requestAnimationFrame(finishTest);
+}
+
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/third_party/blink/web_tests/display-lock/sizing/writing-modes.html b/third_party/blink/web_tests/display-lock/sizing/writing-modes.html
new file mode 100644
index 0000000..c175ffa
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/sizing/writing-modes.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<style>
+.verticalrl {
+  writing-mode: vertical-rl;
+}
+.verticallr {
+  writing-mode: vertical-lr;
+}
+.horizontaltb {
+  writing-mode: horizontal-tb;
+}
+.sized {
+  width: 100px;
+  height: 200px;
+}
+.box {
+  background: lightblue;
+  contain: style layout;
+  border-style: solid;
+  border-width: 1px 2px 3px 4px;
+  padding: 5px 6px 7px 8px;
+}
+.border {
+  border: 1px solid black;
+  width: max-content;
+  margin: 5px;
+}
+</style>
+
+<div class="border verticalrl">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border verticalrl">
+  <div class="box horizontaltb">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border verticallr">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border horizontaltb">
+  <div class="box">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+<div class="border horizontaltb">
+  <div class="box verticalrl">
+    <div class="sized">hello<br>world</div>
+  </div>
+</div>
+
+<script>
+
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest() {
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let items = document.getElementsByClassName("box");
+  let promises = []
+  for (let i = 0; i < items.length; ++i) {
+    promises.push(items[i].displayLock.acquire({ timeout: Infinity, size: [12, 34] }));
+  }
+  await Promise.all(promises);
+  finishTest();
+}
+
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index f8029f24..04d89a81 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -3961,6 +3961,240 @@
      {}
     ]
    ],
+   "css/css-writing-modes/writing-mode-vlr-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-002-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-003-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-003-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-005-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-005-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-006-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-006-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-007-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-007-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-008-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-008-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-009-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-009-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-010-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-010-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-012-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-012-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-014-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-014-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-015-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-015-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-002-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-003-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-003-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-004-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-004-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-005-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-005-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-forms-006-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-forms-006-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-table-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-table-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vlr-table-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vlr-table-002-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-002-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-003-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-003-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-005-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-005-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-007-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-007-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-008-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-008-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-009-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-009-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-010-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-010-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-012-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-012-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-014-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-014-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-015-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-015-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-002-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-003-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-003-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-004-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-004-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-005-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-005-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-forms-006-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-forms-006-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-table-001-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-table-001-manual.html",
+     {}
+    ]
+   ],
+   "css/css-writing-modes/writing-mode-vrl-table-002-manual.html": [
+    [
+     "css/css-writing-modes/writing-mode-vrl-table-002-manual.html",
+     {}
+    ]
+   ],
    "css/selectors/focus-visible-001-manual.html": [
     [
      "css/selectors/focus-visible-001-manual.html",
@@ -6283,6 +6517,36 @@
      {}
     ]
    ],
+   "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html": [
+    [
+     "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html",
+     {}
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html": [
+    [
+     "pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html",
+     {}
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html": [
+    [
+     "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html",
+     {}
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html": [
+    [
+     "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html",
+     {}
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html": [
+    [
+     "pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html",
+     {}
+    ]
+   ],
    "pointerevents/pointerevent_touch-action-keyboard-manual.html": [
     [
      "pointerevents/pointerevent_touch-action-keyboard-manual.html",
@@ -6295,30 +6559,6 @@
      {}
     ]
    ],
-   "pointerevents/pointerevent_touch-action-none-css_touch-manual.html": [
-    [
-     "pointerevents/pointerevent_touch-action-none-css_touch-manual.html",
-     {}
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html": [
-    [
-     "pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html",
-     {}
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html": [
-    [
-     "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html",
-     {}
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html": [
-    [
-     "pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html",
-     {}
-    ]
-   ],
    "pointerevents/pointerevent_touch-action-rotated-divs_touch-manual.html": [
     [
      "pointerevents/pointerevent_touch-action-rotated-divs_touch-manual.html",
@@ -40873,6 +41113,18 @@
      {}
     ]
    ],
+   "css/css-flexbox/align-items-007.html": [
+    [
+     "css/css-flexbox/align-items-007.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-flexbox/align-items-baseline-overflow-non-visible.html": [
     [
      "css/css-flexbox/align-items-baseline-overflow-non-visible.html",
@@ -110929,6 +111181,18 @@
      {}
     ]
    ],
+   "mathml/relations/css-styling/dynamic-dir-1.html": [
+    [
+     "mathml/relations/css-styling/dynamic-dir-1.html",
+     [
+      [
+       "/mathml/relations/css-styling/dynamic-dir-1-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "mathml/relations/css-styling/lengths-1.html": [
     [
      "mathml/relations/css-styling/lengths-1.html",
@@ -131945,11 +132209,6 @@
      {}
     ]
    ],
-   "css/css-contain/parsing/contain-computed-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/css-contain/reference/contain-baseline-ref.html": [
     [
      {}
@@ -158710,6 +158969,11 @@
      {}
     ]
    ],
+   "css/support/red-rect.svg": [
+    [
+     {}
+    ]
+   ],
    "css/support/red.ico": [
     [
      {}
@@ -175615,11 +175879,6 @@
      {}
     ]
    ],
-   "html/semantics/embedded-content/the-iframe-element/src-repeated-in-ancestor-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/semantics/embedded-content/the-iframe-element/stash.py": [
     [
      {}
@@ -178420,6 +178679,11 @@
      {}
     ]
    ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/document.open-03-frame.html": [
     [
      {}
@@ -178550,6 +178814,11 @@
      {}
     ]
    ],
+   "html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/webappapis/scripting/events/contains.json": [
     [
      {}
@@ -180560,6 +180829,11 @@
      {}
     ]
    ],
+   "mathml/relations/css-styling/dynamic-dir-1-ref.html": [
+    [
+     {}
+    ]
+   ],
    "mathml/relations/css-styling/lengths-1-ref.html": [
     [
      {}
@@ -226427,7 +226701,9 @@
    "cookies/samesite/fetch.html": [
     [
      "cookies/samesite/fetch.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/form-get-blank-reload.html": [
@@ -226439,7 +226715,9 @@
    "cookies/samesite/form-get-blank.html": [
     [
      "cookies/samesite/form-get-blank.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/form-post-blank-reload.html": [
@@ -226451,25 +226729,33 @@
    "cookies/samesite/form-post-blank.html": [
     [
      "cookies/samesite/form-post-blank.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/iframe-reload.html": [
     [
      "cookies/samesite/iframe-reload.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/iframe.html": [
     [
      "cookies/samesite/iframe.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/img.html": [
     [
      "cookies/samesite/img.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "cookies/samesite/setcookie-lax.html": [
@@ -232259,6 +232545,12 @@
      {}
     ]
    ],
+   "css/css-position/position-absolute-crash-chrome-007.html": [
+    [
+     "css/css-position/position-absolute-crash-chrome-007.html",
+     {}
+    ]
+   ],
    "css/css-position/position-absolute-dynamic-containing-block.html": [
     [
      "css/css-position/position-absolute-dynamic-containing-block.html",
@@ -290103,38 +290395,6 @@
      {}
     ]
    ],
-   "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html": [
-    [
-     "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html",
-     {
-      "testdriver": true
-     }
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-inherit_child-none_touch.html": [
-    [
-     "pointerevents/pointerevent_touch-action-inherit_child-none_touch.html",
-     {
-      "testdriver": true
-     }
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html": [
-    [
-     "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html",
-     {
-      "testdriver": true
-     }
-    ]
-   ],
-   "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html": [
-    [
-     "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html",
-     {
-      "testdriver": true
-     }
-    ]
-   ],
    "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html": [
     [
      "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html",
@@ -290143,9 +290403,25 @@
      }
     ]
    ],
-   "pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html": [
+   "pointerevents/pointerevent_touch-action-none-css_touch.html": [
     [
-     "pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html",
+     "pointerevents/pointerevent_touch-action-none-css_touch.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-pan-x-css_touch.html": [
+    [
+     "pointerevents/pointerevent_touch-action-pan-x-css_touch.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html": [
+    [
+     "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html",
      {
       "testdriver": true
      }
@@ -290159,6 +290435,15 @@
      }
     ]
    ],
+   "pointerevents/pointerevent_touch-action-pan-y-css_touch.html": [
+    [
+     "pointerevents/pointerevent_touch-action-pan-y-css_touch.html",
+     {
+      "testdriver": true,
+      "timeout": "long"
+     }
+    ]
+   ],
    "pointerevents/pointerevent_touch-action-verification.html": [
     [
      "pointerevents/pointerevent_touch-action-verification.html",
@@ -323499,12 +323784,6 @@
      {}
     ]
    ],
-   "webxr/xrSession_mode.https.html": [
-    [
-     "webxr/xrSession_mode.https.html",
-     {}
-    ]
-   ],
    "webxr/xrSession_prevent_multiple_exclusive.https.html": [
     [
      "webxr/xrSession_prevent_multiple_exclusive.https.html",
@@ -350151,7 +350430,7 @@
    "support"
   ],
   "cookies/samesite/fetch.html": [
-   "734462a3c539811ccd4f92f9ff50840dd0378ad5",
+   "3a2d5bf64c5c685005a6a8d86e40e5ef2e95a5a1",
    "testharness"
   ],
   "cookies/samesite/form-get-blank-reload.html": [
@@ -350159,7 +350438,7 @@
    "testharness"
   ],
   "cookies/samesite/form-get-blank.html": [
-   "a86f34b0fb4a6946be4863e73f371e40cb4829dc",
+   "b7351702b800be327348a833454cd503c57aea37",
    "testharness"
   ],
   "cookies/samesite/form-post-blank-reload.html": [
@@ -350167,19 +350446,19 @@
    "testharness"
   ],
   "cookies/samesite/form-post-blank.html": [
-   "115c6a157a00f679521f5d2b15349ecb6ea130f2",
+   "f2bb0cacfbcb1d86c83967f22849ba7d677721c8",
    "testharness"
   ],
   "cookies/samesite/iframe-reload.html": [
-   "759fc7b03c3c861b65f4b7e0f6794305f67f7043",
+   "c4c3598ca44602a455f2ff6b8b29e5a421913c5e",
    "testharness"
   ],
   "cookies/samesite/iframe.html": [
-   "38a7701bf8a8f189b3d2ad606f277a3f05f374ef",
+   "e511128f9633c145cd2c2c5c94d716132d460209",
    "testharness"
   ],
   "cookies/samesite/img.html": [
-   "b1b04340b796ec93ef26d178678ddc745d43e988",
+   "bca84cbd28b8d19edd221496ad83329813e0db30",
    "testharness"
   ],
   "cookies/samesite/resources/puppet.html": [
@@ -371222,10 +371501,6 @@
    "07378a29f39db8bdf100aa04c60cb23f556d962b",
    "testharness"
   ],
-  "css/css-contain/parsing/contain-computed-expected.txt": [
-   "4b2f1cf60e1f144507858ef549aa5e0d803565e5",
-   "support"
-  ],
   "css/css-contain/parsing/contain-computed.html": [
    "18720b74195fed58c7f3cb5d9f2edf7298f305be",
    "testharness"
@@ -372222,6 +372497,10 @@
    "f20c8969c4b3d988bb961290a219720ce6e4c848",
    "reftest"
   ],
+  "css/css-flexbox/align-items-007.html": [
+   "01e8f001a8a39c8726cf9a9453dfad07d0e1b83a",
+   "reftest"
+  ],
   "css/css-flexbox/align-items-baseline-overflow-non-visible.html": [
    "3c91bc5553084018b2c16cbeb6721077c8db54e2",
    "reftest"
@@ -390842,6 +391121,10 @@
    "94b2469b0e692f00c281d02dfbceb59c0a04d5e4",
    "testharness"
   ],
+  "css/css-position/position-absolute-crash-chrome-007.html": [
+   "9c24210c2570224f6a1812b84148c4ca468a4473",
+   "testharness"
+  ],
   "css/css-position/position-absolute-dynamic-containing-block.html": [
    "3968f685849663574ca213fcb90dc5fb3eaffaa3",
    "testharness"
@@ -419190,6 +419473,162 @@
    "cd844132decf8a19c81b9e865b9ef8903b5e8eb5",
    "reftest"
   ],
+  "css/css-writing-modes/writing-mode-vlr-001-manual.html": [
+   "31186029deca3cdd7df91757e70d21deaaccba7d",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-002-manual.html": [
+   "bb53c939e843f60dfbda6e5b9c03b5aedf139555",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-003-manual.html": [
+   "1aaf29d2e6d0972c12a0feda5dd7171647e7cc4f",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-005-manual.html": [
+   "2bbdca599981e261db590ddcedfa645a6aa595f2",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-006-manual.html": [
+   "0ceb4a74bb9274480abe71f21b1920d00003d207",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-007-manual.html": [
+   "8317c5c8efd7e607ff4b780acc77f80c3a2840af",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-008-manual.html": [
+   "21abffa9194d3354e2411fe0d8caa9528c3b3541",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-009-manual.html": [
+   "ba2ca64828febf295b50bc05f0d7082d347274c2",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-010-manual.html": [
+   "4dc9430b8dada1c35601db40cb4408aad4d37af6",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-012-manual.html": [
+   "ebf773c555984bc7bf30ffdba61b8f3cd03a4d4d",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-014-manual.html": [
+   "656f78759db28d73d8881d1034ff7054dfe9bf35",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-015-manual.html": [
+   "a8fe0055395c9a87275764f984a442805e6c99ab",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-001-manual.html": [
+   "02e0dd8da0d6bde7590fb020a82f3f8ceaa7dc30",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-002-manual.html": [
+   "b89ea1addb3433047cc580106abcb24e3cff77f4",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-003-manual.html": [
+   "bfd90f8438f16c07791371d66de8cbf49d62a0df",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-004-manual.html": [
+   "fd44a2b6ed7bb48b0bffb2f6b33aa9a046e61cc2",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-005-manual.html": [
+   "0ef619a636f67e5abdbeb238c37ee0adb00c6005",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-forms-006-manual.html": [
+   "16162c2a3cd5d59fd4bae18e7239496149e077de",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-table-001-manual.html": [
+   "21bd590863b99eb1f429e1751c3bcc9b0ec603a8",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vlr-table-002-manual.html": [
+   "3a41d1fa60463adafa2088a7b3f08d3f946aaf3a",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-001-manual.html": [
+   "a4f995f4b7fec16670e57afd8d403957fb77c532",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-002-manual.html": [
+   "7c7bcfbcdc6c58f45d9928d84d6ab8cd3bcae893",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-003-manual.html": [
+   "64fcb66b1337b781281251a468968b6dc6b2e990",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-005-manual.html": [
+   "c6462f2fe1aa97b6bffd04f96934171d3f281bb8",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-007-manual.html": [
+   "3427f74990cddc722d6c5bc2766491552a568101",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-008-manual.html": [
+   "7d2a3bb6a7be1a46219fe41afbc233b329cf1e2d",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-009-manual.html": [
+   "6dff8d7efbe124be239816b41d96ca4f4889dc3a",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-010-manual.html": [
+   "e81a579c75a7c1034fc6dc46a575ef91d3c99e52",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-012-manual.html": [
+   "a53ec5c14f4ad12307281379f8bb695ed842c01d",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-014-manual.html": [
+   "bf3424fd04313a38c411061daad8bf0db0c86376",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-015-manual.html": [
+   "cfcdf2f51b7b07742350f49a71d88509e6ddc5f8",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-001-manual.html": [
+   "0548cb968286eff448017e243b0eed651ad6cfad",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-002-manual.html": [
+   "3de4c72c3ff4b07865cbf5538902053351b66e58",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-003-manual.html": [
+   "e07502e4fce16bf3c5bb8e4755cd3cae9f285662",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-004-manual.html": [
+   "42bef3494f963bb0bd40400a4fe7e19a01ea9ca5",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-005-manual.html": [
+   "7177c316d7128f1653953428d60f5cb2e6661676",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-forms-006-manual.html": [
+   "2ed6bc9982846ea4313ded2d54cc35a630e69eb2",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-table-001-manual.html": [
+   "1705beb791531eea974e77125e8aaae363570f91",
+   "manual"
+  ],
+  "css/css-writing-modes/writing-mode-vrl-table-002-manual.html": [
+   "0f1c1d19977cd65fbb7a0ea450d9a582d380f4d6",
+   "manual"
+  ],
   "css/cssom-view/CaretPosition-001.html": [
    "d8e97a92342cb8ba7e7a185132849ae60485c329",
    "testharness"
@@ -423982,6 +424421,10 @@
    "8b4b25364e0ffbe09e563e13b567fa57330e48d5",
    "support"
   ],
+  "css/support/red-rect.svg": [
+   "3fe10a2b6fd33ad9da17729964dd6bf965474912",
+   "support"
+  ],
   "css/support/red.ico": [
    "22a7b36fe3ec2c05c348ba7b45c9fb764ef2def5",
    "support"
@@ -451010,10 +451453,6 @@
    "4e6293949a0d9a799e6b3bb627fa181e29fe0b2c",
    "testharness"
   ],
-  "html/semantics/embedded-content/the-iframe-element/src-repeated-in-ancestor-expected.txt": [
-   "e97bed397e8d45b2aa670e402abc9f5005122d81",
-   "support"
-  ],
   "html/semantics/embedded-content/the-iframe-element/src-repeated-in-ancestor.html": [
    "2f77dfe164df3737cbbabf4efce6e28028e62537",
    "testharness"
@@ -457282,6 +457721,10 @@
    "3558397410edea6eaa9e73fa6d0293cc7e4d48ba",
    "testharness"
   ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt": [
+   "2a74109857ba157e77b3ed3f1c6da5d5de557ccc",
+   "support"
+  ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js": [
    "6b80ecacf8f640ff94209dbd915049e261214eac",
    "testharness"
@@ -457538,6 +457981,10 @@
    "ed6c006651162aeaac41a4ad7a8e81ad0bbd457e",
    "testharness"
   ],
+  "html/webappapis/scripting/events/compile-event-handler-settings-objects-expected.txt": [
+   "27f6821050a1dd0d2429946fbb8b3412d1870e01",
+   "support"
+  ],
   "html/webappapis/scripting/events/compile-event-handler-settings-objects.html": [
    "29ac9b8ced469025278b5d5215b651b58a6f5a4d",
    "testharness"
@@ -458879,11 +459326,11 @@
    "reftest"
   ],
   "infrastructure/reftest/reftest_fuzzy_no_differences.html": [
-   "324873a8ccf70bed77a328a75ae8e2de08d1ba32",
+   "95863904aac993ca569e3d574737117962c1c4d2",
    "reftest"
   ],
   "infrastructure/reftest/reftest_fuzzy_no_differences_1.html": [
-   "6bf85ceebedc63c0cefc7dce044739c46a08f350",
+   "9513f9bda82d0c40fe2b86a415d073e9863bf504",
    "reftest"
   ],
   "infrastructure/reftest/reftest_match.html": [
@@ -460099,7 +460546,7 @@
    "reftest"
   ],
   "lint.whitelist": [
-   "a7a4600d9cdceb5df65422ca08404d44df7c9989",
+   "f6411453345c249a4378709631569710a70945d2",
    "support"
   ],
   "loading/preloader-css-import-no-quote.tentative.html": [
@@ -460542,6 +460989,14 @@
    "ddb2173a2e01ff78b16bc9c86f4a0f2ad37935dc",
    "testharness"
   ],
+  "mathml/relations/css-styling/dynamic-dir-1-ref.html": [
+   "111ea79e243a83880783b5ab46ae6d989ead1f32",
+   "support"
+  ],
+  "mathml/relations/css-styling/dynamic-dir-1.html": [
+   "c4c99d878c19305d02d0ed450e46da66802c0746",
+   "reftest"
+  ],
   "mathml/relations/css-styling/lengths-1-ref.html": [
    "9fca6f49632ca080ee1b2a32a9ce2d251241dfcc",
    "support"
@@ -473119,7 +473574,7 @@
    "support"
   ],
   "pointerevents/pointerevent_support.js": [
-   "dc35ea24eebc65dd3b0fe52dd54042c78959bd1d",
+   "e8c847b12a880a557d8d3cd69bc0bc77cf3378af",
    "support"
   ],
   "pointerevents/pointerevent_suppress_compat_events_on_click.html": [
@@ -473142,29 +473597,29 @@
    "5fe6179840eeda9a025e951f8ff28b211da9fafe",
    "testharness"
   ],
-  "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html": [
-   "ae2373c3f532fdada27c941617f8d05d0d2a7da3",
-   "testharness"
+  "pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html": [
+   "dcea2837502b82b3fc873ddf3a4b044e38165c02",
+   "manual"
   ],
-  "pointerevents/pointerevent_touch-action-inherit_child-none_touch.html": [
-   "81f0ea6050a4b060708bcebc1eeb65d7ee904c70",
-   "testharness"
+  "pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html": [
+   "16e42954e51abc58c89e608c0edfa29d9a44b63b",
+   "manual"
   ],
-  "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html": [
-   "775708d4a7741d053ea20472d94bf4f936175804",
-   "testharness"
+  "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html": [
+   "c75d067e447f7382005542df6ed267850ef6aa0a",
+   "manual"
   ],
-  "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html": [
-   "592cfd6ae5367d2830ce3343aae7cae0e1d737a0",
-   "testharness"
+  "pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html": [
+   "d420cc56c77b6910ee96d875ee24eb0b9b0a4c71",
+   "manual"
   ],
   "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html": [
    "a1fefe16982316546b2cb0a7bf14362fe21f7145",
    "testharness"
   ],
-  "pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html": [
-   "45ea1432b4e4ad5de824bf1d1798e458a939dbc7",
-   "testharness"
+  "pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html": [
+   "5e674a14da550fb63bfe53859a8e4db529f559e8",
+   "manual"
   ],
   "pointerevents/pointerevent_touch-action-keyboard-manual.html": [
    "a41d7078f2ee87a8a5686379536aaf1e0de915df",
@@ -473174,25 +473629,25 @@
    "fcc8584515c51d60bb01092ffe1f701273c7bb58",
    "manual"
   ],
-  "pointerevents/pointerevent_touch-action-none-css_touch-manual.html": [
-   "dec694f3eca9dbfe35483d0783d716f42a0d7443",
-   "manual"
+  "pointerevents/pointerevent_touch-action-none-css_touch.html": [
+   "cc9602442acb8f4267c2c4d0bf63097d9992b3e3",
+   "testharness"
   ],
-  "pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html": [
-   "e757baec6be427884d6270234f4c73e3ddb959b5",
-   "manual"
+  "pointerevents/pointerevent_touch-action-pan-x-css_touch.html": [
+   "a91f1f55d101ba27d72636743ab8311270ebbba9",
+   "testharness"
   ],
-  "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html": [
-   "e2a4386b27abcd29be0563a8537653bec0206ccd",
-   "manual"
+  "pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html": [
+   "d056eb9b0e5924561f2902424827aa1edac435fc",
+   "testharness"
   ],
   "pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html": [
    "0c88054379538b4287c9157124f68b9cbff82234",
    "testharness"
   ],
-  "pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html": [
-   "44f89b8eb774f6aa8d4c6e3722508b63f42271fb",
-   "manual"
+  "pointerevents/pointerevent_touch-action-pan-y-css_touch.html": [
+   "98168755a684e00595909e428b5a95b22c4b219c",
+   "testharness"
   ],
   "pointerevents/pointerevent_touch-action-rotated-divs_touch-manual.html": [
    "1c09b15f1f99eead72a0689ab14a4facb1c61e3f",
@@ -492015,7 +492470,7 @@
    "support"
   ],
   "tools/gitignore/gitignore.py": [
-   "9b661308ab179d48bc0fc946d078ef995225d572",
+   "901a1f418ba1d9f5d378bd38d0403b8adc1d798c",
    "support"
   ],
   "tools/lint/__init__.py": [
@@ -492035,7 +492490,7 @@
    "support"
   ],
   "tools/lint/rules.py": [
-   "76d5d3e99264de999e999086436c8b524c62a297",
+   "94aff6430ed4a3bcde2704585f49ae21da85281b",
    "support"
   ],
   "tools/localpaths.py": [
@@ -492071,7 +492526,7 @@
    "support"
   ],
   "tools/manifest/manifest.py": [
-   "5dde9374642381c42527289addf8d7687b08a245",
+   "b521040016843138f33120d46fa5556e53b6457c",
    "support"
   ],
   "tools/manifest/sourcefile.py": [
@@ -492391,7 +492846,7 @@
    "support"
   ],
   "tools/runner/index.html": [
-   "2d7d25297ca2977465eed49585c9661283684c38",
+   "57940d02d0c32b366c407abec10a7d70d440d60d",
    "support"
   ],
   "tools/runner/report.css": [
@@ -499503,7 +499958,7 @@
    "support"
   ],
   "web-share/META.yml": [
-   "1197ab9f237637f15aedd9152a615c1776c2f2c3",
+   "e054ccc8ec34058cc749a04cb3f06c0a72368f76",
    "support"
   ],
   "web-share/OWNERS": [
@@ -507427,7 +507882,7 @@
    "support"
   ],
   "webxr/idlharness.https.window-expected.txt": [
-   "eba2b00b71381d5316529254118de0e1bc950c39",
+   "285b97cfec23480155c80bfaf8ca0d14387d259f",
    "support"
   ],
   "webxr/idlharness.https.window.js": [
@@ -507550,10 +508005,6 @@
    "07abc39728c0453668a4fbdc785a9194a2dfb7a0",
    "testharness"
   ],
-  "webxr/xrSession_mode.https.html": [
-   "a1d066084393742559a020cb6e71277740793db7",
-   "testharness"
-  ],
   "webxr/xrSession_prevent_multiple_exclusive.https.html": [
    "e61bd392718ae3b0f8ac8de0fa81604f2d32dcce",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-001-manual.html
new file mode 100644
index 0000000..3118602
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-001-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, vertical lines</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display a line of text vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if you see a tall, thin orange rectangle.</p>
+<div class="test">
+<span lang="mn">ᠮᠤᠩᠭᠤᠯ ᠤᠯᠤᠰ</span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-002-manual.html
new file mode 100644
index 0000000..bb53c93
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-002-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, line wrap</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will wrap lines from left to right."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test { font-family: webfont, serif; font-size: 24px; height: 250px; width: 250px; }
+.test span { background-color:orange; color:orange;  }
+.test span#end { background-color:blue; color:blue;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the blue rectangle is on the right-most side.</p>
+<div class="test">
+<span lang="mn">ᠴᠤᠢᠵᠤᠩᠵᠠᠪ ᠪᠠᠭᠰᠢ ᠶᠢᠨ <span id="end">ᠦᠭᠦᠯᠡᠯ</span></span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-003-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-003-manual.html
new file mode 100644
index 0000000..1aaf29d2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-003-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, alignment</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will cause lines to display from the left side of the enclosing box."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test { font-family: webfont, serif; font-size: 24px; height: 250px; width: 250px; border: 1px solid orange; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the orange filled rectangle is vertical and on the left side of the square box.</p>
+<div class="test">
+<span lang="mn">ᠴᠤᠢᠵᠤᠩᠵᠠᠪ</span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-005-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-005-manual.html
new file mode 100644
index 0000000..2bbdca5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-005-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, default Mongolian orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Mongolian characters with the right orientation."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if text is vertical and the Mongolian characters are  oriented the same way as on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn-orientation.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-006-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-006-manual.html
new file mode 100644
index 0000000..0ceb4a74
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-006-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, Mongolian joining</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Mongolian characters with correct joining behaviour."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the Mongolian characters are joined as shown on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn-orientation.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-007-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-007-manual.html
new file mode 100644
index 0000000..8317c5c8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-007-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, default Latin orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Latin characters rotated 90° right."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px;  float: left; margin-right: 30px;color: #ccc; }
+span[lang=en] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the text runs vertically and the orientation of the Latin characters is the same as on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="en">W3C i18n</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn+latin.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-008-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-008-manual.html
new file mode 100644
index 0000000..21abffa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-008-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, default Arabic orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters rotated 90° right."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the orientation of the Arabic characters is the same as on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="ar">نشاط التدويل</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-009-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-009-manual.html
new file mode 100644
index 0000000..ba2ca64
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-009-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, default Arabic direction</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters progressing up the page."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the order of the Arabic characters is the same as on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="ar">نشاط التدويل</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-010-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-010-manual.html
new file mode 100644
index 0000000..4dc9430
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-010-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, Arabic joining</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters using cursive joining."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px;  color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the Arabic characters are joined up as shown on the blue background.</p>
+<div class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="ar">نشاط التدويل</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-012-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-012-manual.html
new file mode 100644
index 0000000..ebf773c5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-012-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, Latin wrapping</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will wrap Latin text across a line break such that the first word in memory is on the left."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; height: 150px; color: #ccc; }
+span[lang=en] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+<script>
+function setMargin (height) {
+	document.getElementById('test').style.height = height+'px'
+	}
+</script>
+</head>
+<body>
+<p class="instructions">Test passes if the two Latin script words are displayed in the same relative positions around the line break as on the blue background.</p>
+<p class="instructions">Use this control to set the line length, if necessary: <input type="text" value="150" style="width: 30px; text-align:right;" onChange="setMargin(this.value);"/>px</p>
+<div id="test" class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="en">W3C i18n</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn_en_wrap.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-014-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-014-manual.html
new file mode 100644
index 0000000..656f7875
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-014-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, Arabic wrapping</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will arrange Arabic text across a line break such that the first word in memory is on the left side of the line break."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; height: 150px;  color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+<script>
+function setMargin (height) {
+	document.getElementById('test').style.height = height+'px'
+	}
+</script>
+</head>
+<body>
+<p class="instructions">Test passes if the two Arabic words are displayed in the same relative positions around the line break as on the blue background.</p>
+<p class="instructions">Use this control to set the line length, if necessary: <input type="text" value="150" style="width: 30px; text-align:right;" onChange="setMargin(this.value);"/>px</p>
+<div id="test" class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <span lang="ar">نشاط التدويل</span> ᠤᠯᠤᠰ</div>
+<div class="ref"><img src="support/mn_ar_wrap.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-015-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-015-manual.html
new file mode 100644
index 0000000..a8fe005
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-015-manual.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, image orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, replaced content such as images is displayed upright."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc;  color: #ccc; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text is vertical and the world map has north at the top.</p>
+<div id="test" class="test" lang="mn">ᠮᠤᠩᠭᠤᠯ <img src="support/world.gif" alt="ref image"/> ᠤᠯᠤᠰ</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-001-manual.html
new file mode 100644
index 0000000..02e0dd8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-001-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, input type=text</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display an input field for text vertically, and with vertical text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+input { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<input type="text" value="ᠮᠤᠩᠭᠤᠯ W3C i18n ᠤᠯᠤᠰ" />
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-002-manual.html
new file mode 100644
index 0000000..b89ea1ad
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-002-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, input type=text placeholder</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display an input field for text vertically, and with vertical placeholder text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+input { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<input type="text" placeholder="ᠮᠤᠩᠭᠤᠯ W3C i18n ᠤᠯᠤᠰ" />
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-003-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-003-manual.html
new file mode 100644
index 0000000..bfd90f8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-003-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, textarea</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display a textarea field vertically, and with vertical text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+textarea { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<textarea rows="3">ᠮᠤᠩᠭᠤᠯ W3C i18n ᠤᠯᠤᠰ</textarea>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-004-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-004-manual.html
new file mode 100644
index 0000000..fd44a2b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-004-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, textarea placeholder</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display a textarea field vertically, and with vertical placeholder text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+textarea { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<textarea rows="3" placeholder="ᠮᠤᠩᠭᠤᠯ W3C i18n ᠤᠯᠤᠰ"></textarea>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-005-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-005-manual.html
new file mode 100644
index 0000000..0ef619a6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-005-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, select, selected item</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display a select box vertically, and the selected item will be displayed vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+select { font-family: webfont; font-size: 24px; }
+.test { text-align: center; vertical-align: middle; width: 100%; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the displayed selection area is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<select>
+<option value="1">ᠮᠤᠩᠭᠤᠯ item 1 ᠤᠯᠤᠰ</option>
+<option value="2">ᠮᠤᠩᠭᠤᠯ item 2 ᠤᠯᠤᠰ</option>
+<option value="3">ᠮᠤᠩᠭᠤᠯ item 3 ᠤᠯᠤᠰ</option>
+</select>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-006-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-006-manual.html
new file mode 100644
index 0000000..16162c2a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-forms-006-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, select, options</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display selection options vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+select { font-family: webfont; font-size: 24px; }
+.test { text-align: center; vertical-align: middle; width: 100%; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the selection options displayed when you click on the selector are vertical.</p>
+<div class="test">
+<select>
+<option value="1">ᠮᠤᠩᠭᠤᠯ item 1 ᠤᠯᠤᠰ</option>
+<option value="2">ᠮᠤᠩᠭᠤᠯ item 2 ᠤᠯᠤᠰ</option>
+<option value="3">ᠮᠤᠩᠭᠤᠯ item 3 ᠤᠯᠤᠰ</option>
+</select>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-001-manual.html
new file mode 100644
index 0000000..21bd590
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-001-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, vertical lines</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display a line of text vertically within a table cell."/>
+<style type="text/css">
+@font-face {
+    font-family: 'webfont';
+    src: 	url('../../fonts/noto/NotoSansMongolian-regular.woff2') format('woff2');
+    font-weight: normal;
+    font-style: normal;
+	}
+.test, .ref { font-family: webfont, serif; font-size: 14px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if you see 4 tall, thin orange rectangles.</p>
+<div class="test">
+<table><tbody>
+<tr><th><span lang="mn">ᠮᠤᠩᠭᠤᠯ</span></th><td><span lang="mn">ᠮᠤᠩᠭᠤᠯ</span></td></tr>
+<tr><th><span lang="mn">ᠮᠤᠩᠭᠤᠯ</span></th><td><span lang="mn">ᠮᠤᠩᠭᠤᠯ</span></td></tr>
+</tbody></table>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-002-manual.html
new file mode 100644
index 0000000..3a41d1f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vlr-table-002-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-lr, table cell order</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display table columns horizontally, with the top of the table on the left."/>
+<style type="text/css">
+.test { font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-lr; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the numbers increase top-to-bottom, starting on the left.</p>
+<div class="test">
+<table><tbody>
+<tr><th>1</th><th>2</th></tr>
+<tr><td>3</td><td>4</td></tr>
+</tbody></table>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-001-manual.html
new file mode 100644
index 0000000..a4f995f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-001-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, vertical lines</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display a line of text vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if you see a tall, thin orange rectangle.</p>
+<div class="test">
+<span lang="zh-hans">国际化活动万维网联盟</span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-002-manual.html
new file mode 100644
index 0000000..7c7bcfbc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-002-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, line wrap</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will wrap lines from right to left."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+.test span#end { background-color:blue; color:blue;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the blue rectangle is on the left-most side.</p>
+<div class="test">
+<span lang="zh-hans">国际化活动万维网联盟国际化活动万维<span id="end">网联盟</span></span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-003-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-003-manual.html
new file mode 100644
index 0000000..64fcb66
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-003-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, alignment</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will cause lines to display from the right side of the enclosing box."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; border: 1px solid orange; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the orange filled rectangle is vertical and on the right side of the square box.</p>
+<div class="test">
+<span lang="zh-hans">国际化活动万维网联盟</span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-005-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-005-manual.html
new file mode 100644
index 0000000..c6462f2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-005-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, default Han orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-rl will display chinese characters upright."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the text is vertical and the Chinese characters are oriented the same way as on the blue background.</p>
+<div class="test" lang="mn">国际化活动万维网联盟</div>
+<div class="ref"><img src="support/zh-orientation.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-007-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-007-manual.html
new file mode 100644
index 0000000..3427f74
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-007-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, default Latin orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-lr will display Latin characters rotated 90° right by default."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc; }
+span[lang=en] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the orientation of the Latin characters is the same as on the blue background.</p>
+<div class="test" lang="zh-hans">国际化活动<span lang="en">W3C i18n</span>万维网联盟</div>
+<div class="ref"><img src="support/zh+latin.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-008-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-008-manual.html
new file mode 100644
index 0000000..7d2a3bb6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-008-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, default Arabic orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters rotated 90° right."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the orientation of the Arabic characters is the same as on the blue background.</p>
+<div class="test" lang="zh-hans">国际化活动<span lang="ar">نشاط التدويل</span>万维网联盟</div>
+<div class="ref"><img src="support/zh+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-009-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-009-manual.html
new file mode 100644
index 0000000..6dff8d7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-009-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, default Arabic direction</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters progressing up the page."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the order of the Arabic characters is the same as on the blue background.</p>
+<div class="test" lang="zh-hans">国际化活动<span lang="ar">نشاط التدويل</span>万维网联盟</div>
+<div class="ref"><img src="support/zh+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-010-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-010-manual.html
new file mode 100644
index 0000000..e81a579
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-010-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, Arabic joining</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-lr will display Arabic characters using cursive joining."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px;  color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text runs vertically and the Arabic characters are joined up as shown on the blue background.</p>
+<div class="test" lang="zh-hans">国际化活动<span lang="ar">نشاط التدويل</span>万维网联盟</div>
+<div class="ref"><img src="support/zh+arabic.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-012-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-012-manual.html
new file mode 100644
index 0000000..a53ec5c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-012-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, Latin wrapping</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-rl will wrap Latin text across a line break such that the first word in memory is on the right."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; height: 250px; color: #ccc; }
+span[lang=en] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+<script>
+function setMargin (height) {
+	document.getElementById('test').style.height = height+'px'
+	}
+</script>
+</head>
+<body>
+<p class="instructions">Test passes if the two Latin words on the left are displayed in the same relative positions around a line break as on the blue background.</p>
+<p class="instructions">Use this control to set the line length, if necessary: <input type="text" value="250" style="width: 30px; text-align:right;" onChange="setMargin(this.value);"/>px</p>
+<div id="test" class="test" lang="zh-hans">国际化活动<span lang="en">W3C i18n</span>万维网联盟</div>
+<div class="ref"><img src="support/zh_en_wrap.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-014-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-014-manual.html
new file mode 100644
index 0000000..bf3424f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-014-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, Arabic wrapping</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, writing-mode:vertical-rl will arrange Arabic text across a line break such that the first word in memory is on the right-hand side of the line break."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; height: 200px; color: #ccc; }
+span[lang=ar] { color: black; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+<script>
+function setMargin (height) {
+	document.getElementById('test').style.height = height+'px'
+	}
+</script>
+</head>
+<body>
+<p class="instructions">Test passes if the two Arabic words are displayed in the same relative positions around the line break as on the blue background.</p>
+<p class="instructions">Use this control to set the line length, if necessary: <input type="text" value="200" style="width: 30px; text-align:right;" onChange="setMargin(this.value);"/>px</p>
+<div id="test" class="test" lang="zh-hans">国际化活动<span lang="ar">نشاط التدويل</span>万维网联盟</div>
+<div class="ref"><img src="support/zh_ar_wrap.png" alt="ref image"/></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-015-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-015-manual.html
new file mode 100644
index 0000000..cfcdf2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-015-manual.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, image orientation</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="By default, replaced content such as images is displayed upright."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test { font-family: webfont, serif; font-size: 24px; float: left; margin-right: 30px; color: #ccc;  color: #ccc; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the text is vertical and the world map has north at the top.</p>
+<div id="test" class="test" lang="zh-hans">国际化活动<img src="support/world.gif" alt="ref image"/>万维网联盟</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-001-manual.html
new file mode 100644
index 0000000..0548cb96
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-001-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, input type=text</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display an input field for text vertically, and with vertical text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+input { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<input type="text" value="国际化活动W3C i18n万维网联盟" />
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-002-manual.html
new file mode 100644
index 0000000..3de4c72c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-002-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, input type=text placeholder</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display an input field for text vertically, and with vertical placeholder text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+input { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<input type="text" placeholder="国际化活动W3C i18n万维网联盟" />
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-003-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-003-manual.html
new file mode 100644
index 0000000..e07502e4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-003-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, textarea</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display a textarea field vertically, and with vertical text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+textarea { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<textarea rows="3">国际化活动W3C i18n万维网联盟</textarea>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-004-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-004-manual.html
new file mode 100644
index 0000000..42bef34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-004-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, textarea placeholder</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display a textarea field vertically, and with vertical placeholder text inside."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+textarea { font-family: webfont; font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the input field is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<textarea rows="3" placeholder="国际化活动W3C i18n万维网联盟"></textarea>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-005-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-005-manual.html
new file mode 100644
index 0000000..7177c316
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-005-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, select, selected item</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display a select box vertically, and the selected item will be displayed vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+select { font-family: webfont; font-size: 24px; }
+.test { text-align: center; vertical-align: middle; width: 100%; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the displayed selection area is vertical and the text inside it has default vertical settings.</p>
+<div class="test">
+<select>
+<option value="1">国际化活动item1万维网联盟</option>
+<option value="2">国际化活动item2万维网联盟</option>
+<option value="3">国际化活动item3万维网联盟</option>
+</select>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-006-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-006-manual.html
new file mode 100644
index 0000000..2ed6bc9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-forms-006-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, select, options</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display selection options vertically."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+select { font-family: webfont; font-size: 24px; }
+.test { text-align: center; vertical-align: middle; width: 100%; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions">Test passes if the selection options displayed when you click on the selector are vertical.</p>
+<div class="test">
+<select>
+<option value="1">国际化活动item1万维网联盟</option>
+<option value="2">国际化活动item2万维网联盟</option>
+<option value="3">国际化活动item3万维网联盟</option>
+</select>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-001-manual.html
new file mode 100644
index 0000000..1705beb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-001-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, vertical lines</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display a line of text vertically within a table cell."/>
+<style type="text/css">
+@font-face {
+    font-family: "webfont";
+    src: url("../../fonts/mplus-1p-regular.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
+    }
+.test, .ref { font-family: webfont, serif; font-size: 14px; height: 300px; width: 300px; }
+.test span { background-color:orange; color:orange;  }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if you see 4 tall, thin orange rectangles.</p>
+<div class="test">
+<table><tbody>
+<tr><th><span lang="zh">国际化活动</span></th><td><span lang="zh">国际化活动</span></td></tr>
+<tr><th><span lang="zh">国际化活动</span></th><td><span lang="zh">国际化活动</span></td></tr>
+</tbody></table>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-002-manual.html
new file mode 100644
index 0000000..0f1c1d1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vrl-table-002-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8"/>
+<title>writing mode:vertical-rl, table cell order</title>
+<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"/>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"/>
+<meta name="assert" content="writing-mode:vertical-rl will display table columns horizontally, with the top of the table on the right."/>
+<style type="text/css">
+.test { font-size: 34px; }
+</style>
+<!-- this is the test -->
+<style type="text/css">
+.test { writing-mode: vertical-rl; }
+</style>
+</head>
+<body>
+<p class="instructions" dir="ltr">Test passes if the numbers increase top-to-bottom, starting on the right.</p>
+<div class="test">
+<table><tbody>
+<tr><th>1</th><th>2</th></tr>
+<tr><td>3</td><td>4</td></tr>
+</tbody></table>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences.html b/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences.html
index 324873a8..95863904 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences.html
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <link rel=match href=fuzzy-ref-1.html>
-<!-- This exactly matches the reference, and includes the possibilty of
+<!-- This exactly matches the reference, and includes the possibility of
      0 pixels different; in this case the maxDifference is ignored --->
 <meta name=fuzzy content="fuzzy-ref-1.html:128;0-100">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences_1.html b/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences_1.html
index 6bf85cee..9513f9b 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences_1.html
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/reftest/reftest_fuzzy_no_differences_1.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <link rel=match href=fuzzy-ref-1.html>
-<!-- This exactly matches the reference, and includes the possibilty of
+<!-- This exactly matches the reference, and includes the possibility of
      0 difference in the color channel; in this case the pixelsDifferent is ignored --->
 <meta name=fuzzy content="fuzzy-ref-1.html:0-128;100">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/lint.whitelist b/third_party/blink/web_tests/external/wpt/lint.whitelist
index a7a4600..f641145 100644
--- a/third_party/blink/web_tests/external/wpt/lint.whitelist
+++ b/third_party/blink/web_tests/external/wpt/lint.whitelist
@@ -801,7 +801,10 @@
 
 # Tests that use WebKit/Blink testing APIs
 LAYOUTTESTS APIS: css/css-regions/interactivity/*
+LAYOUTTESTS APIS: import-maps/resolving.tentative.html
+LAYOUTTESTS APIS: permissions/test-background-fetch-permission.html
 LAYOUTTESTS APIS: resources/chromium/generic_sensor_mocks.js
+LAYOUTTESTS APIS: resources/chromium/webxr-test.js
 
 # Gecko additons to remove
 CSS-COLLIDING-REF-NAME: css/css-contain/reference/contain-size-fieldset-001-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1-ref.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1-ref.html
new file mode 100644
index 0000000..111ea79
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1-ref.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test dynamically changing dir attribute</title>
+</head>
+<body>
+    <p>
+      math:
+      <math dir="rtl">
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+      <math dir="rtl">
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+      <math>
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+    </p>
+    <p>
+      mstyle:
+      <math>
+        <mstyle dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle>
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+    </p>
+    <p>
+      mrow:
+      <math>
+        <mrow dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+      <math>
+        <mrow dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+      <math>
+        <mrow>
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+    </p>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1.html
new file mode 100644
index 0000000..c4c99d87
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/dynamic-dir-1.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <meta charset="utf-8">
+  <title>Test dynamically changing dir attribute</title></head>
+  <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#cssproperties">
+  <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dom">
+  <meta name="assert" content="The dir attribute should update direction map to css properties dynamically">
+  <link rel="match" href="dynamic-dir-1-ref.html">
+  <script>
+      window.addEventListener("load", () => {
+
+        // force initial layout so we're sure what we're testing against
+        document.documentElement.getBoundingClientRect();
+
+        ["math", "mstyle", "mrow"].forEach((tag) => {
+          let elements = document.getElementsByTagName(tag);
+
+          // set an explcit rtl where there was none
+          elements[0].setAttribute("dir", "rtl");
+
+          // change explcit ltr to rtl
+          elements[1].setAttribute("dir", "rtl");
+
+          // remove an explicitly set dir="rtl"
+          elements[2].removeAttribute("dir");
+
+        })
+
+        document.documentElement.classList.remove('reftest-wait');
+      })
+    </script>
+</head>
+<body>
+    <p>
+      math:
+      <math>
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+      <math dir="ltr">
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+      <math dir="rtl">
+        <mi>a</mi>
+        <mi>b</mi>
+        <mi>c</mi>
+      </math>
+    </p>
+    <p>
+      mstyle:
+      <math>
+        <mstyle>
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle dir="ltr">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+      <math>
+        <mstyle dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mstyle>
+      </math>
+    </p>
+    <p>
+      mrow:
+      <math>
+        <mrow>
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+      <math>
+        <mrow dir="ltr">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+      <math>
+        <mrow dir="rtl">
+          <mi>a</mi>
+          <mi>b</mi>
+          <mi>c</mi>
+        </mrow>
+      </math>
+    </p>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
index dc35ea2..e8c847b 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
@@ -285,12 +285,3 @@
                    .pointerUp()
                    .send();
 }
-
-function touchTapInTarget(target) {
-    return new test_driver.Actions()
-                   .addPointer("pointer1", "touch")
-                   .pointerMove(0, 0, {origin: target})
-                   .pointerDown()
-                   .pointerUp()
-                   .send();
-}
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html
rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
index ae2373c3..dcea2837 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
@@ -7,9 +7,6 @@
         <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
-        <script src="/resources/testdriver.js"></script>
-        <script src="/resources/testdriver-actions.js"></script>
-        <script src="/resources/testdriver-vendor.js"></script>
         <script src="pointerevent_support.js"></script>
         <style>
             .scroller > div {
@@ -92,7 +89,6 @@
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
 
                 // Check if touch-action attribute works properly for embedded divs
                 // Scrollable-Parent, Child: `auto`, Grand-Child: `none`
@@ -103,25 +99,13 @@
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+                    test_touchaction.done();
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
-
-                // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
-                    return touchScrollInTarget(scrollTarget, 'right');
-                }).then(function() {
-                    return touchTapInTarget(btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
-                });
             }
         </script>
         <h1>behaviour: none</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html
rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html
index 81f0ea6..16e42954 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html
@@ -7,9 +7,6 @@
         <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
-        <script src="/resources/testdriver.js"></script>
-        <script src="/resources/testdriver-actions.js"></script>
-        <script src="/resources/testdriver-vendor.js"></script>
         <script src="pointerevent_support.js"></script>
         <style>
             .scroller > div {
@@ -87,7 +84,6 @@
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
@@ -98,25 +94,13 @@
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+                    test_touchaction.done();
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
-
-                // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
-                    return touchScrollInTarget(scrollTarget, 'right');
-                }).then(function() {
-                    return touchTapInTarget(btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
-                });
             }
         </script>
         <h1>behaviour: none</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html
rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
index 775708d..c75d067e 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
@@ -7,9 +7,6 @@
         <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
-        <script src="/resources/testdriver.js"></script>
-        <script src="/resources/testdriver-actions.js"></script>
-        <script src="/resources/testdriver-vendor.js"></script>
         <script src="pointerevent_support.js"></script>
         <style>
             .scroller > div {
@@ -91,7 +88,6 @@
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
@@ -102,20 +98,8 @@
                         assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
-                    updateDescriptionComplete();
-                });
-
-                // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
-                    return touchScrollInTarget(scrollTarget, 'right');
-                }).then(function() {
-                    return touchTapInTarget(btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
                     test_touchaction.done();
+                    updateDescriptionComplete();
                 });
             }
         </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html
rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
index 592cfd6..d420cc56 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
@@ -7,9 +7,6 @@
         <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
-        <script src="/resources/testdriver.js"></script>
-        <script src="/resources/testdriver-actions.js"></script>
-        <script src="/resources/testdriver-vendor.js"></script>
         <script src="pointerevent_support.js"></script>
         <style>
             .scroller > div {
@@ -92,7 +89,6 @@
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
 
                 // Check if touch-action attribute works properly for embedded divs
                 // Scrollable-Parent, Child: `pan-x`, Grand-Child: `pan-y`
@@ -103,25 +99,13 @@
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+                    test_touchaction.done();
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
-
-                // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
-                    return touchScrollInTarget(scrollTarget, 'right');
-                }).then(function() {
-                    return touchTapInTarget(btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
-                });
             }
         </script>
         <h1>behaviour: none</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html
rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html
index 45ea143..5e674a1 100644
--- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html
+++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html
@@ -7,9 +7,6 @@
         <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
-        <script src="/resources/testdriver.js"></script>
-        <script src="/resources/testdriver-actions.js"></script>
-        <script src="/resources/testdriver-vendor.js"></script>
         <script src="pointerevent_support.js"></script>
         <style>
             .scroller {
@@ -87,7 +84,6 @@
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
@@ -98,25 +94,13 @@
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+                    test_touchaction.done();
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
-
-                // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
-                    return touchScrollInTarget(scrollTarget, 'right');
-                }).then(function() {
-                    return touchTapInTarget(btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
-                });
             }
         </script>
         <h1>behaviour: none</h1>
diff --git a/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html b/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html
new file mode 100644
index 0000000..a142f55
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/portals-host-post-message.sub.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>Test postMessage on PortalHost</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+  <script>
+    function createPortal(portalSrc) {
+      var portal = document.createElement("portal");
+      portal.src = portalSrc;
+      return new Promise((resolve, reject) => {
+        portal.addEventListener("message", e => {
+          if (e.data == "loaded")
+            resolve(portal);
+        });
+        document.body.appendChild(portal);
+      });
+    }
+
+    async function createPortalAndLoopMessage(portalSrc, params) {
+      var portal = await createPortal(portalSrc);
+      var waitForResponse = new Promise((resolve, reject) => {
+        portal.addEventListener("message", e => { resolve(e); });
+      });
+      portal.postMessage(params, "*");
+      return waitForResponse;
+    }
+
+    const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-post-message.sub.html";
+
+    promise_test(async () => {
+      var {data, origin} = await createPortalAndLoopMessage(
+          "resources/portal-host-post-message.sub.html", ["test", "*"]);
+      assert_equals(data, "test");
+      assert_equals(origin, "http://{{host}}:{{ports[http][0]}}");
+    }, "Message received after postMessage from portal host");
+
+    promise_test(async () => {
+      var {data, origin} = await createPortalAndLoopMessage(
+          crossOriginUrl, ["test", "*"]);
+      assert_equals(data, "test");
+      assert_equals(origin, "http://{{hosts[alt][www]}}:{{ports[http][0]}}");
+    }, "Message received after postMessage from portal host in cross-origin-portal");
+
+    promise_test(async () => {
+      var {data, origin} = await createPortalAndLoopMessage(
+          "resources/portal-host-post-message.sub.html", ["test"]);
+      assert_equals(data, "test");
+      assert_equals(origin, "http://{{host}}:{{ports[http][0]}}");
+    }, "Message received from same-origin portal host with no target origin specified");
+
+    promise_test(async () => {
+      var {data, origin} = await createPortalAndLoopMessage(
+         crossOriginUrl, ["test", "http://{{host}}:{{ports[http][0]}}"]);
+      assert_equals(data, "test");
+    }, "Message received from cross-origin portal host with target origin correctly specified");
+
+    promise_test(async () => {
+       var receiveMessage = new Promise((resolve, reject) => {
+         var bc = new BroadcastChannel("portal-host-post-message-after-activate");
+         bc.onmessage = e => { resolve(e); };
+       });
+       const portalUrl = encodeURIComponent(
+          "portal-host-post-message-after-activate.html");
+       window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
+       var message = await receiveMessage;
+       assert_equals(message.data, "InvalidStateError");
+    }, "Calling postMessage after receiving onactivate event should fail");
+
+    promise_test(() => {
+      var portal = document.createElement("portal");
+      portal.src = "resources/portal-host-post-message-navigate-1.html";
+      var count = 0;
+      var waitForMessages = new Promise((resolve, reject) => {
+        portal.addEventListener("message", e => {
+          count++;
+          if (count == 2)
+            resolve();
+        });
+      });
+      document.body.appendChild(portal);
+      return waitForMessages;
+    }, "postMessage before and after portal navigation should work");
+
+    async_test(t => {
+      createPortalAndLoopMessage("resources/portal-host-post-message.sub.html",
+          ["test", "http://{{hosts[alt][www]}}:{{ports[http][0]}}"])
+          .then(t.step_func(() => { assert_unreached("message delivered"); }));
+      t.step_timeout(t.done, 2000);
+    }, "Message should not be received from portal host with target set to different origin");
+
+    async_test(t => {
+      createPortalAndLoopMessage(crossOriginUrl, ["test"]).then(t.step_func(() => {
+        assert_unreached("message delivered");
+      }));
+      t.step_timeout(t.done, 2000);
+    }, "Message should not be received cross origin-portal host with no target origin set");
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-after-activate.html b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-after-activate.html
new file mode 100644
index 0000000..07db1a0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-after-activate.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script>
+  var bc = new BroadcastChannel("portal");
+  bc.postMessage("loaded");
+  bc.close();
+
+  var ph = window.portalHost;
+
+  window.onportalactivate = e => {
+    var exception_name = ""
+    try {
+      ph.postMessage("message", "*");
+    }
+    catch (error) {
+      exception_name = error.name;
+    }
+    bc = new BroadcastChannel("portal-host-post-message-after-activate");
+    bc.postMessage(exception_name, "*");
+    bc.close();
+  };
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-1.html b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-1.html
new file mode 100644
index 0000000..3b36eae
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-1.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<script>
+  window.portalHost.postMessage("loaded", "*");
+  window.location.href = "portal-host-post-message-navigate-2.html"
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-2.html b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-2.html
new file mode 100644
index 0000000..163c42e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message-navigate-2.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script>
+  window.portalHost.postMessage("loaded", "*");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message.sub.html b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message.sub.html
new file mode 100644
index 0000000..8df9830
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/resources/portal-host-post-message.sub.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script>
+  window.portalHost.postMessage("loaded", "*");
+  window.portalHost.addEventListener("message", e => {
+    window.portalHost.postMessage(...e.data);
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/gitignore/gitignore.py b/third_party/blink/web_tests/external/wpt/tools/gitignore/gitignore.py
index 9b661308..901a1f41 100644
--- a/third_party/blink/web_tests/external/wpt/tools/gitignore/gitignore.py
+++ b/third_party/blink/web_tests/external/wpt/tools/gitignore/gitignore.py
@@ -216,7 +216,8 @@
                     for rule_dir in [None, dirpath]:
                         if name in literals.get(rule_dir, empty):
                             exclude = literals[rule_dir][name]
-                            if not any(rule.match(path) for rule in exclude):
+                            if not any(rule.match(name if name_only else path)
+                                       for name_only, rule in exclude):
                                 # Skip this item
                                 self.cache[path] = True
                                 break
diff --git a/third_party/blink/web_tests/external/wpt/tools/lint/rules.py b/third_party/blink/web_tests/external/wpt/tools/lint/rules.py
index 76d5d3e..94aff64 100644
--- a/third_party/blink/web_tests/external/wpt/tools/lint/rules.py
+++ b/third_party/blink/web_tests/external/wpt/tools/lint/rules.py
@@ -327,10 +327,10 @@
     description = "Print function used"
 
 class LayoutTestsRegexp(Regexp):
-    pattern = br"eventSender|testRunner|window\.internals"
+    pattern = br"(eventSender|testRunner|internals)\."
     name = "LAYOUTTESTS APIS"
     file_extensions = [".html", ".htm", ".js", ".xht", ".xhtml", ".svg"]
-    description = "eventSender/testRunner/window.internals used; these are LayoutTests-specific APIs (WebKit/Blink)"
+    description = "eventSender/testRunner/internals used; these are LayoutTests-specific APIs (WebKit/Blink)"
 
 class SpecialPowersRegexp(Regexp):
     pattern = b"SpecialPowers"
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
index 5dde9374..b5210400 100644
--- a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
+++ b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
@@ -483,17 +483,17 @@
                              allow_cached=allow_cached)
         except ManifestVersionMismatch:
             logger.info("Manifest version changed, rebuilding")
-            rebuild = True
 
         if manifest is not None and manifest.url_base != url_base:
             logger.info("Manifest url base did not match, rebuilding")
-            rebuild = True
+            manifest = None
 
     if manifest is None:
         manifest = Manifest(tests_root, url_base)
+        rebuild = True
         update = True
 
-    if update:
+    if rebuild or update:
         tree = vcs.get_tree(tests_root, manifest, manifest_path, cache_root,
                             working_copy, rebuild)
         changed = manifest.update(tree)
diff --git a/third_party/blink/web_tests/external/wpt/tools/runner/index.html b/third_party/blink/web_tests/external/wpt/tools/runner/index.html
index 2d7d2529..57940d02 100644
--- a/third_party/blink/web_tests/external/wpt/tools/runner/index.html
+++ b/third_party/blink/web_tests/external/wpt/tools/runner/index.html
@@ -23,8 +23,16 @@
   <div class="alert alert-warning">
         This runner does not fully support all test types and has a number of
         <a href="https://github.com/web-platform-tests/wpt/labels/runner">known issues</a>.
+        <span id="runner-contact-info"></span>
         <code>./wpt run</code> is a more well-supported runner, see the documentation on
         <a href="https://web-platform-tests.org/running-tests/">running tests</a>.
+        <script>
+        if (location.host == "w3c-test.org") {
+            document.getElementById("runner-contact-info")
+                .innerHTML = ' If this runner isn’t working, contact'
+                    + ' <a href="mailto:mike@w3.org">mike@w3.org</a>. '
+        }
+        </script>
   </div>
 
   <div id="testControl" class="panel panel-default">
diff --git a/third_party/blink/web_tests/external/wpt/web-share/META.yml b/third_party/blink/web_tests/external/wpt/web-share/META.yml
index 1197ab9f23..e054ccc 100644
--- a/third_party/blink/web_tests/external/wpt/web-share/META.yml
+++ b/third_party/blink/web_tests/external/wpt/web-share/META.yml
@@ -1,4 +1,5 @@
 spec: https://wicg.github.io/web-share/
 suggested_reviewers:
+  - ewilligers
   - mgiuca
   - marcoscaceres
diff --git a/third_party/blink/web_tests/fast/workers/worker-performance-time.html b/third_party/blink/web_tests/fast/workers/worker-performance-time.html
deleted file mode 100644
index 5e39ef1e..0000000
--- a/third_party/blink/web_tests/fast/workers/worker-performance-time.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<title>Test the timing in the worker to be consistent between animation and performance.now().</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script id="worker" type="text/worker">
-var countWorker = 10;
-function animate(time) {
-  var timeNow = performance.now();
-  countWorker--;
-  self.postMessage([time,timeNow, countWorker]);
-  if(countWorker > 0)
-    requestAnimationFrame(animate);
-};
-
-self.onmessage = function(msg){
-  requestAnimationFrame(animate);
-}
-</script>
-<script>
-async_test(function(t) {
-  var blob = new Blob([document.getElementById("worker").textContent]);
-  var worker = new Worker(URL.createObjectURL(blob));
-  worker.onmessage = t.step_func(function(pairTime) {
-    var time = pairTime.data[0];
-    var timeNow = pairTime.data[1];
-    var count = pairTime.data[2];
-    assert_approx_equals(time, timeNow, 2, "Times must be close enough");
-    if(count == 0)
-      t.done();
-  });
-  worker.postMessage("");
-}, 'Test the timing in the worker to be consistent between animation and performance.now');
-</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/plugins/embed-change-attribute-reattach.html b/third_party/blink/web_tests/plugins/embed-change-attribute-reattach.html
new file mode 100644
index 0000000..0463a19
--- /dev/null
+++ b/third_party/blink/web_tests/plugins/embed-change-attribute-reattach.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+  var misery = async_test("no crash");
+  var loaded = false;
+  function stab(victim) {
+      if (loaded)
+          return;
+      loaded = true;
+      victim.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
+      victim.style.display = "block";
+      misery.done();
+  }
+</script>
+<embed src="not-found" onload="stab(this)"></embed>
diff --git a/third_party/blink/web_tests/virtual/display-lock/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt b/third_party/blink/web_tests/virtual/display-lock/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt
index 149252b9..048480c 100644
--- a/third_party/blink/web_tests/virtual/display-lock/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt
+++ b/third_party/blink/web_tests/virtual/display-lock/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt
@@ -8,10 +8,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -28,10 +28,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -47,10 +47,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -66,10 +66,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -97,10 +97,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -117,10 +117,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -136,10 +136,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
@@ -155,10 +155,10 @@
         8,
         8,
         "L",
-        18,
+        792,
         8,
         "L",
-        18,
+        792,
         18,
         "L",
         8,
diff --git a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-display-none-editable.html b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-display-none-editable.html
index 3c1b2637..d48f9d5 100644
--- a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-display-none-editable.html
+++ b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-display-none-editable.html
@@ -16,7 +16,7 @@
 </style>
 
 <div id="first" tabindex="0">First</div>
-<input id="second" type="text" value="Second (|d| key will remove)"</input>
+<input id="second" type="text" value="Second (|d| key will remove)"></input>
 <div id="third" tabindex="0">Third</div>
 
 <script>
diff --git a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-does-not-submit.html b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-does-not-submit.html
new file mode 100644
index 0000000..20d9ae6
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-does-not-submit.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<script src="../../../../../resources/testharness.js"></script>
+<script src="../../../../../resources/testharnessreport.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/third_party/blink/public/mojom/page/spatial_navigation.mojom.js"></script>
+<script src="../../../../../fast/spatial-navigation/resources/mock-snav-service.js"></script>
+<script src="../../../../../fast/spatial-navigation/resources/snav-testharness.js"></script>
+
+<form action="javascript:fail();">
+<input type="text" id="first"></input><p />
+<input type="submit" value="Submit" />
+</form>
+
+<script>
+  function fail() {
+    assert_false(true, "Form should not have been submitted.");
+  }
+  promise_test(async () => {
+    let first = document.getElementById("first");
+
+    snav.triggerMove("Down");
+    await snavCallback();
+
+    assert_false(mockSnavService.canExitFocus,
+                "Should not be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_false(mockSnavService.hasNextFormElement,
+                "Should not be able to move to next form element.");
+
+    eventSender.keyDown('Enter');
+    assert_equals(document.activeElement,
+                  first,
+                  "'first' should be focused.");
+
+    await snav.rAF();
+
+    assert_true(mockSnavService.canExitFocus,
+                "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_true(mockSnavService.hasNextFormElement,
+                 "Should be able to move to next form element.");
+  }, 'Form does not submit when passing spat nav focus.');
+</script>
diff --git a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state-on-click.html b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state-on-click.html
index 3fb47bba..09564259 100644
--- a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state-on-click.html
+++ b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state-on-click.html
@@ -12,58 +12,46 @@
 </form>
 
 <script>
-  async_test((t) => {
+  function notCalled() {
+    assert_false(true, "Should not be called");
+  };
+  mockSnavService.callback = notCalled;
+
+  promise_test(async () => {
     let first = document.getElementById("first");
     let second = document.getElementById("second");
 
-    mockSnavService.callback = notCalled;
+    await snav.rAF();
 
-    async function runTest() {
-      console.error('0');
-      await snav.rAF();
+    snav.triggerMove('Down');
 
-      snav.triggerMove('Down');
-      await snavCallback();
-      assert_equals(window.internals.interestedElement,
-                    first,
-                    "'first' should be interested.");
-      assert_not_equals(document.activeElement,
-                        first,
-                        "'first' should not yet be focused.");
-      assert_false(mockSnavService.canExitFocus,
-                  "Should be able to exit focus.");
-      assert_true(mockSnavService.canSelectElement,
-                  "Should be able to select element.");
-      assert_false(mockSnavService.hasNextFormElement,
-                   "Should be able to move to next form element.");
+    await snavCallback();
+    assert_equals(window.internals.interestedElement,
+                  first,
+                  "'first' should be interested.");
+    assert_not_equals(document.activeElement,
+                      first,
+                      "'first' should not yet be focused.");
+    assert_false(mockSnavService.canExitFocus,
+                "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_false(mockSnavService.hasNextFormElement,
+                 "Should be able to move to next form element.");
 
-      eventSender.keyDown('Enter');
-      await snavCallback();
-      assert_true(mockSnavService.canExitFocus,
-                  "Should be able to exit focus.");
-      assert_true(mockSnavService.canSelectElement,
-                  "Should be able to select element.");
-      assert_true(mockSnavService.hasNextFormElement,
-                  "Should be able to move to next form element.");
-      assert_equals(window.internals.interestedElement,
-                    first,
-                    "'first' should be interested.");
-      assert_equals(document.activeElement,
-                    first,
-                    "'first' should be focused.");
-
-      t.done();
-    };
-
-    t.step_timeout(() => {
-      runTest();
-    }, 0);
-
-    function notCalled() {
-      t.step_timeout(() => {
-        assert_false(true, "Should not be called");
-      }, 0);
-    };
-
+    eventSender.keyDown('Enter');
+    await snavCallback();
+    assert_true(mockSnavService.canExitFocus,
+                "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_true(mockSnavService.hasNextFormElement,
+                "Should be able to move to next form element.");
+    assert_equals(window.internals.interestedElement,
+                  first,
+                  "'first' should be interested.");
+    assert_equals(document.activeElement,
+                  first,
+                  "'first' should be focused.");
   }, 'Spat Nav state updates correctly when clicking on form elements.');
 </script>
diff --git a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state.html b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state.html
index 5925dc8c..6501c24 100644
--- a/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state.html
+++ b/third_party/blink/web_tests/virtual/focusless-spat-nav/fast/spatial-navigation/focusless/snav-focusless-form-state.html
@@ -13,72 +13,64 @@
 </form>
 
 <script>
-  async_test((t) => {
+  function notCalled() {
+    assert_false(true, "Should not be called");
+  };
+
+  let initialState = snavCallback();
+  promise_test(async () => {
+
     let first = document.getElementById("first");
     let second = document.getElementById("second");
     let third = document.getElementById("third");
 
-    let initialState = snavCallback();
+    await snav.rAF();
 
-    async function runTest() {
-      assert_equals(document.activeElement,
-                    first,
-                    "'first' should start focused.");
-      assert_equals(window.internals.interestedElement,
-                    first,
-                    "'first' should start interested.");
+    assert_equals(document.activeElement,
+                  first,
+                  "'first' should start focused.");
+    assert_equals(window.internals.interestedElement,
+                  first,
+                  "'first' should start interested.");
 
-      await initialState;
-      assert_true(mockSnavService.canExitFocus,
-                  "Should be able to exit focus.");
-      assert_true(mockSnavService.canSelectElement,
-                  "Should be able to select element.");
-      assert_true(mockSnavService.hasNextFormElement,
-                  "Should be able to move to next form element.");
+    await initialState;
+    assert_true(mockSnavService.canExitFocus,
+                "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_true(mockSnavService.hasNextFormElement,
+                "Should be able to move to next form element.");
 
-      mockSnavService.callback = notCalled;
-      eventSender.keyDown('Tab');
-      assert_equals(document.activeElement,
-                    second,
-                    "'second' should be focused.");
+    mockSnavService.callback = notCalled;
+    eventSender.keyDown('Tab');
+    assert_equals(document.activeElement,
+                  second,
+                  "'second' should be focused.");
 
-      await snav.rAF();
+    await snav.rAF();
 
-      eventSender.keyDown('Tab');
-      assert_equals(document.activeElement,
-                    third,
-                    "'third' should be focused.");
+    eventSender.keyDown('Tab');
+    assert_equals(document.activeElement,
+                  third,
+                  "'third' should be focused.");
 
-      await snavCallback();
-      assert_true(mockSnavService.canExitFocus,
-                  "Should be able to exit focus.");
-      assert_true(mockSnavService.canSelectElement,
-                  "Should be able to select element.");
-      assert_false(mockSnavService.hasNextFormElement,
-                   "Should be able to move to next form element.");
+    await snavCallback();
+    assert_true(mockSnavService.canExitFocus,
+                "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_false(mockSnavService.hasNextFormElement,
+                 "Should be able to move to next form element.");
 
-      eventSender.keyDown('Escape');
+    eventSender.keyDown('Escape');
 
-      await snavCallback();
-      assert_false(mockSnavService.canExitFocus,
-                   "Should be able to exit focus.");
-      assert_true(mockSnavService.canSelectElement,
-                  "Should be able to select element.");
-      assert_false(mockSnavService.hasNextFormElement,
-                   "Should be able to move to next form element.");
-
-      t.done();
-    };
-
-    t.step_timeout(() => {
-      runTest();
-    }, 0);
-
-    function notCalled() {
-      t.step_timeout(() => {
-        assert_false(true, "Should not be called");
-      }, 0);
-    };
+    await snavCallback();
+    assert_false(mockSnavService.canExitFocus,
+                 "Should be able to exit focus.");
+    assert_true(mockSnavService.canSelectElement,
+                "Should be able to select element.");
+    assert_false(mockSnavService.hasNextFormElement,
+                 "Should be able to move to next form element.");
 
   }, 'Spat Nav state updates correctly for form elements.');
 </script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index ff8cf7d..ad3ea216 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5564,6 +5564,7 @@
 interface PortalHost : EventTarget
     attribute @@toStringTag
     method constructor
+    method postMessage
 interface Presentation
     attribute @@toStringTag
     getter defaultRequest
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index ae850c1..fc7dbcf 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -264,10 +264,13 @@
   @property
   def main_lib_path(self):
     # Cannot extract this from GN because --cloud needs to work without GN.
+    # TODO(agrieve): Could maybe extract from .apk?
     if self.IsLinux():
       return 'chrome'
-    if 'monochrome' in self.target:
+    if 'monochrome' in self.target or 'trichrome' in self.target:
       ret = 'lib.unstripped/libmonochrome_base.so'
+    elif 'webview' in self.target:
+      ret = 'lib.unstripped/libwebviewchromium.so'
     else:
       ret = 'lib.unstripped/libchrome_base.so'
     # Maintain support for measuring non-bundle apks.
@@ -1064,4 +1067,3 @@
 
 if __name__ == '__main__':
   sys.exit(main())
-
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b75db81..e513c8f 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -22932,9 +22932,10 @@
   <int value="2869" label="V8RTCQuicTransport_SendDatagram_Method"/>
   <int value="2870" label="V8RTCQuicTransport_ReceiveDatagrams_Method"/>
   <int value="2871" label="CSSValueContainStyle"/>
-  <int value="2872" label="WebShareContainingFiles"/>
-  <int value="2873" label="WebShareWithoutFiles"/>
-  <int value="2874" label="WebShareCancelled"/>
+  <int value="2872" label="WebShareSuccessfulContainingFiles"/>
+  <int value="2873" label="WebShareSuccessfulWithoutFiles"/>
+  <int value="2874" label="WebShareUnsuccessfulContainingFiles"/>
+  <int value="2875" label="WebShareUnsuccessfulWithoutFiles"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -32834,6 +32835,7 @@
   <int value="-1327676774" label="disable-accelerated-mjpeg-decode"/>
   <int value="-1326463296" label="SSLCommittedInterstitials:disabled"/>
   <int value="-1325887476" label="NewPrintPreview:enabled"/>
+  <int value="-1324029365" label="EnableTLS13EarlyData:enabled"/>
   <int value="-1322882747" label="disable-datasaver-prompt"/>
   <int value="-1319688939" label="ignore-gpu-blacklist"/>
   <int value="-1318914924" label="OverflowIconsForMediaControls:enabled"/>
@@ -33789,6 +33791,7 @@
   <int value="151101719" label="HtmlBaseUsernameDetector:enabled"/>
   <int value="157217034" label="enable-tab-for-desktop-share"/>
   <int value="157318016" label="AutomaticTabDiscarding:enabled"/>
+  <int value="161409456" label="AutofillUseMobileLabelDisambiguation:disabled"/>
   <int value="161694478" label="OmniboxNewAnswerLayout:enabled"/>
   <int value="173288154" label="PrintPdfAsImage:enabled"/>
   <int value="178337215" label="enable-md-history"/>
@@ -34219,6 +34222,7 @@
   <int value="848324390" label="enable-lock-screen-apps"/>
   <int value="849980462" label="RemoveNtpFakebox:disabled"/>
   <int value="851085848" label="enable-settings-window"/>
+  <int value="851616920" label="EnableTLS13EarlyData:disabled"/>
   <int value="852313529" label="RTCUnifiedPlanByDefault:disabled"/>
   <int value="854730848" label="disable-app-info-dialog-mac"/>
   <int value="855746780" label="disable-physical-keyboard-autocorrect"/>
@@ -34410,6 +34414,7 @@
   <int value="1167350114" label="AndroidNightMode:enabled"/>
   <int value="1167613030" label="enable-permission-action-reporting"/>
   <int value="1169418814" label="ManualFallbacksFilling:enabled"/>
+  <int value="1173244409" label="AutofillUseMobileLabelDisambiguation:enabled"/>
   <int value="1174088940" label="enable-wasm"/>
   <int value="1177120582" label="InstallableInkDrop:disabled"/>
   <int value="1179013979"
@@ -34709,6 +34714,7 @@
       label="OmniboxUIExperimentWhiteBackgroundOnBlur:disabled"/>
   <int value="1617187093" label="enable-improved-a2hs"/>
   <int value="1618633341" label="MashOopViz:enabled"/>
+  <int value="1620369597" label="enable-unsafe-webgpu"/>
   <int value="1621298798" label="VrBrowserKeyboard:enabled"/>
   <int value="1622131033" label="ozone-test-single-overlay-support"/>
   <int value="1626824478" label="ExperimentalAppBanners:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e37eebc..c1e5c6f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -24358,6 +24358,38 @@
   <summary>Specified DevTools action has been taken.</summary>
 </histogram>
 
+<histogram name="DevTools.BackgroundService.ClearEvents"
+    enum="ServiceWorkerStatusCode" expires_after="M78">
+  <owner>dgozman@chromium.org</owner>
+  <owner>rayankans@chromium.org</owner>
+  <summary>
+    The result of clearing all stored events for a Background Service feature.
+    This is called if a developer clicks on a delete button in a Background
+    Service DevTools panel.
+  </summary>
+</histogram>
+
+<histogram name="DevTools.BackgroundService.GetEvents"
+    enum="ServiceWorkerStatusCode" expires_after="M78">
+  <owner>dgozman@chromium.org</owner>
+  <owner>rayankans@chromium.org</owner>
+  <summary>
+    The result of loading all stored events for a Background Service feature.
+    This is called when the a Bakground Service DevTools panel is opened.
+  </summary>
+</histogram>
+
+<histogram name="DevTools.BackgroundService.LogEvent"
+    enum="ServiceWorkerStatusCode" expires_after="M78">
+  <owner>dgozman@chromium.org</owner>
+  <owner>rayankans@chromium.org</owner>
+  <summary>
+    The result of logging a Background Service event. An event is logged if
+    `Recording` mode is on and a relevant Background Service event is taking
+    place.
+  </summary>
+</histogram>
+
 <histogram name="DevTools.InspectElement" units="ms">
   <owner>alph@chromium.org</owner>
   <owner>pfeldman@chromium.org</owner>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 74b7406..4cab5a4 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -130,7 +130,6 @@
       }
     ],
     'platform': 'android-chrome',
-      'browser': 'bin/monochrome_64_32_bundle',
     'dimension': {
       'pool': 'chrome.tests.perf-fyi',
       'os': 'Android',
@@ -969,8 +968,6 @@
   # For trybot testing we always use the reference build
   if tester_config.get('testing', False):
     browser_name = 'reference'
-  elif 'browser' in tester_config:
-    browser_name = 'exact'
   elif tester_config['platform'] == 'android':
     browser_name = 'android-chromium'
   elif tester_config['platform'].startswith('android-'):
@@ -987,13 +984,7 @@
     '--upload-results'
   ]
 
-  if 'browser' in tester_config:
-    test_args.append('--browser-executable=../../out/Release/%s' %
-                     tester_config['browser'])
-    if tester_config['platform'].startswith('android'):
-      test_args.append('--device=android')
-
-  if tester_config['platform'].startswith('android-webview'):
+  if browser_name.startswith('android-webview'):
     test_args.append(
         '--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk')
 
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py
index 7697b49..3f326e7 100644
--- a/tools/perf/core/perf_data_generator_unittest.py
+++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -97,61 +97,6 @@
       }
     self.assertEquals(returned_test, expected_generated_test)
 
-  def testGeneratePerformanceTestSuiteExact(self):
-    swarming_dimensions = [
-        {'os': 'SkyNet', 'pool': 'T-RIP'}
-    ]
-    test_config = {
-        'platform': 'android-webview',
-        'browser': 'bin/monochrome_64_32_bundle',
-        'dimension': swarming_dimensions,
-    }
-    test = {
-        'isolate': 'performance_test_suite',
-        'extra_args': [
-            '--run-ref-build',
-            '--test-shard-map-filename=shard_map.json',
-          ],
-        'num_shards': 26
-    }
-    returned_test = perf_data_generator.generate_performance_test(
-        test_config, test)
-
-    expected_generated_test = {
-        'override_compile_targets': ['performance_test_suite'],
-        'isolate_name': 'performance_test_suite',
-        'args': ['-v', '--browser=exact', '--upload-results',
-                 '--browser-executable=../../out/Release'
-                 '/bin/monochrome_64_32_bundle',
-                 '--device=android',
-                 '--webview-embedder-apk=../../out/Release'
-                 '/apks/SystemWebViewShell.apk',
-                 '--run-ref-build',
-                 '--test-shard-map-filename=shard_map.json'],
-        'trigger_script': {
-          'args': [
-            '--multiple-dimension-script-verbose',
-            'True'
-          ],
-          'requires_simultaneous_shard_dispatch': True,
-          'script': '//testing/trigger_scripts/perf_device_trigger.py'
-        },
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py'
-        },
-        'swarming': {
-          'ignore_task_failure': False,
-          'can_use_on_swarming_builders': True,
-          'expiration': 7200,
-          'io_timeout': 1800,
-          'hard_timeout': 36000,
-          'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]],
-          'shards': 26
-        },
-        'name': 'performance_test_suite'
-      }
-    self.assertEquals(returned_test, expected_generated_test)
-
   def testGeneratePerformanceTestSuiteWebview(self):
     swarming_dimensions = [
         {'os': 'SkyNet', 'pool': 'T-RIP'}
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py
index 7ace5f3..df7cd111 100644
--- a/tools/perf/core/perf_json_config_validator.py
+++ b/tools/perf/core/perf_json_config_validator.py
@@ -81,18 +81,17 @@
   browser_options = _ParseBrowserFlags(test_config['args'])
   if 'WebView' in builder_name or 'webview' in builder_name:
     if browser_options.browser not in (
-        'android-webview', 'android-webview-google', 'exact'):
+        'android-webview', 'android-webview-google'):
       raise ValueError(
-          "%s must use 'android-webview', 'android-webview-google' or 'exact' "
-          "browser" % builder_name)
+          "%s must use 'android-webview' or 'android-webview-google' browser" %
+          builder_name)
     if not browser_options.webview_embedder_apk:
       raise ValueError('%s must set --webview-embedder-apk flag' % builder_name)
   elif 'Android' in builder_name or 'android' in builder_name:
-    if browser_options.browser not in (
-        'android-chromium', 'android-chrome', 'exact'):
+    if browser_options.browser not in ('android-chromium', 'android-chrome'):
       raise ValueError(
-          "%s must use 'android-chromium', 'android-chrome' or 'exact' "
-          "browser" % builder_name)
+          "%s must use 'android-chromium' or 'android-chrome' browser" %
+          builder_name)
   elif builder_name in ('win-10-perf', 'Win 7 Nvidia GPU Perf'):
     if browser_options.browser != 'release_x64':
       raise ValueError("%s must use 'release_x64' browser type" %
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 79523d2..5c90f6ad 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -358,6 +358,7 @@
 crbug.com/865400 [ Pixel_2 ] v8.browsing_mobile-future/browse:shopping:avito [ Skip ]
 crbug.com/923116 [ Android ] v8.browsing_mobile-future/browse:shopping:avito [ Skip ]
 crbug.com/954949 [ Nexus5X_Webview ] v8.browsing_mobile-future/browse:news:washingtonpost [ Skip ]
+crbug.com/958336 [ Android ] v8.browsing_mobile-future/browse:shopping:flipkart [ Skip ]
 
 # Benchmark: v8.detached_context_age_in_gc
 crbug.com/770982 [ Win ] v8.detached_context_age_in_gc/Docs_(1_open_document_tab) [ Skip ]
diff --git a/ui/aura/native_window_occlusion_tracker_win.cc b/ui/aura/native_window_occlusion_tracker_win.cc
index 19cf044..2d2f877b 100644
--- a/ui/aura/native_window_occlusion_tracker_win.cc
+++ b/ui/aura/native_window_occlusion_tracker_win.cc
@@ -600,7 +600,7 @@
   // up the thread sequence. In order to prevent DCHECK failures with the
   // |occlusion_update_timer_, we need to call
   // ScheduleOcclusionCalculationIfNeeded from a task.
-  // See SchedulerWorkerCOMDelegate::GetWorkFromWindowsMessageQueue().
+  // See WorkerThreadCOMDelegate::GetWorkFromWindowsMessageQueue().
   task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc
index 1bedbfeb..b6ac286 100644
--- a/ui/base/ime/dummy_text_input_client.cc
+++ b/ui/base/ime/dummy_text_input_client.cc
@@ -145,11 +145,13 @@
   return false;
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
 void DummyTextInputClient::SetCompositionFromExistingText(
     const gfx::Range& range,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+#endif
 
+#if defined(OS_WIN)
 void DummyTextInputClient::SetActiveCompositionForAccessibility(
     const gfx::Range& range,
     const base::string16& active_composition_text,
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h
index a06a70e..f97f4ca 100644
--- a/ui/base/ime/dummy_text_input_client.h
+++ b/ui/base/ime/dummy_text_input_client.h
@@ -56,11 +56,13 @@
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
 
-#if defined(OS_WIN)
-  // Overridden from ui::TextInputClient(Windows only):
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
   void SetCompositionFromExistingText(
       const gfx::Range& range,
       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
+#endif
+
+#if defined(OS_WIN)
   void SetActiveCompositionForAccessibility(
       const gfx::Range& range,
       const base::string16& active_composition_text,
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h
index 680be4e..cd01ff38 100644
--- a/ui/base/ime/text_input_client.h
+++ b/ui/base/ime/text_input_client.h
@@ -204,13 +204,16 @@
   // fields that are considered 'private' (e.g. in incognito tabs).
   virtual bool ShouldDoLearning() = 0;
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
   // Start composition over a given UTF-16 code range from existing text. This
   // should only be used for composition scenario when IME wants to start
   // composition on existing text.
   virtual void SetCompositionFromExistingText(
       const gfx::Range& range,
       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) = 0;
+#endif
+
+#if defined(OS_WIN)
   // Notifies accessibility about active composition. This API is currently
   // only defined for TSF which is available only on Windows
   // https://docs.microsoft.com/en-us/windows/desktop/api/UIAutomationCore/
diff --git a/ui/events/blink/blink_features.cc b/ui/events/blink/blink_features.cc
index d9b953b8..e35717ec 100644
--- a/ui/events/blink/blink_features.cc
+++ b/ui/events/blink/blink_features.cc
@@ -31,16 +31,14 @@
 const base::Feature kDontSendKeyEventsToJavascript{
     "DontSendKeyEventsToJavascript", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kSkipBrowserTouchFilter{"SkipBrowserTouchFilter",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
-const char kSkipBrowserTouchFilterTypeParamName[] = "type";
-const char kSkipBrowserTouchFilterTypeParamValueDiscrete[] = "discrete";
-const char kSkipBrowserTouchFilterTypeParamValueAll[] = "all";
-const char kSkipBrowserTouchFilterFilteringProcessParamName[] =
+const base::Feature kSkipTouchEventFilter{"SkipTouchEventFilter",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+const char kSkipTouchEventFilterTypeParamName[] = "type";
+const char kSkipTouchEventFilterTypeParamValueDiscrete[] = "discrete";
+const char kSkipTouchEventFilterTypeParamValueAll[] = "all";
+const char kSkipTouchEventFilterFilteringProcessParamName[] =
     "skip_filtering_process";
-const char kSkipBrowserTouchFilterFilteringProcessParamValueBrowser[] =
-    "browser";
-const char
-    kSkipBrowserTouchFilterFilteringProcessParamValueBrowserAndRenderer[] =
-        "browser_and_renderer";
+const char kSkipTouchEventFilterFilteringProcessParamValueBrowser[] = "browser";
+const char kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer[] =
+    "browser_and_renderer";
 }
diff --git a/ui/events/blink/blink_features.h b/ui/events/blink/blink_features.h
index 38f3732..4db2afc 100644
--- a/ui/events/blink/blink_features.h
+++ b/ui/events/blink/blink_features.h
@@ -63,20 +63,20 @@
 // "type" FeatureParam,
 // which can be either "discrete" (default) or "all".
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const base::Feature kSkipBrowserTouchFilter;
+extern const base::Feature kSkipTouchEventFilter;
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const char kSkipBrowserTouchFilterTypeParamName[];
+extern const char kSkipTouchEventFilterTypeParamName[];
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const char kSkipBrowserTouchFilterTypeParamValueDiscrete[];
+extern const char kSkipTouchEventFilterTypeParamValueDiscrete[];
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const char kSkipBrowserTouchFilterTypeParamValueAll[];
+extern const char kSkipTouchEventFilterTypeParamValueAll[];
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const char kSkipBrowserTouchFilterFilteringProcessParamName[];
+extern const char kSkipTouchEventFilterFilteringProcessParamName[];
 COMPONENT_EXPORT(BLINK_FEATURES)
-extern const char kSkipBrowserTouchFilterFilteringProcessParamValueBrowser[];
+extern const char kSkipTouchEventFilterFilteringProcessParamValueBrowser[];
 COMPONENT_EXPORT(BLINK_FEATURES)
 extern const char
-    kSkipBrowserTouchFilterFilteringProcessParamValueBrowserAndRenderer[];
+    kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer[];
 }
 
 #endif  // UI_EVENTS_BLINK_BLINK_FEATURES_H_
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 96db4e8b..4dad264 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -184,19 +184,19 @@
   scroll_predictor_ = std::make_unique<ScrollPredictor>(
       base::FeatureList::IsEnabled(features::kResamplingScrollEvents));
 
-  if (base::FeatureList::IsEnabled(features::kSkipBrowserTouchFilter) &&
+  if (base::FeatureList::IsEnabled(features::kSkipTouchEventFilter) &&
       GetFieldTrialParamValueByFeature(
-          features::kSkipBrowserTouchFilter,
-          features::kSkipBrowserTouchFilterFilteringProcessParamName) ==
+          features::kSkipTouchEventFilter,
+          features::kSkipTouchEventFilterFilteringProcessParamName) ==
           features::
-              kSkipBrowserTouchFilterFilteringProcessParamValueBrowserAndRenderer) {
+              kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer) {
     // Skipping filtering for touch events on renderer process is enabled.
     // Always skip filtering discrete events.
     skip_touch_filter_discrete_ = true;
     if (GetFieldTrialParamValueByFeature(
-            features::kSkipBrowserTouchFilter,
-            features::kSkipBrowserTouchFilterTypeParamName) ==
-        features::kSkipBrowserTouchFilterTypeParamValueAll) {
+            features::kSkipTouchEventFilter,
+            features::kSkipTouchEventFilterTypeParamName) ==
+        features::kSkipTouchEventFilterTypeParamValueAll) {
       // The experiment config also specifies to skip touchmove events.
       skip_touch_filter_all_ = true;
     }
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h
index 3275b97..8996c033 100644
--- a/ui/events/blink/input_handler_proxy.h
+++ b/ui/events/blink/input_handler_proxy.h
@@ -239,7 +239,7 @@
   // tests and to allow testing both Blink and CC input handling paths.
   bool force_input_to_main_thread_;
 
-  // These flags are set for the SkipBrowserTouchFilter experiment. The
+  // These flags are set for the SkipTouchEventFilter experiment. The
   // experiment either skips filtering discrete (touch start/end) events to the
   // main thread, or all events (touch start/end/move).
   bool skip_touch_filter_discrete_ = false;
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc
index 6f3741ac..8b27a254 100644
--- a/ui/gfx/color_transform.cc
+++ b/ui/gfx/color_transform.cc
@@ -13,7 +13,7 @@
 
 #include "base/logging.h"
 #include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/icc_profile.h"
 #include "ui/gfx/skia_color_space_util.h"
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc
index 49fb7cf..5a9c515 100644
--- a/ui/gfx/icc_profile.cc
+++ b/ui/gfx/icc_profile.cc
@@ -13,7 +13,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/synchronization/lock.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
-#include "third_party/skia/third_party/skcms/skcms.h"
+#include "third_party/skia/include/third_party/skcms/skcms.h"
 #include "ui/gfx/skia_color_space_util.h"
 
 namespace gfx {
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index c966b855..05999a9a 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -168,10 +168,13 @@
   return false;
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
 void PrefixSelector::SetCompositionFromExistingText(
     const gfx::Range& range,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+#endif
+
+#if defined(OS_WIN)
 void PrefixSelector::SetActiveCompositionForAccessibility(
     const gfx::Range& range,
     const base::string16& active_composition_text,
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h
index 69580d70..ffa961a 100644
--- a/ui/views/controls/prefix_selector.h
+++ b/ui/views/controls/prefix_selector.h
@@ -76,11 +76,13 @@
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
 
-#if defined(OS_WIN)
-  // Overridden from ui::TextInputClient(Windows only):
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
   void SetCompositionFromExistingText(
       const gfx::Range& range,
       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
+#endif
+
+#if defined(OS_WIN)
   void SetActiveCompositionForAccessibility(
       const gfx::Range& range,
       const base::string16& active_composition_text,
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index dddefc5..2eb217b 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1749,13 +1749,15 @@
   return false;
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
 // TODO(https://crbug.com/952355): Implement this method to support Korean IME reconversion feature
 // on native text fields (e.g. find bar).
 void Textfield::SetCompositionFromExistingText(
     const gfx::Range& range,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {}
+#endif
 
+#if defined(OS_WIN)
 // TODO(https://crbug.com/952355): Implement this method once TSF supports reconversion
 // features on native text fields.
 void Textfield::SetActiveCompositionForAccessibility(
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index d620fb1..7655af09 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -372,11 +372,13 @@
   ukm::SourceId GetClientSourceForMetrics() const override;
   bool ShouldDoLearning() override;
 
-#if defined(OS_WIN)
-  // Overridden from ui::TextInputClient(Windows only):
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
   void SetCompositionFromExistingText(
       const gfx::Range& range,
       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
+#endif
+
+#if defined(OS_WIN)
   void SetActiveCompositionForAccessibility(
       const gfx::Range& range,
       const base::string16& active_composition_text,
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 6e063b1..97c4075 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -425,6 +425,11 @@
   }
 
   if (visible_ != visible) {
+    // If the View is currently visible, schedule paint to refresh parent.
+    // TODO(beng): not sure we should be doing this if we have a layer.
+    if (visible_)
+      SchedulePaint();
+
     visible_ = visible;
     AdvanceFocusIfNecessary();
 
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 6c19974..2a38f66 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -420,7 +420,6 @@
     // only aura activation changes).
     aura::Window* active_window = activation_client->GetActiveWindow();
     if (active_window) {
-      base::AutoReset<bool> scoped(&is_handling_deactivation_, true);
       activation_client->DeactivateWindow(active_window);
       GetInputMethod()->OnBlur();
     }
@@ -1160,11 +1159,10 @@
   DCHECK(content_window_ == gained_active || content_window_ == lost_active);
   if (gained_active == content_window_ && restore_focus_on_activate_) {
     restore_focus_on_activate_ = false;
-    // For OS_LINUX, desktop native widget may be activated during deactivation
-    // when the active aura::Window is not |content_window_|. In such case,
-    // skip RestoreFocusedView so that we don't activate the widget immediately
-    // after its deactivation.
-    if (!is_handling_deactivation_)
+    // For OS_LINUX, desktop native widget may not be activated when child
+    // widgets gets aura activation changes. Only when desktop native widget is
+    // active, we can rely on aura activation to restore focused view.
+    if (GetWidget()->IsActive())
       GetWidget()->GetFocusManager()->RestoreFocusedView();
   } else if (lost_active == content_window_ && GetWidget()->HasFocusManager()) {
     DCHECK(!restore_focus_on_activate_);
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index bed6fa5..5d45002 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -321,16 +321,6 @@
   // See DesktopWindowTreeHost::ShouldUseDesktopNativeCursorManager().
   bool use_desktop_native_cursor_manager_ = false;
 
-  // Whether HandleActivationChanged is being called for deactivation. The
-  // current active aura::Window is deactivated in HandleActivationChanged.
-  // However, the current active window could be a sibling of |content_window_|
-  // (e.g. aura::Window of a child bubble widget such as browser window
-  // bubbles). The deactivation of such window would activate |content_window_|
-  // and could trigger RestoreFocusedView which could activate the widget. The
-  // flag is used to skip RestoreFocusedView to avoid activating the widget
-  // immediately after it is deactivated.
-  bool is_handling_deactivation_ = false;
-
   // The following factory is used for calls to close the NativeWidgetAura
   // instance.
   base::WeakPtrFactory<DesktopNativeWidgetAura> close_widget_factory_;