diff --git a/.gn b/.gn
index 00608b8..13648bd 100644
--- a/.gn
+++ b/.gn
@@ -212,9 +212,7 @@
   "//remoting:*",  # 27 errors
   "//sandbox/linux:*",  # 13 errors
   "//sandbox/mac:*",  # 14 errors
-  "//sandbox/policy:*",  # 1 error
   "//sandbox/win:*",  # 7 errors
-  "//sandbox:*",  # 3 errors
 
   # //third_party/blink/*, https://crbug.com/800764
   "//third_party/blink/common:*",  # 9 errors
diff --git a/AUTHORS b/AUTHORS
index 449705df2..5bfd0ce 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -612,6 +612,7 @@
 Luka Dojcilovic <l.dojcilovic@gmail.com>
 Lukasz Krakowiak <lukasz.krakowiak@mobica.com>
 Luke Inman-Semerau <luke.semerau@gmail.com>
+Luke Seunghoe Gu <gulukesh@gmail.com>
 Luke Zarko <lukezarko@gmail.com>
 Luoxi Pan <l.panpax@gmail.com>
 Maarten Lankhorst <m.b.lankhorst@gmail.com>
diff --git a/DEPS b/DEPS
index b614df8..71bb64a 100644
--- a/DEPS
+++ b/DEPS
@@ -199,7 +199,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'd72cb4c076b7113b667a706ddecb8f03695ca555',
+  'skia_revision': '9acf5844cae6cd48bc106ea9bf5a2b337c8d1d33',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -211,7 +211,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '45f54928a6280936f6a2f60aa7a413fb68292604',
+  'angle_revision': 'cc5513855cc5bed41612c5cadd60f665e24ccce5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -270,7 +270,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '832dab01db1d5995b096e83e209653e7487e962e',
+  'devtools_frontend_revision': '45fb1f2ebb99ec7146ad3f489831d9c39aa78f18',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -306,7 +306,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '7221ccf85e26a29459729b3d296b71346c538a94',
+  'spv_tools_revision': '680c77fa6c81ba03d19b3315d1cad116fc4e6da2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -322,7 +322,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'e8e089ad282e27d21c7bb426a73819d67266a3b3',
+  'dawn_revision': '450b6f4f844dab9417e54f08adf5b9d2ad30d1d7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -549,7 +549,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '3002e9a73f9b6c070495fc7f27d1cc183b8bdd4f',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'f2dd90e06cca99d66d4e33c99fad0d13180b1e04',
       'condition': 'checkout_ios',
   },
 
@@ -1252,7 +1252,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'df50009d3edec39cee9a7f5a59851701848fa32d',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f50a0fb8a663da54c9424fc3ba54bec9ebdf962a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1330,7 +1330,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'qH1GinMX67CP0YPwoB1xzpQVlBVVjqbDaNokFsY7Ax8C'
+              'version': 'bFZPJOh8GXPYKi1ZjDmJbS25G2gzmx-vLgGZ9Q4F82cC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1480,7 +1480,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '0c5f244817c22303d65811e6a25b3d97f8a08127',
+    Var('webrtc_git') + '/src.git' + '@' + 'd74c0e600a7f5bc43c2bcb75d4903b3038677459',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1552,7 +1552,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b150835596913d2051f12b3e60d8b12a38398f91',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@086c75fa39cf228f305c5689949c041d01634d92',
     'condition': 'checkout_src_internal',
   },
 
@@ -1560,7 +1560,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '1XLVSh3k-pIPAMRHWfJCplE490YVs_aTLs81WqTGqUgC',
+        'version': 'vqT-WqhwS504vwcLdBC9Y998VXTrAydEbVVHCjdZSPMC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 19ef421..7f5a2f3a 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -29,9 +29,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/i18n/rtl.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/path_service.h"
+#include "base/task/current_thread.h"
 #include "components/crash/content/browser/child_exit_observer_android.h"
 #include "components/crash/core/common/crash_key.h"
 #include "components/embedder_support/android/metrics/memory_metrics_logger.h"
@@ -75,7 +75,7 @@
 
   // Creates a SingleThreadTaskExecutor for Android WebView if doesn't exist.
   DCHECK(!main_task_executor_.get());
-  if (!base::MessageLoopCurrent::IsSet()) {
+  if (!base::CurrentThread::IsSet()) {
     main_task_executor_ = std::make_unique<base::SingleThreadTaskExecutor>(
         base::MessagePumpType::UI);
   }
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
index 10521eb4..5d54028b 100644
--- a/android_webview/browser/aw_browser_terminator.cc
+++ b/android_webview/browser/aw_browser_terminator.cc
@@ -72,7 +72,7 @@
     switch (delegate->OnRenderProcessGone(child_process_pid, crashed)) {
       case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kException:
         // Let the exception propagate back to the message loop.
-        base::MessageLoopCurrentForUI::Get()->Abort();
+        base::CurrentUIThread::Get()->Abort();
         return;
       case AwRenderProcessGoneDelegate::RenderProcessGoneResult::kUnhandled:
         if (crashed) {
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc
index f5aa3cd..1bd2d18 100644
--- a/android_webview/browser/aw_contents_client_bridge.cc
+++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -15,7 +15,7 @@
 #include "base/android/jni_string.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/client_certificate_delegate.h"
 #include "content/public/browser/render_frame_host.h"
@@ -386,7 +386,7 @@
     // Tell the chromium message loop to not perform any tasks after the current
     // one - we want to make sure we return to Java cleanly without first making
     // any new JNI calls.
-    base::MessageLoopCurrentForUI::Get()->Abort();
+    base::CurrentUIThread::Get()->Abort();
     // If we crashed we don't want to continue the navigation.
     *ignore_navigation = true;
     return false;
diff --git a/android_webview/browser/aw_proxy_controller.cc b/android_webview/browser/aw_proxy_controller.cc
index 003d55b..753ac7f9 100644
--- a/android_webview/browser/aw_proxy_controller.cc
+++ b/android_webview/browser/aw_proxy_controller.cc
@@ -12,7 +12,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/feature_list.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/proxy_resolution/proxy_config_service_android.h"
 
@@ -40,7 +40,7 @@
     // Tell the chromium message loop to not perform any tasks after the current
     // one - we want to make sure we return to Java cleanly without first making
     // any new JNI calls.
-    base::MessageLoopCurrentForUI::Get()->Abort();
+    base::CurrentUIThread::Get()->Abort();
   }
 }
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 35df6143..5e947c3 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2596,6 +2596,7 @@
     # TODO(https://crbug.com/644336): Remove dependencies on CrasAudioClient.
     "//chromeos/dbus/audio",
     "//chromeos/dbus/power",
+    "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/dbus/system_clock",
 
     # TODO(https://crbug.com/644355): Remove Shill dependencies.
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc
index 43f6a4af4..70b8476f 100644
--- a/ash/ambient/ambient_controller.cc
+++ b/ash/ambient/ambient_controller.cc
@@ -32,6 +32,7 @@
 #include "chromeos/assistant/buildflags.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "ui/base/ui_base_types.h"
@@ -339,6 +340,20 @@
   }
 }
 
+void AmbientController::ScreenIdleStateChanged(
+    const power_manager::ScreenIdleState& idle_state) {
+  if (!IsUiClosed(ambient_ui_model_.ui_visibility()))
+    return;
+
+  auto* session_controller = Shell::Get()->session_controller();
+  if (idle_state.dimmed() && !session_controller->IsScreenLocked() &&
+      session_controller->CanLockScreen()) {
+    // TODO(b/161469136): revise this behavior after further discussion.
+    // Locks the device when screen is dimmed to start ambient screen.
+    Shell::Get()->session_controller()->LockScreen();
+  }
+}
+
 void AmbientController::AddAmbientViewDelegateObserver(
     AmbientViewDelegateObserver* observer) {
   delegate_.AddObserver(observer);
@@ -458,7 +473,7 @@
 
   // Enables auto-show and starts the timer.
   autoshow_enabled_ = true;
-  if (LockScreen::HasInstance()) {
+  if (!inactivity_monitor_ && LockScreen::HasInstance()) {
     inactivity_monitor_ = std::make_unique<InactivityMonitor>(
         LockScreen::Get()->widget()->GetWeakPtr(),
         base::BindOnce(&AmbientController::OnAutoShowTimeOut,
diff --git a/ash/ambient/ambient_controller.h b/ash/ambient/ambient_controller.h
index 3a4efde..88f26c3 100644
--- a/ash/ambient/ambient_controller.h
+++ b/ash/ambient/ambient_controller.h
@@ -61,6 +61,8 @@
                         const base::TimeTicks& timestamp) override;
   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
+  void ScreenIdleStateChanged(
+      const power_manager::ScreenIdleState& idle_state) override;
 
   void AddAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer);
   void RemoveAmbientViewDelegateObserver(AmbientViewDelegateObserver* observer);
diff --git a/ash/ambient/ambient_controller_unittest.cc b/ash/ambient/ambient_controller_unittest.cc
index 1ffc946..3243df5 100644
--- a/ash/ambient/ambient_controller_unittest.cc
+++ b/ash/ambient/ambient_controller_unittest.cc
@@ -313,4 +313,16 @@
                    device::mojom::WakeLockType::kPreventDisplaySleep));
 }
 
+TEST_F(AmbientControllerTest, ShouldShowAmbientScreenWhenScreenIsDimmed) {
+  EXPECT_FALSE(ambient_controller()->IsShown());
+
+  // Should lock the device and enter ambient mode when the screen is dimmed.
+  SetScreenDimmedAndWait(true);
+
+  EXPECT_TRUE(ambient_controller()->IsShown());
+
+  // Closes ambient for clean-up.
+  CloseAmbientScreen();
+}
+
 }  // namespace ash
diff --git a/ash/ambient/test/ambient_ash_test_base.cc b/ash/ambient/test/ambient_ash_test_base.cc
index 3cd026d..5f2de2f 100644
--- a/ash/ambient/test/ambient_ash_test_base.cc
+++ b/ash/ambient/test/ambient_ash_test_base.cc
@@ -23,6 +23,7 @@
 #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/dbus/power_manager/idle.pb.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
@@ -138,6 +139,14 @@
   base::RunLoop().RunUntilIdle();
 }
 
+void AmbientAshTestBase::SetScreenDimmedAndWait(bool is_screen_dimmed) {
+  power_manager::ScreenIdleState screen_idle_state;
+  screen_idle_state.set_dimmed(is_screen_dimmed);
+  chromeos::FakePowerManagerClient::Get()->SendScreenIdleStateChanged(
+      screen_idle_state);
+  base::RunLoop().RunUntilIdle();
+}
+
 void AmbientAshTestBase::SetPhotoViewImageSize(int width, int height) {
   auto* image_decoder = static_cast<TestAmbientImageDecoderImpl*>(
       ambient_controller()
diff --git a/ash/ambient/test/ambient_ash_test_base.h b/ash/ambient/test/ambient_ash_test_base.h
index bfaa676..b8e7663 100644
--- a/ash/ambient/test/ambient_ash_test_base.h
+++ b/ash/ambient/test/ambient_ash_test_base.h
@@ -57,6 +57,10 @@
   // Wait until the event has been processed.
   void SimulateSystemResumeAndWait();
 
+  // Simulates a screen dimmed event.
+  // Wait until the event has been processed.
+  void SetScreenDimmedAndWait(bool is_screen_dimmed);
+
   // Set the size of the next image that will be loaded.
   void SetPhotoViewImageSize(int width, int height);
 
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 2c7150f..b8f75cb 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -26,9 +26,9 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/task_observer.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
@@ -220,12 +220,12 @@
 void RunAllTasksUntilIdle() {
   while (true) {
     TaskObserver task_observer;
-    base::MessageLoopCurrent::Get()->AddTaskObserver(&task_observer);
+    base::CurrentThread::Get()->AddTaskObserver(&task_observer);
     // May spin message loop.
     base::ThreadPoolInstance::Get()->FlushForTesting();
 
     base::RunLoop().RunUntilIdle();
-    base::MessageLoopCurrent::Get()->RemoveTaskObserver(&task_observer);
+    base::CurrentThread::Get()->RemoveTaskObserver(&task_observer);
 
     if (!task_observer.processed())
       break;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 19b9983..f9e4c5bb 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -368,7 +368,6 @@
     "memory/weak_ptr.h",
     "memory/writable_shared_memory_region.cc",
     "memory/writable_shared_memory_region.h",
-    "message_loop/message_loop_current.h",
     "message_loop/message_pump.cc",
     "message_loop/message_pump.h",
     "message_loop/message_pump_default.cc",
@@ -1747,6 +1746,7 @@
         "allocator/partition_allocator/address_pool_manager.h",
         "allocator/partition_allocator/address_space_randomization.cc",
         "allocator/partition_allocator/address_space_randomization.h",
+        "allocator/partition_allocator/checked_ptr_support.h",
         "allocator/partition_allocator/memory_reclaimer.cc",
         "allocator/partition_allocator/memory_reclaimer.h",
         "allocator/partition_allocator/oom.h",
diff --git a/base/allocator/partition_allocator/checked_ptr_support.h b/base/allocator/partition_allocator/checked_ptr_support.h
new file mode 100644
index 0000000..1322427
--- /dev/null
+++ b/base/allocator/partition_allocator/checked_ptr_support.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_CHECKED_PTR_SUPPORT_H_
+#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_CHECKED_PTR_SUPPORT_H_
+
+#define ENABLE_TAG_FOR_CHECKED_PTR2 0
+#define ENABLE_TAG_FOR_MTE_CHECKED_PTR 0
+
+#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_CHECKED_PTR_SUPPORT_H_
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 96bc8571..405de1c 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -71,8 +71,13 @@
                   (1UL << 31) + kPageAllocationGranularity,
               "maximum direct mapped allocation");
 // Check that some of our zanier calculations worked out as expected.
+#if !ENABLE_TAG_FOR_MTE_CHECKED_PTR
 static_assert(kGenericSmallestBucket == alignof(std::max_align_t),
               "generic smallest bucket");
+#else
+static_assert(kGenericSmallestBucket >= alignof(std::max_align_t),
+              "generic smallest bucket");
+#endif
 static_assert(kGenericMaxBucketed == 983040, "generic max bucketed");
 static_assert(kMaxSystemPagesPerSlotSpan < (1 << 8),
               "System pages per slot span must be less than 128.");
@@ -826,11 +831,10 @@
       &partition_root_);
 }
 
-template void PartitionAllocator<internal::ThreadSafe>::~PartitionAllocator();
+template PartitionAllocator<internal::ThreadSafe>::~PartitionAllocator();
 template void PartitionAllocator<internal::ThreadSafe>::init(
     PartitionAllocatorAlignment alignment);
-template void
-    PartitionAllocator<internal::NotThreadSafe>::~PartitionAllocator();
+template PartitionAllocator<internal::NotThreadSafe>::~PartitionAllocator();
 template void PartitionAllocator<internal::NotThreadSafe>::init(
     PartitionAllocatorAlignment alignment);
 
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index 55dfc1d0..cc54b49 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -598,7 +598,8 @@
   }
 
   if (allow_extras && !bucket->is_direct_mapped()) {
-    internal::PartitionTagSetValue(ret, GetNewPartitionTag());
+    internal::PartitionTagSetValue(ret, page->bucket->slot_size,
+                                   GetNewPartitionTag());
   }
 
   return ret;
@@ -625,7 +626,7 @@
   auto* root = PartitionRoot<thread_safe>::FromPage(page);
   if (root->allow_extras && !page->bucket->is_direct_mapped()) {
     // TODO(tasak): clear partition tag. Temporarily set the tag to be 0.
-    internal::PartitionTagClearValue(ptr);
+    internal::PartitionTagClearValue(ptr, page->bucket->slot_size);
   }
   ptr = internal::PartitionPointerAdjustSubtract(root->allow_extras, ptr);
   internal::DeferredUnmap deferred_unmap;
diff --git a/base/allocator/partition_allocator/partition_alloc_constants.h b/base/allocator/partition_allocator/partition_alloc_constants.h
index 855b8138..625ca4e 100644
--- a/base/allocator/partition_allocator/partition_alloc_constants.h
+++ b/base/allocator/partition_allocator/partition_alloc_constants.h
@@ -8,6 +8,7 @@
 #include <limits.h>
 #include <cstddef>
 
+#include "base/allocator/partition_allocator/checked_ptr_support.h"
 #include "base/allocator/partition_allocator/page_allocator_constants.h"
 
 #include "build/build_config.h"
@@ -152,8 +153,13 @@
 //
 // In practice, this means 8 bytes alignment on 32 bit architectures, and 16
 // bytes on 64 bit ones.
+#if ENABLE_TAG_FOR_MTE_CHECKED_PTR
+// MTECheckedPtr requires 16B-alignment because kBytesPerPartitionTag is 16.
+static const size_t kGenericMinBucketedOrder = 5;
+#else
 static const size_t kGenericMinBucketedOrder =
     alignof(std::max_align_t) == 16 ? 5 : 4;  // 2^(order - 1), that is 16 or 8.
+#endif
 // The largest bucketed order is 1 << (20 - 1), storing [512 KiB, 1 MiB):
 static const size_t kGenericMaxBucketedOrder = 20;
 static const size_t kGenericNumBucketedOrders =
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index eeb1c7c7..02d413f 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -2515,9 +2515,9 @@
   constexpr PartitionTag kTag1 = static_cast<PartitionTag>(0xBADA);
   constexpr PartitionTag kTag2 = static_cast<PartitionTag>(0xDB8A);
   constexpr PartitionTag kTag3 = static_cast<PartitionTag>(0xA3C4);
-  PartitionTagSetValue(ptr1, kTag1);
-  PartitionTagSetValue(ptr2, kTag2);
-  PartitionTagSetValue(ptr3, kTag3);
+  PartitionTagSetValue(ptr1, page->bucket->slot_size, kTag1);
+  PartitionTagSetValue(ptr2, page->bucket->slot_size, kTag2);
+  PartitionTagSetValue(ptr3, page->bucket->slot_size, kTag3);
 
   memset(ptr1, 0, kTestAllocSize);
   memset(ptr2, 0, kTestAllocSize);
diff --git a/base/allocator/partition_allocator/partition_tag.h b/base/allocator/partition_allocator/partition_tag.h
index 11bf9b5..11de3c7 100644
--- a/base/allocator/partition_allocator/partition_tag.h
+++ b/base/allocator/partition_allocator/partition_tag.h
@@ -5,6 +5,8 @@
 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_
 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_
 
+#include <string.h>
+
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 #include "base/allocator/partition_allocator/partition_cookie.h"
 #include "base/allocator/partition_allocator/partition_tag_bitmap.h"
@@ -61,7 +63,7 @@
                                  kInSlotTagBufferSize);
 }
 
-ALWAYS_INLINE void PartitionTagSetValue(void* ptr, PartitionTag value) {
+ALWAYS_INLINE void PartitionTagSetValue(void* ptr, size_t, PartitionTag value) {
   *PartitionTagPointer(ptr) = value;
 }
 
@@ -69,7 +71,7 @@
   return *PartitionTagPointer(ptr);
 }
 
-ALWAYS_INLINE void PartitionTagClearValue(void* ptr) {
+ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t) {
   PA_DCHECK(PartitionTagGetValue(ptr));
   *PartitionTagPointer(ptr) = 0;
 }
@@ -122,20 +124,32 @@
   return ptr;
 }
 
-ALWAYS_INLINE void PartitionTagSetValue(void* ptr, PartitionTag value) {
-  *PartitionTagPointer(ptr) = value;
+ALWAYS_INLINE void PartitionTagSetValue(void* ptr,
+                                        size_t size,
+                                        PartitionTag value) {
+  PA_DCHECK((size % tag_bitmap::kBytesPerPartitionTag) == 0);
+  size_t tag_count = size >> tag_bitmap::kBytesPerPartitionTagShift;
+  PartitionTag* tag_ptr = PartitionTagPointer(ptr);
+  if (sizeof(PartitionTag) == 1) {
+    memset(tag_ptr, value, tag_count);
+  } else {
+    while (tag_count-- > 0)
+      *tag_ptr++ = value;
+  }
 }
 
 ALWAYS_INLINE PartitionTag PartitionTagGetValue(void* ptr) {
   return *PartitionTagPointer(ptr);
 }
 
-ALWAYS_INLINE void PartitionTagClearValue(void* ptr) {
-  PA_DCHECK(PartitionTagGetValue(ptr));
-  *PartitionTagPointer(ptr) = 0;
+ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t size) {
+  size_t tag_region_size = size >> tag_bitmap::kBytesPerPartitionTagShift
+                                       << tag_bitmap::kPartitionTagSizeShift;
+  PA_DCHECK(!memchr(PartitionTagPointer(ptr), 0, tag_region_size));
+  memset(PartitionTagPointer(ptr), 0, tag_region_size);
 }
 
-#else  // !ENABLE_TAG_FOR_CHECKED_PTR2
+#else  // !ENABLE_TAG_FOR_CHECKED_PTR2 && !ENABLE_TAG_FOR_MTE_CHECKED_PTR
 
 using PartitionTag = uint16_t;
 
@@ -163,13 +177,13 @@
   return ptr;
 }
 
-ALWAYS_INLINE void PartitionTagSetValue(void*, PartitionTag) {}
+ALWAYS_INLINE void PartitionTagSetValue(void*, size_t, PartitionTag) {}
 
 ALWAYS_INLINE PartitionTag PartitionTagGetValue(void*) {
   return 0;
 }
 
-ALWAYS_INLINE void PartitionTagClearValue(void* ptr) {}
+ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t) {}
 
 #endif  // !ENABLE_TAG_FOR_CHECKED_PTR2
 
diff --git a/base/allocator/partition_allocator/partition_tag_bitmap.h b/base/allocator/partition_allocator/partition_tag_bitmap.h
index 69740b4a..5392a8be 100644
--- a/base/allocator/partition_allocator/partition_tag_bitmap.h
+++ b/base/allocator/partition_allocator/partition_tag_bitmap.h
@@ -5,17 +5,14 @@
 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_
 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_
 
+#include "base/allocator/partition_allocator/checked_ptr_support.h"
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 
-#define ENABLE_TAG_FOR_CHECKED_PTR2 0
-#define ENABLE_TAG_FOR_MTE_CHECKED_PTR 0
-
 namespace base {
 
 namespace internal {
 
 #if ENABLE_TAG_FOR_MTE_CHECKED_PTR
-#undef ENABLE_TAG_FOR_CHECKED_PTR2
 
 // Normal bucket layout
 // +----------------+ super_page_base
@@ -62,6 +59,9 @@
 //  +-----------+ slot_size
 static constexpr size_t kBytesPerPartitionTag = 1U
                                                 << kBytesPerPartitionTagShift;
+static_assert(
+    kGenericMinBucketedOrder >= kBytesPerPartitionTagShift + 1,
+    "MTECheckedPtr requires kBytesPerPartitionTagShift-bytes alignment.");
 
 static constexpr size_t kBytesPerPartitionTagRatio =
     kBytesPerPartitionTag / kPartitionTagSize;
diff --git a/base/files/file_descriptor_watcher_posix.cc b/base/files/file_descriptor_watcher_posix.cc
index be430632..0eaef1e 100644
--- a/base/files/file_descriptor_watcher_posix.cc
+++ b/base/files/file_descriptor_watcher_posix.cc
@@ -9,12 +9,12 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/no_destructor.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_checker.h"
 #include "base/threading/thread_local.h"
@@ -34,7 +34,7 @@
 
 class FileDescriptorWatcher::Controller::Watcher
     : public MessagePumpForIO::FdWatcher,
-      public MessageLoopCurrent::DestructionObserver {
+      public CurrentThread::DestructionObserver {
  public:
   Watcher(WeakPtr<Controller> controller, MessagePumpForIO::Mode mode, int fd);
   ~Watcher() override;
@@ -48,7 +48,7 @@
   void OnFileCanReadWithoutBlocking(int fd) override;
   void OnFileCanWriteWithoutBlocking(int fd) override;
 
-  // MessageLoopCurrent::DestructionObserver:
+  // CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override;
 
   // The MessagePumpForIO's watch handle (stops the watch when destroyed).
@@ -96,20 +96,19 @@
 
 FileDescriptorWatcher::Controller::Watcher::~Watcher() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  MessageLoopCurrentForIO::Get()->RemoveDestructionObserver(this);
+  CurrentIOThread::Get()->RemoveDestructionObserver(this);
 }
 
 void FileDescriptorWatcher::Controller::Watcher::StartWatching() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(MessageLoopCurrentForIO::IsSet());
+  DCHECK(CurrentIOThread::IsSet());
 
-  const bool watch_success =
-      MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
-          fd_, false, mode_, &fd_watch_controller_, this);
+  const bool watch_success = CurrentIOThread::Get()->WatchFileDescriptor(
+      fd_, false, mode_, &fd_watch_controller_, this);
   DCHECK(watch_success) << "Failed to watch fd=" << fd_;
 
   if (!registered_as_destruction_observer_) {
-    MessageLoopCurrentForIO::Get()->AddDestructionObserver(this);
+    CurrentIOThread::Get()->AddDestructionObserver(this);
     registered_as_destruction_observer_ = true;
   }
 }
diff --git a/base/message_loop/fd_watch_controller_posix_unittest.cc b/base/message_loop/fd_watch_controller_posix_unittest.cc
index 9e2e297..812ee5f5 100644
--- a/base/message_loop/fd_watch_controller_posix_unittest.cc
+++ b/base/message_loop/fd_watch_controller_posix_unittest.cc
@@ -12,10 +12,10 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/gtest_util.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
@@ -137,9 +137,9 @@
   {
     test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
 
-    MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
-        write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
-        &handler);
+    CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
+                                                MessagePumpForIO::WATCH_WRITE,
+                                                &watcher, &handler);
     // Don't run the message loop, just destroy it.
   }
 
@@ -156,9 +156,9 @@
     MessagePumpForIO::FdWatchController watcher(FROM_HERE);
 
     TestHandler handler;
-    MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
-        write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
-        &handler);
+    CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
+                                                MessagePumpForIO::WATCH_WRITE,
+                                                &watcher, &handler);
     ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
     ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
   }
@@ -173,7 +173,7 @@
   handler.watcher_to_delete_ =
       std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
 
-  MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  CurrentIOThread::Get()->WatchFileDescriptor(
       write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
       handler.watcher_to_delete_.get(), &handler);
   RunLoop().Run();
@@ -281,7 +281,7 @@
   // The triggered read will cause the watcher action to run. |one| would
   // also be immediately available for writing, so this should not cause a
   // use-after-free on the |handler|.
-  MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  CurrentIOThread::Get()->WatchFileDescriptor(
       one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
       handler->controller(), handler);
   run_loop.Run();
@@ -314,7 +314,7 @@
   // should cause both the read and write watchers to be triggered. The
   // |handler| will do its action in response to the write event, which should
   // not trigger a use-after-free for the second read that was queued.
-  MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  CurrentIOThread::Get()->WatchFileDescriptor(
       one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
       handler->controller(), handler);
   run_loop.Run();
@@ -331,7 +331,7 @@
   TestHandler handler;
 
   // Watch the pipe for readability.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -357,7 +357,7 @@
   TestHandler handler;
 
   // Watch the pipe for writability.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
       &watcher, &handler));
 
@@ -380,7 +380,7 @@
   TestHandler handler;
 
   // Watch the pipe for readability.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -409,7 +409,7 @@
                              OnceClosure());
 
   // Create persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -430,7 +430,7 @@
   CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
 
   // Create a non-persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -451,7 +451,7 @@
   CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
 
   // Create persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -473,7 +473,7 @@
                                RunLoop* run_loop) {
   controller->StopWatchingFileDescriptor();
 
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
       new_handler));
 
@@ -493,7 +493,7 @@
                               OnceClosure());
 
   // Create persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
       &watcher, &handler1));
 
@@ -520,7 +520,7 @@
   CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
 
   // Create a non-persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
@@ -551,7 +551,7 @@
   CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
 
   // Create a non-persistent watcher.
-  ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
       read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
       &watcher, &handler));
 
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h
deleted file mode 100644
index 947c8de..0000000
--- a/base/message_loop/message_loop_current.h
+++ /dev/null
@@ -1,26 +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_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
-#define BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
-
-#include "base/task/current_thread.h"
-#include "build/build_config.h"
-
-// MessageLoopCurrent, MessageLoopCurrentForIO, and MessageLoopCurrentForUI are
-// being replaced by CurrentThread, CurrentIOThread, and CurrentUIThread
-// respectively (https://crbug.com/891670). You should no longer include this
-// header nor use these classes. This file will go away as soon as we have
-// migrated all uses.
-
-namespace base {
-using MessageLoopCurrent = CurrentThread;
-using MessageLoopCurrentForIO = CurrentIOThread;
-
-#if !defined(OS_NACL)
-using MessageLoopCurrentForUI = CurrentUIThread;
-#endif
-}  // namespace base
-
-#endif  // BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc
index c1da85c..1599847 100644
--- a/base/message_loop/message_pump_glib_unittest.cc
+++ b/base/message_loop/message_pump_glib_unittest.cc
@@ -18,13 +18,13 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/synchronization/waitable_event_watcher.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
@@ -472,7 +472,7 @@
 
   // Run a nested, straight GLib message loop.
   {
-    MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks;
+    CurrentThread::ScopedNestableTaskAllower allow_nestable_tasks;
     runner->RunGLib();
   }
 
@@ -506,7 +506,7 @@
 
   // Run a nested, straight Gtk message loop.
   {
-    MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks;
+    CurrentThread::ScopedNestableTaskAllower allow_nestable_tasks;
     runner->RunLoop();
   }
 
@@ -745,7 +745,7 @@
                           Unretained(watcher.get()), &event,
                           std::move(write_fd_task), io_runner()));
 
-  // Queue |event| to signal on |MessageLoopCurrentForUI::Get()|.
+  // Queue |event| to signal on |CurrentUIThread::Get()|.
   ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&event)));
 
diff --git a/base/message_loop/message_pump_mac_unittest.mm b/base/message_loop/message_pump_mac_unittest.mm
index 840a3f5f..942ab8a3 100644
--- a/base/message_loop/message_pump_mac_unittest.mm
+++ b/base/message_loop/message_pump_mac_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -38,7 +38,7 @@
 // This function posts |task| and runs the given |mode|.
 void RunTaskInMode(CFRunLoopMode mode, OnceClosure task) {
   // Since this task is "ours" rather than a system task, allow nesting.
-  MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  CurrentThread::ScopedNestableTaskAllower allow;
   CancelableOnceClosure cancelable(std::move(task));
   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancelable.callback());
   while (CFRunLoopRunInMode(mode, 0, true) == kCFRunLoopRunHandledSource)
@@ -133,7 +133,7 @@
   RunLoop run_loop;
   ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindLambdaForTesting([&] {
-        MessageLoopCurrent::ScopedNestableTaskAllower allow;
+        CurrentThread::ScopedNestableTaskAllower allow;
         ScopedPumpMessagesInPrivateModes pump_private;
         [NSApp runModalForWindow:window];
       }));
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc
index 10f05af..1eadb24 100644
--- a/base/message_loop/message_pump_perftest.cc
+++ b/base/message_loop/message_pump_perftest.cc
@@ -9,13 +9,13 @@
 #include "base/bind_helpers.h"
 #include "base/format_macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
@@ -191,7 +191,7 @@
           java_thread_->state()->sequence_manager.get());
     }
 #endif
-    return MessageLoopCurrent::Get()->GetCurrentSequenceManagerImpl();
+    return CurrentThread::Get()->GetCurrentSequenceManagerImpl();
   }
 
  private:
diff --git a/base/power_monitor/power_monitor_device_source_win.cc b/base/power_monitor/power_monitor_device_source_win.cc
index ba30941..309824b7 100644
--- a/base/power_monitor/power_monitor_device_source_win.cc
+++ b/base/power_monitor/power_monitor_device_source_win.cc
@@ -5,11 +5,11 @@
 #include "base/power_monitor/power_monitor_device_source.h"
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/win/wrapped_window_proc.h"
 
 namespace base {
@@ -68,7 +68,7 @@
 
 PowerMonitorDeviceSource::PowerMessageWindow::PowerMessageWindow()
     : instance_(NULL), message_hwnd_(NULL) {
-  if (!MessageLoopCurrentForUI::IsSet()) {
+  if (!CurrentUIThread::IsSet()) {
     // Creating this window in (e.g.) a renderer inhibits shutdown on Windows.
     // See http://crbug.com/230122. TODO(vandebo): http://crbug.com/236031
     DLOG(ERROR)
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index f05a470d..9d89120 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/location.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_default.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/optional.h"
@@ -27,6 +26,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/real_time_domain.h"
 #include "base/task/sequence_manager/sequence_manager.h"
 #include "base/task/sequence_manager/task_queue.h"
@@ -4264,7 +4264,7 @@
   bool* destruction_observer_called_;
 };
 
-class SMDestructionObserver : public MessageLoopCurrent::DestructionObserver {
+class SMDestructionObserver : public CurrentThread::DestructionObserver {
  public:
   SMDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
       : task_destroyed_(task_destroyed),
diff --git a/base/task/single_thread_task_executor_unittest.cc b/base/task/single_thread_task_executor_unittest.cc
index df91620..2b21d10 100644
--- a/base/task/single_thread_task_executor_unittest.cc
+++ b/base/task/single_thread_task_executor_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/pending_task.h"
@@ -24,6 +23,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/task_observer.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
@@ -304,7 +304,7 @@
 #if defined(OS_WIN)
 
 void SubPumpFunc(OnceClosure on_done) {
-  MessageLoopCurrent::ScopedAllowApplicationTasksInNativeNestedLoop
+  CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
       allow_nestable_tasks;
   MSG msg;
   while (::GetMessage(&msg, NULL, 0, 0)) {
@@ -321,7 +321,7 @@
 // can cause implicit message loops.
 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
   order->RecordStart(MESSAGEBOX, cookie);
-  Optional<MessageLoopCurrent::ScopedAllowApplicationTasksInNativeNestedLoop>
+  Optional<CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop>
       maybe_allow_nesting;
   if (is_reentrant)
     maybe_allow_nesting.emplace();
@@ -428,7 +428,7 @@
 }
 
 void TestIOHandler::Init() {
-  MessageLoopCurrentForIO::Get()->RegisterIOHandler(file_.Get(), this);
+  CurrentIOThread::Get()->RegisterIOHandler(file_.Get(), this);
 
   DWORD read;
   EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
@@ -445,8 +445,8 @@
 }
 
 void TestIOHandler::WaitForIO() {
-  EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(300, this));
-  EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(400, this));
+  EXPECT_TRUE(CurrentIOThread::Get()->WaitForIOCompletion(300, this));
+  EXPECT_TRUE(CurrentIOThread::Get()->WaitForIOCompletion(400, this));
 }
 
 void RunTest_IOHandler() {
@@ -1338,7 +1338,7 @@
 
 TEST_P(SingleThreadTaskExecutorTypedTest, NestableTasksAllowedAtTopLevel) {
   SingleThreadTaskExecutor executor(GetParam());
-  EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+  EXPECT_TRUE(CurrentThread::Get()->NestableTasksAllowed());
 }
 
 // Nestable tasks shouldn't be allowed to run reentrantly by default (regression
@@ -1350,7 +1350,7 @@
       FROM_HERE,
       BindOnce(
           [](RunLoop* run_loop) {
-            EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+            EXPECT_FALSE(CurrentThread::Get()->NestableTasksAllowed());
             run_loop->Quit();
           },
           Unretained(&run_loop)));
@@ -1379,7 +1379,7 @@
                       // nestable tasks are by default disallowed from this
                       // layer.
                       EXPECT_FALSE(
-                          MessageLoopCurrent::Get()->NestableTasksAllowed());
+                          CurrentThread::Get()->NestableTasksAllowed());
                       nested_run_loop->Quit();
                     },
                     Unretained(&nested_run_loop)));
@@ -1400,11 +1400,11 @@
       BindOnce(
           [](RunLoop* run_loop) {
             {
-              MessageLoopCurrent::ScopedAllowApplicationTasksInNativeNestedLoop
+              CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
                   allow_nestable_tasks;
-              EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+              EXPECT_TRUE(CurrentThread::Get()->NestableTasksAllowed());
             }
-            EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
+            EXPECT_FALSE(CurrentThread::Get()->NestableTasksAllowed());
             run_loop->Quit();
           },
           Unretained(&run_loop)));
@@ -1413,22 +1413,22 @@
 
 TEST_P(SingleThreadTaskExecutorTypedTest, IsIdleForTesting) {
   SingleThreadTaskExecutor executor(GetParam());
-  EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
   executor.task_runner()->PostTask(FROM_HERE, BindOnce([]() {}));
   executor.task_runner()->PostDelayedTask(FROM_HERE, BindOnce([]() {}),
                                           TimeDelta::FromMilliseconds(10));
-  EXPECT_FALSE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_FALSE(CurrentThread::Get()->IsIdleForTesting());
   RunLoop().RunUntilIdle();
-  EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
 
   PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));
-  EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
 }
 
 TEST_P(SingleThreadTaskExecutorTypedTest, IsIdleForTestingNonNestableTask) {
   SingleThreadTaskExecutor executor(GetParam());
   RunLoop run_loop;
-  EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
   bool nested_task_run = false;
   executor.task_runner()->PostTask(
       FROM_HERE, BindLambdaForTesting([&]() {
@@ -1440,18 +1440,18 @@
         executor.task_runner()->PostTask(
             FROM_HERE, BindLambdaForTesting([&]() {
               EXPECT_FALSE(nested_task_run);
-              EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+              EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
             }));
 
         nested_run_loop.RunUntilIdle();
         EXPECT_FALSE(nested_task_run);
-        EXPECT_FALSE(MessageLoopCurrent::Get()->IsIdleForTesting());
+        EXPECT_FALSE(CurrentThread::Get()->IsIdleForTesting());
       }));
 
   run_loop.RunUntilIdle();
 
   EXPECT_TRUE(nested_task_run);
-  EXPECT_TRUE(MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
@@ -1706,7 +1706,7 @@
   // This test ensures that application tasks are being processed by the native
   // subpump despite the kMsgHaveWork event having already been consumed by the
   // time the subpump is entered. This is subtly enforced by
-  // MessageLoopCurrent::ScopedAllowApplicationTasksInNativeNestedLoop which
+  // CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop which
   // will ScheduleWork() upon construction (and if it's absent, the
   // SingleThreadTaskExecutor shouldn't process application tasks so
   // kMsgHaveWork is irrelevant). Note: This test also fails prior to the fix
@@ -1959,7 +1959,7 @@
   bool* destruction_observer_called_;
 };
 
-class MLDestructionObserver : public MessageLoopCurrent::DestructionObserver {
+class MLDestructionObserver : public CurrentThread::DestructionObserver {
  public:
   MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
       : task_destroyed_(task_destroyed),
@@ -1991,7 +1991,7 @@
   bool destruction_observer_called = false;
 
   MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
-  MessageLoopCurrent::Get()->AddDestructionObserver(&observer);
+  CurrentThread::Get()->AddDestructionObserver(&observer);
   executor->task_runner()->PostDelayedTask(
       FROM_HERE,
       BindOnce(&DestructionObserverProbe::Run,
@@ -2078,7 +2078,7 @@
     case 2:
       // Since we're about to enter a modal loop, tell the message loop that we
       // intend to nest tasks.
-      MessageLoopCurrent::ScopedAllowApplicationTasksInNativeNestedLoop
+      CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
           allow_nestable_tasks;
       bool did_run = false;
       ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/base/test/android/java_handler_thread_helpers.cc b/base/test/android/java_handler_thread_helpers.cc
index d69673e9..b37de785 100644
--- a/base/test/android/java_handler_thread_helpers.cc
+++ b/base/test/android/java_handler_thread_helpers.cc
@@ -5,8 +5,8 @@
 #include "base/test/android/java_handler_thread_helpers.h"
 
 #include "base/android/java_handler_thread.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/test/base_unittests_jni_headers/JavaHandlerThreadHelpers_jni.h"
 
 namespace base {
@@ -24,7 +24,7 @@
   JNIEnv* env = AttachCurrentThread();
   Java_JavaHandlerThreadHelpers_throwException(env);
   DCHECK(HasException(env));
-  base::MessageLoopCurrentForUI::Get()->Abort();
+  base::CurrentUIThread::Get()->Abort();
   event->Signal();
 }
 
diff --git a/base/test/power_monitor_test_base.cc b/base/test/power_monitor_test_base.cc
index 6dbc3aef7..f66c599 100644
--- a/base/test/power_monitor_test_base.cc
+++ b/base/test/power_monitor_test_base.cc
@@ -4,15 +4,15 @@
 
 #include "base/test/power_monitor_test_base.h"
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 
 namespace base {
 
 PowerMonitorTestSource::PowerMonitorTestSource() {
-  DCHECK(MessageLoopCurrent::Get())
+  DCHECK(CurrentThread::Get())
       << "PowerMonitorTestSource requires a MessageLoop.";
 }
 
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.cc b/base/test/scoped_mock_time_message_loop_task_runner.cc
index 0ace2923..b48a2844 100644
--- a/base/test/scoped_mock_time_message_loop_task_runner.cc
+++ b/base/test/scoped_mock_time_message_loop_task_runner.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/check_op.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/test_pending_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -17,11 +17,11 @@
 ScopedMockTimeMessageLoopTaskRunner::ScopedMockTimeMessageLoopTaskRunner()
     : task_runner_(new TestMockTimeTaskRunner),
       previous_task_runner_(ThreadTaskRunnerHandle::Get()) {
-  DCHECK(MessageLoopCurrent::Get());
+  DCHECK(CurrentThread::Get());
   // To ensure that we process any initialization tasks posted to the
   // MessageLoop by a test fixture before replacing its TaskRunner.
   RunLoop().RunUntilIdle();
-  MessageLoopCurrent::Get()->SetTaskRunner(task_runner_);
+  CurrentThread::Get()->SetTaskRunner(task_runner_);
 }
 
 ScopedMockTimeMessageLoopTaskRunner::~ScopedMockTimeMessageLoopTaskRunner() {
@@ -32,7 +32,7 @@
         pending_task.location, std::move(pending_task.task),
         pending_task.GetTimeToRun() - task_runner_->NowTicks());
   }
-  MessageLoopCurrent::Get()->SetTaskRunner(std::move(previous_task_runner_));
+  CurrentThread::Get()->SetTaskRunner(std::move(previous_task_runner_));
 }
 
 }  // namespace base
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.h b/base/test/scoped_mock_time_message_loop_task_runner.h
index b671304..8323ef4 100644
--- a/base/test/scoped_mock_time_message_loop_task_runner.h
+++ b/base/test/scoped_mock_time_message_loop_task_runner.h
@@ -14,7 +14,7 @@
 class SingleThreadTaskRunner;
 
 // A scoped wrapper around TestMockTimeTaskRunner that replaces
-// MessageLoopCurrent::Get()'s task runner (and consequently
+// CurrentThread::Get()'s task runner (and consequently
 // ThreadTaskRunnerHandle) with a TestMockTimeTaskRunner and resets it back at
 // the end of its scope.
 //
diff --git a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc b/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
index f2f34b8..4b7e7b1 100644
--- a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
+++ b/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/test/test_pending_task.h"
@@ -43,7 +43,7 @@
  public:
   ScopedMockTimeMessageLoopTaskRunnerTest()
       : original_task_runner_(new TestMockTimeTaskRunner()) {
-    MessageLoopCurrent::Get()->SetTaskRunner(original_task_runner_);
+    CurrentThread::Get()->SetTaskRunner(original_task_runner_);
   }
 
  protected:
diff --git a/base/test/task_environment_unittest.cc b/base/test/task_environment_unittest.cc
index 5d20d60f..87e99e21 100644
--- a/base/test/task_environment_unittest.cc
+++ b/base/test/task_environment_unittest.cc
@@ -12,10 +12,10 @@
 #include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/debug/debugger.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/synchronization/atomic_flag.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/time_domain.h"
 #include "base/task/thread_pool.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
@@ -330,32 +330,32 @@
 // MainThreadType which is redundant (message loop and message pump tests
 // otherwise cover the advanced functionality provided by UI/IO pumps).
 TEST_F(TaskEnvironmentTest, MainThreadType) {
-  // Uses MessageLoopCurrent as a convenience accessor but could be replaced by
-  // different accessors when we get rid of MessageLoopCurrent.
-  EXPECT_FALSE(MessageLoopCurrent::IsSet());
-  EXPECT_FALSE(MessageLoopCurrentForUI::IsSet());
-  EXPECT_FALSE(MessageLoopCurrentForIO::IsSet());
+  // Uses CurrentThread as a convenience accessor but could be replaced by
+  // different accessors when we get rid of CurrentThread.
+  EXPECT_FALSE(CurrentThread::IsSet());
+  EXPECT_FALSE(CurrentUIThread::IsSet());
+  EXPECT_FALSE(CurrentIOThread::IsSet());
   {
     TaskEnvironment task_environment;
-    EXPECT_TRUE(MessageLoopCurrent::IsSet());
-    EXPECT_FALSE(MessageLoopCurrentForUI::IsSet());
-    EXPECT_FALSE(MessageLoopCurrentForIO::IsSet());
+    EXPECT_TRUE(CurrentThread::IsSet());
+    EXPECT_FALSE(CurrentUIThread::IsSet());
+    EXPECT_FALSE(CurrentIOThread::IsSet());
   }
   {
     TaskEnvironment task_environment(TaskEnvironment::MainThreadType::UI);
-    EXPECT_TRUE(MessageLoopCurrent::IsSet());
-    EXPECT_TRUE(MessageLoopCurrentForUI::IsSet());
-    EXPECT_FALSE(MessageLoopCurrentForIO::IsSet());
+    EXPECT_TRUE(CurrentThread::IsSet());
+    EXPECT_TRUE(CurrentUIThread::IsSet());
+    EXPECT_FALSE(CurrentIOThread::IsSet());
   }
   {
     TaskEnvironment task_environment(TaskEnvironment::MainThreadType::IO);
-    EXPECT_TRUE(MessageLoopCurrent::IsSet());
-    EXPECT_FALSE(MessageLoopCurrentForUI::IsSet());
-    EXPECT_TRUE(MessageLoopCurrentForIO::IsSet());
+    EXPECT_TRUE(CurrentThread::IsSet());
+    EXPECT_FALSE(CurrentUIThread::IsSet());
+    EXPECT_TRUE(CurrentIOThread::IsSet());
   }
-  EXPECT_FALSE(MessageLoopCurrent::IsSet());
-  EXPECT_FALSE(MessageLoopCurrentForUI::IsSet());
-  EXPECT_FALSE(MessageLoopCurrentForIO::IsSet());
+  EXPECT_FALSE(CurrentThread::IsSet());
+  EXPECT_FALSE(CurrentUIThread::IsSet());
+  EXPECT_FALSE(CurrentIOThread::IsSet());
 }
 
 #if defined(OS_POSIX)
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index 8659724..2a07813 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -13,10 +13,10 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/task/sequence_manager/task_queue.h"
 #include "base/task/simple_task_executor.h"
@@ -343,15 +343,15 @@
 
   // Lazily initialize the |message_loop| so that it can run on this thread.
   DCHECK(delegate_);
-  // This binds MessageLoopCurrent and ThreadTaskRunnerHandle.
+  // This binds CurrentThread and ThreadTaskRunnerHandle.
   delegate_->BindToCurrentThread(timer_slack_);
-  DCHECK(MessageLoopCurrent::Get());
+  DCHECK(CurrentThread::Get());
   DCHECK(ThreadTaskRunnerHandle::IsSet());
 
 #if defined(OS_POSIX) && !defined(OS_NACL)
   // Allow threads running a MessageLoopForIO to use FileDescriptorWatcher API.
   std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher;
-  if (MessageLoopCurrentForIO::IsSet()) {
+  if (CurrentIOThread::IsSet()) {
     file_descriptor_watcher.reset(
         new FileDescriptorWatcher(delegate_->GetDefaultTaskRunner()));
   }
diff --git a/base/threading/thread.h b/base/threading/thread.h
index f19f328..13f35d21 100644
--- a/base/threading/thread.h
+++ b/base/threading/thread.h
@@ -46,7 +46,7 @@
 //
 //  (1) Thread::CleanUp()
 //  (2) MessageLoop::~MessageLoop
-//  (3.b) MessageLoopCurrent::DestructionObserver::WillDestroyCurrentMessageLoop
+//  (3.b) CurrentThread::DestructionObserver::WillDestroyCurrentMessageLoop
 //
 // This API is not thread-safe: unless indicated otherwise its methods are only
 // valid from the owning sequence (which is the one from which Start() is
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
index 36d03ba..c5df9f0a 100644
--- a/base/threading/thread_perftest.cc
+++ b/base/threading/thread_perftest.cc
@@ -12,12 +12,12 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/task_observer.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
@@ -187,7 +187,7 @@
       i->task_runner()->PostTask(
           FROM_HERE, BindOnce(
                          [](MessageLoopObserver* observer) {
-                           MessageLoopCurrent::Get()->AddTaskObserver(observer);
+                           CurrentThread::Get()->AddTaskObserver(observer);
                          },
                          Unretained(&message_loop_observer)));
     }
diff --git a/base/threading/thread_unittest.cc b/base/threading/thread_unittest.cc
index d828642..717756c 100644
--- a/base/threading/thread_unittest.cc
+++ b/base/threading/thread_unittest.cc
@@ -15,10 +15,10 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/task/task_executor.h"
@@ -107,7 +107,7 @@
 // Observer that writes a value into |event_list| when a message loop has been
 // destroyed.
 class CapturingDestructionObserver
-    : public base::MessageLoopCurrent::DestructionObserver {
+    : public base::CurrentThread::DestructionObserver {
  public:
   // |event_list| must remain valid throughout the observer's lifetime.
   explicit CapturingDestructionObserver(EventList* event_list)
@@ -128,8 +128,8 @@
 
 // Task that adds a destruction observer to the current message loop.
 void RegisterDestructionObserver(
-    base::MessageLoopCurrent::DestructionObserver* observer) {
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(observer);
+    base::CurrentThread::DestructionObserver* observer) {
+  base::CurrentThread::Get()->AddDestructionObserver(observer);
 }
 
 // Task that calls GetThreadId() of |thread|, stores the result into |id|, then
@@ -453,7 +453,7 @@
 //
 //  (1) Thread::CleanUp()
 //  (2) MessageLoop::~MessageLoop()
-//      MessageLoopCurrent::DestructionObservers called.
+//      CurrentThread::DestructionObservers called.
 TEST_F(ThreadTest, CleanUp) {
   EventList captured_events;
   CapturingDestructionObserver loop_destruction_observer(&captured_events);
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 7dd02e8..cb142dc 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -20,7 +20,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/process/process.h"
 #include "base/process/process_metrics.h"
@@ -30,6 +29,7 @@
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/platform_thread.h"
@@ -209,7 +209,7 @@
 };
 
 class TraceLog::ThreadLocalEventBuffer
-    : public MessageLoopCurrent::DestructionObserver,
+    : public CurrentThread::DestructionObserver,
       public MemoryDumpProvider {
  public:
   explicit ThreadLocalEventBuffer(TraceLog* trace_log);
@@ -229,7 +229,7 @@
   int generation() const { return generation_; }
 
  private:
-  // MessageLoopCurrent::DestructionObserver
+  // CurrentThread::DestructionObserver
   void WillDestroyCurrentMessageLoop() override;
 
   // MemoryDumpProvider implementation.
@@ -258,7 +258,7 @@
       generation_(trace_log->generation()) {
   // ThreadLocalEventBuffer is created only if the thread has a message loop, so
   // the following message_loop won't be NULL.
-  MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  CurrentThread::Get()->AddDestructionObserver(this);
 
   // This is to report the local memory usage when memory-infra is enabled.
   MemoryDumpManager::GetInstance()->RegisterDumpProvider(
@@ -272,7 +272,7 @@
 
 TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
   CheckThisIsCurrentBuffer();
-  MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+  CurrentThread::Get()->RemoveDestructionObserver(this);
   MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this);
 
   {
@@ -423,7 +423,7 @@
   // - to handle the final flush.
   // For a thread without a message loop or if the message loop may be blocked,
   // the trace events will be added into the main buffer directly.
-  if (thread_blocks_message_loop_.Get() || !MessageLoopCurrent::IsSet() ||
+  if (thread_blocks_message_loop_.Get() || !CurrentThread::IsSet() ||
       !ThreadTaskRunnerHandle::IsSet()) {
     return;
   }
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h
index 58a3ec4..a7e7ea4a 100644
--- a/base/trace_event/traced_value.h
+++ b/base/trace_event/traced_value.h
@@ -131,14 +131,6 @@
     KeptValueType kept_value_type_;
   };
 
-  // Return std::string representation given by |value|'s ostream operator<<.
-  template <class T>
-  static std::string ValueToString(const T& value) {
-    std::stringstream ss;
-    ss << value;
-    return ss.str();
-  }
-
   // A custom serialization class can be supplied by implementing the
   // Writer interface and supplying a factory class to SetWriterFactoryCallback.
   // Primarily used by Perfetto to write TracedValues directly into its proto
@@ -239,6 +231,14 @@
   std::string ToFormattedJSON() const;
 };
 
+// Return std::string representation given by |value|'s ostream operator<<.
+template <typename T>
+std::string ValueToString(const T& value) {
+  std::stringstream ss;
+  ss << value;
+  return ss.str();
+}
+
 }  // namespace trace_event
 }  // namespace base
 
diff --git a/base/trace_event/traced_value_unittest.cc b/base/trace_event/traced_value_unittest.cc
index 657a390..1caf27bb 100644
--- a/base/trace_event/traced_value_unittest.cc
+++ b/base/trace_event/traced_value_unittest.cc
@@ -16,7 +16,7 @@
 namespace trace_event {
 
 TEST(TraceEventArgumentTest, ValueToString) {
-  std::string zero = TracedValue::ValueToString(0);
+  std::string zero = ValueToString(0);
   EXPECT_EQ("0", zero);
 }
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index aacfec6..34c4525 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200716.2.1
+0.20200717.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index aacfec6..34c4525 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200716.2.1
+0.20200717.1.1
diff --git a/cc/input/scrollbar_controller.h b/cc/input/scrollbar_controller.h
index fd08bbcf..f9b59b3 100644
--- a/cc/input/scrollbar_controller.h
+++ b/cc/input/scrollbar_controller.h
@@ -5,6 +5,8 @@
 #ifndef CC_INPUT_SCROLLBAR_CONTROLLER_H_
 #define CC_INPUT_SCROLLBAR_CONTROLLER_H_
 
+#include <memory>
+
 #include "cc/cc_export.h"
 #include "cc/input/input_handler.h"
 #include "cc/input/scrollbar.h"
diff --git a/cc/layers/viewport.cc b/cc/layers/viewport.cc
index 46b5f15..dc8074fc 100644
--- a/cc/layers/viewport.cc
+++ b/cc/layers/viewport.cc
@@ -4,6 +4,8 @@
 
 #include "cc/layers/viewport.h"
 
+#include <algorithm>
+
 #include "base/check.h"
 #include "base/memory/ptr_util.h"
 #include "cc/input/browser_controls_offset_manager.h"
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc
index f835c57..efb9139 100644
--- a/cc/metrics/compositor_frame_reporter.cc
+++ b/cc/metrics/compositor_frame_reporter.cc
@@ -613,6 +613,9 @@
     CHECK_LT(histogram_index, kMaxCompositorLatencyHistogramIndex);
     CHECK_GE(histogram_index, 0);
 
+    // Note: There's a 1:1 mapping between `histogram_index` and the name
+    // returned by `GetCompositorLatencyHistogramName()` which allows the use of
+    // `STATIC_HISTOGRAM_POINTER_GROUP()` to cache histogram objects.
     STATIC_HISTOGRAM_POINTER_GROUP(
         GetCompositorLatencyHistogramName(
             report_type_index, frame_sequence_tracker_type, stage_type_index),
@@ -640,20 +643,23 @@
     const int histogram_base_index =
         event_type_index * kEventLatencyScrollTypeCount + scroll_type_index;
 
-    // For scroll events, report total latency up to gpu-swap-end. This is
+    // For scroll events, report total latency up to gpu-swap-begin. This is
     // useful in comparing new EventLatency metrics with LatencyInfo-based
     // scroll event latency metrics.
     if (event_metrics.scroll_type() && !viz_breakdown_.swap_timings.is_null()) {
-      const base::TimeDelta swap_end_latency =
-          viz_breakdown_.swap_timings.swap_end - event_metrics.time_stamp();
-      const std::string swap_end_histogram_name =
-          histogram_base_name + ".TotalLatencyToSwapEnd";
+      const base::TimeDelta swap_begin_latency =
+          viz_breakdown_.swap_timings.swap_start - event_metrics.time_stamp();
+      const std::string swap_begin_histogram_name =
+          histogram_base_name + ".TotalLatencyToSwapBegin";
+      // Note: There's a 1:1 mapping between `histogram_base_index` and
+      // `swap_begin_histogram_name` which allows the use of
+      // `STATIC_HISTOGRAM_POINTER_GROUP()` to cache histogram objects.
       STATIC_HISTOGRAM_POINTER_GROUP(
-          swap_end_histogram_name, histogram_base_index,
+          swap_begin_histogram_name, histogram_base_index,
           kMaxEventLatencyHistogramBaseIndex,
-          AddTimeMicrosecondsGranularity(swap_end_latency),
+          AddTimeMicrosecondsGranularity(swap_begin_latency),
           base::Histogram::FactoryMicrosecondsTimeGet(
-              swap_end_histogram_name, kEventLatencyHistogramMin,
+              swap_begin_histogram_name, kEventLatencyHistogramMin,
               kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
               base::HistogramBase::kUmaTargetedHistogramFlag));
     }
@@ -682,6 +688,9 @@
         stage_it->start_time - event_metrics.time_stamp();
     const std::string b2r_histogram_name =
         histogram_base_name + ".BrowserToRendererCompositor";
+    // Note: There's a 1:1 mapping between `histogram_base_index` and
+    // `b2r_histogram_name` which allows the use of
+    // `STATIC_HISTOGRAM_POINTER_GROUP()` to cache histogram objects.
     STATIC_HISTOGRAM_POINTER_GROUP(
         b2r_histogram_name, histogram_base_index,
         kMaxEventLatencyHistogramBaseIndex,
@@ -768,6 +777,9 @@
   const int histogram_index =
       histogram_base_index * (kStageTypeCount + kAllBreakdownCount) +
       stage_type_index;
+  // Note: There's a 1:1 mapping between `histogram_index` and `histogram_name`
+  // which allows the use of `STATIC_HISTOGRAM_POINTER_GROUP()` to cache
+  // histogram objects.
   STATIC_HISTOGRAM_POINTER_GROUP(
       histogram_name, histogram_index, kMaxEventLatencyHistogramIndex,
       AddTimeMicrosecondsGranularity(latency),
diff --git a/cc/metrics/compositor_frame_reporter_unittest.cc b/cc/metrics/compositor_frame_reporter_unittest.cc
index 4503fdfb..07d50390 100644
--- a/cc/metrics/compositor_frame_reporter_unittest.cc
+++ b/cc/metrics/compositor_frame_reporter_unittest.cc
@@ -470,8 +470,8 @@
   const int total_latency_ms =
       (viz_breakdown.presentation_feedback.timestamp - event_time)
           .InMicroseconds();
-  const int swap_end_latency_ms =
-      (viz_breakdown.swap_timings.swap_end - event_time).InMicroseconds();
+  const int swap_begin_latency_ms =
+      (viz_breakdown.swap_timings.swap_start - event_time).InMicroseconds();
   struct {
     const char* name;
     const int64_t latency_ms;
@@ -479,12 +479,12 @@
   } expected_counts[] = {
       {"EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
        1},
-      {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
-       swap_end_latency_ms, 1},
+      {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin",
+       swap_begin_latency_ms, 1},
       {"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
        2},
-      {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
-       swap_end_latency_ms, 2},
+      {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+       swap_begin_latency_ms, 2},
   };
   for (const auto& expected_count : expected_counts) {
     histogram_tester.ExpectTotalCount(expected_count.name,
diff --git a/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index 70c03a29..035b5d1 100644
--- a/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -1160,8 +1160,8 @@
   // Verify that EventLatency histograms are recorded.
   const int64_t total_latency_ms =
       (details.presentation_feedback.timestamp - event_time).InMicroseconds();
-  const int64_t swap_end_latency_ms =
-      (details.swap_timings.swap_end - event_time).InMicroseconds();
+  const int64_t swap_begin_latency_ms =
+      (details.swap_timings.swap_start - event_time).InMicroseconds();
   struct {
     const char* name;
     const int64_t latency_ms;
@@ -1169,12 +1169,12 @@
   } expected_counts[] = {
       {"EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
        1},
-      {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
-       swap_end_latency_ms, 1},
+      {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin",
+       swap_begin_latency_ms, 1},
       {"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
        2},
-      {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
-       swap_end_latency_ms, 2},
+      {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+       swap_begin_latency_ms, 2},
   };
   for (const auto& expected_count : expected_counts) {
     histogram_tester.ExpectTotalCount(expected_count.name,
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc
index 37ecb8a..5b014c0 100644
--- a/cc/trees/ukm_manager.cc
+++ b/cc/trees/ukm_manager.cc
@@ -313,8 +313,8 @@
           static_cast<int64_t>(*event_metrics.scroll_type()));
 
       if (!viz_breakdown.swap_timings.is_null()) {
-        builder.SetTotalLatencyToSwapEnd(
-            (viz_breakdown.swap_timings.swap_end - event_metrics.time_stamp())
+        builder.SetTotalLatencyToSwapBegin(
+            (viz_breakdown.swap_timings.swap_start - event_metrics.time_stamp())
                 .InMicroseconds());
       }
     }
diff --git a/cc/trees/ukm_manager_unittest.cc b/cc/trees/ukm_manager_unittest.cc
index ad0b88c..55eac74 100644
--- a/cc/trees/ukm_manager_unittest.cc
+++ b/cc/trees/ukm_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "cc/trees/ukm_manager.h"
 
+#include <utility>
 #include <vector>
 
 #include "base/time/time.h"
@@ -65,7 +66,7 @@
 const char kVizBreakdownSwapEndToPresentationCompositorFrame[] =
     "SubmitCompositorFrameToPresentationCompositorFrame."
     "SwapEndToPresentationCompositorFrame";
-const char kTotalLatencyToSwapEnd[] = "TotalLatencyToSwapEnd";
+const char kTotalLatencyToSwapBegin[] = "TotalLatencyToSwapBegin";
 const char kTotalLatency[] = "TotalLatency";
 
 // Names of frame sequence types use in compositor latency UKM metrics (see
@@ -383,7 +384,7 @@
   viz_breakdown.presentation_feedback.timestamp =
       (now += base::TimeDelta::FromMicroseconds(5));
 
-  const base::TimeTicks swap_end_time = viz_breakdown.swap_timings.swap_end;
+  const base::TimeTicks swap_start_time = viz_breakdown.swap_timings.swap_start;
   const base::TimeTicks present_time =
       viz_breakdown.presentation_feedback.timestamp;
 
@@ -449,8 +450,8 @@
         entry, kSubmitCompositorFrameToPresentationCompositorFrame,
         (present_time - submit_time).InMicroseconds());
     test_ukm_recorder_->ExpectEntryMetric(
-        entry, kTotalLatencyToSwapEnd,
-        (swap_end_time - event_time).InMicroseconds());
+        entry, kTotalLatencyToSwapBegin,
+        (swap_start_time - event_time).InMicroseconds());
     test_ukm_recorder_->ExpectEntryMetric(
         entry, kTotalLatency, (present_time - event_time).InMicroseconds());
   }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index a0f1940..674fef83 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel;
 import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.ui.TabObscuringHandler;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
@@ -44,7 +45,7 @@
 @JNINamespace("autofill_assistant")
 // TODO(crbug.com/806868): This class should be removed once all logic is in native side and the
 // model is directly modified by the native AssistantMediator.
-class AutofillAssistantUiController {
+public class AutofillAssistantUiController {
     private static Set<ChromeActivity> sActiveChromeActivities;
     private long mNativeUiController;
 
@@ -55,6 +56,19 @@
     private SnackbarController mSnackbarController;
 
     /**
+     * Getter for the current profile while assistant is running. Since autofill assistant is only
+     * available in regular mode and there is only one regular profile in android, this method
+     * returns {@link Profile#getLastUsedRegularProfile()}.
+     *
+     * TODO(b/161519639): Return current profile to support multi profiles, instead of returning
+     * always regular profile. This could be achieve by retrieving profile from native and using it
+     * where the profile is needed on Java side.
+     * @return The current regular profile.
+     */
+    public static Profile getProfile() {
+        return Profile.getLastUsedRegularProfile();
+    }
+    /**
      * Finds an activity to which a AA UI can be added.
      *
      * <p>The activity must not already have an AA UI installed.
@@ -165,6 +179,12 @@
                                 safeNativeStop(DropOutReason.TAB_DETACHED);
                                 return;
                             }
+
+                            // If we have an open snackbar, execute the callback immediately. This
+                            // may shut down the Autofill Assistant.
+                            if (mSnackbarController != null) {
+                                mSnackbarController.onDismissNoAction(/* actionData= */ null);
+                            }
                             AutofillAssistantClient.fromWebContents(mWebContents).destroyUi();
                         }
                     }
@@ -368,9 +388,10 @@
 
     // Native methods.
     private void safeSnackbarResult(boolean undo) {
-        if (mNativeUiController != 0) {
+        if (mSnackbarController != null && mNativeUiController != 0) {
             AutofillAssistantUiControllerJni.get().snackbarResult(
                     mNativeUiController, AutofillAssistantUiController.this, undo);
+            mSnackbarController = null;
         }
     }
 
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsCoordinator.java
index d20795d..bf9f379 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsCoordinator.java
@@ -11,6 +11,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController;
 import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetailsViewBinder.ViewHolder;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
@@ -26,7 +27,8 @@
 
     public AssistantDetailsCoordinator(Context context, AssistantDetailsModel model) {
         this(context, model,
-                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY));
+                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY,
+                        AutofillAssistantUiController.getProfile()));
     }
 
     @VisibleForTesting
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantDrawable.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantDrawable.java
index 9fbeb51..bbca2a7 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantDrawable.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantDrawable.java
@@ -19,6 +19,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController;
 import org.chromium.chrome.browser.autofill_assistant.drawable.AssistantDrawableIcon;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
@@ -103,8 +104,8 @@
     }
 
     private static class AssistantBitmapDrawable extends AssistantDrawable {
-        private final ImageFetcher mImageFetcher =
-                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY);
+        private final ImageFetcher mImageFetcher = ImageFetcherFactory.createImageFetcher(
+                ImageFetcherConfig.DISK_CACHE_ONLY, AutofillAssistantUiController.getProfile());
         private final String mUrl;
         private final int mWidthInPixels;
         private final int mHeightInPixels;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
index 8911f7c..5a1035b 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxCoordinator.java
@@ -9,6 +9,7 @@
 import android.view.View;
 
 import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController;
 import org.chromium.chrome.browser.autofill_assistant.infobox.AssistantInfoBoxViewBinder.ViewHolder;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
@@ -24,7 +25,8 @@
 
     public AssistantInfoBoxCoordinator(Context context, AssistantInfoBoxModel model) {
         this(context, model,
-                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY));
+                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY,
+                        AutofillAssistantUiController.getProfile()));
     }
 
     /** Used for testing to inject an image fetcher. */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
index ed2411d4..f57d860 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
@@ -10,6 +10,7 @@
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 
+import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
@@ -38,7 +39,8 @@
             BrowserControlsStateProvider browserControls, CompositorViewHolder compositorViewHolder,
             ScrimView scrim, AssistantOverlayModel model) {
         this(context, browserControls, compositorViewHolder, scrim, model,
-                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY));
+                ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY,
+                        AutofillAssistantUiController.getProfile()));
     }
 
     public AssistantOverlayCoordinator(Context context,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
index fc64403..d184353 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java
@@ -78,17 +78,6 @@
     }
 
     @CalledByNative
-    private static boolean shouldDelegateLocationPermission(String url) {
-        TrustedWebActivityPermissionManager manager = TrustedWebActivityPermissionManager.get();
-        Origin origin = Origin.create(Uri.parse(url));
-        if (origin == null) return false;
-        String packageName = manager.getDelegatePackageName(origin);
-        return manager.isRunningTwa()
-                && TrustedWebActivityPermissionManager.hasAndroidLocationPermission(packageName)
-                != null;
-    }
-
-    @CalledByNative
     private static void decidePermission(String url, long callback) {
         Origin origin = Origin.create(Uri.parse(url));
         if (origin == null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
index bb8e1e5..99308134 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
@@ -15,6 +15,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.TestFileUtil;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
@@ -99,6 +100,7 @@
 
     @Test
     @LargeTest
+    @DisabledTest(message = "Noop since UseDownloadOfflineContentProvider is enabled in debug.")
     @Feature({"Download"})
     public void testResumeInterruptedDownload() {
         if (useDownloadOfflineContentProvider()) return;
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 3772b6e8..4fa34571 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -701,6 +701,13 @@
         </message>
       </if>
 
+      <!-- Dice Web Signin Interception Bubble-->
+      <if expr="not chromeos and not is_android">
+        <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble">
+          You signed in with a work account. Would you like to create a new Chromium Profile for Work to keep your data separate?
+        </message>
+      </if>
+
       <!-- Chrome Cleanup prompt.
            Note: these strings should only be used by Google Chrome, but
                  omitting them brings up a hash collision error. -->
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
new file mode 100644
index 0000000..dc2f9af32
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@
+5b9b6af71c9cb4fced7472e927c8a4e695a34e62
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index af0335a8..481f05e1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7745,6 +7745,18 @@
         Cancel sign in
       </message>
 
+      <!-- Dice Web Signin Interception Bubble-->
+      <if expr="not chromeos and not is_android">
+        <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE" desc="Title of the web signin interception bubble">
+          Create Work Profile?
+        </message>
+        <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL" desc="Label of the confirmation button in the web signin interception bubble">
+          New Profile
+        </message>
+        <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL" desc="Label of the cancel button in the web signin interception bubble">
+          Cancel
+        </message>
+      </if>
 
       <!-- Signin Error tab modal dialog -->
       <message name="IDS_SIGNIN_ERROR_TITLE" desc="Title of the signin error tab modal dialog.">
diff --git a/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..dc2f9af32
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+5b9b6af71c9cb4fced7472e927c8a4e695a34e62
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..dc2f9af32
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+5b9b6af71c9cb4fced7472e927c8a4e695a34e62
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1
new file mode 100644
index 0000000..dc2f9af32
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@
+5b9b6af71c9cb4fced7472e927c8a4e695a34e62
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 7c20e107..c9a3fa55 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -708,6 +708,13 @@
         </message>
       </if>
 
+      <!-- Dice Web Signin Interception Bubble-->
+      <if expr="not chromeos and not is_android">
+        <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble">
+          You signed in with a work account. Would you like to create a new Chrome Profile for Work to keep your data separate?
+        </message>
+      </if>
+
       <!-- Chrome Cleanup prompt -->
       <if expr="is_win">
         <message name="IDS_CHROME_CLEANUP_PROMPT_EXPLANATION" desc="Description in the Chrome Cleanup dialog that Chrome browser shows when unwanted software, like ad injectors or software that changes the user's settings without their knowledge, is found on the user's computer. Appears under the title asking 'Remove harmful software?' Actor is Chrome; we are asking, Do you want Chrome to remove harmful software? 'it' is harmful software. User has the option of clicking 'Remove' to proceed with a cleanup, or 'Details' to see more details. The description is also shown on the Chrome Cleanup section of the Settings page, under 'Remove harmful software' title. Preferrably, the translation for this string should parallel IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_CURRENTLY_REMOVING.">
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
new file mode 100644
index 0000000..dc2f9af32
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@
+5b9b6af71c9cb4fced7472e927c8a4e695a34e62
\ No newline at end of file
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp
index 6c5197da5..272b84e1 100644
--- a/chrome/app/media_router_strings.grdp
+++ b/chrome/app/media_router_strings.grdp
@@ -76,13 +76,8 @@
   <message name="IDS_MEDIA_ROUTER_ISSUE_TAB_AUDIO_NOT_SUPPORTED" desc="Title of an issue shown when the user is casting a tab, but only its visual content can be cast and not its audio output.">
     Casting tab audio is not supported on this device.
   </message>
-  <if expr="is_macosx">
-    <message name="IDS_MEDIA_ROUTER_ISSUE_MAC_SCREEN_CAPTURE_PERMISSION_ERROR" desc="Title of an issue shown when the user is casting a window or desktop, and the associated MAC OS X 10.15+ system permission for 'Screen Recording' is not granted.">
-      Unable to cast screen. Check the Screen Recording permission in System Preferences.
-    </message>
-  </if>
 
-<!-- Sink List -->
+  <!-- Sink List -->
   <message name="IDS_MEDIA_ROUTER_STATUS_LOOKING_FOR_DEVICES" desc="Status text temporarily shown while searching for Cast devices but none have been found.">
     Looking for devices
   </message>
diff --git a/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_MAC_SCREEN_CAPTURE_PERMISSION_ERROR.png.sha1 b/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_MAC_SCREEN_CAPTURE_PERMISSION_ERROR.png.sha1
deleted file mode 100644
index 5963743..0000000
--- a/chrome/app/media_router_strings_grdp/IDS_MEDIA_ROUTER_ISSUE_MAC_SCREEN_CAPTURE_PERMISSION_ERROR.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-132219c7007d8910e5c140403116c879cbae30bc
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index ad5759f..a4998bd 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1032,6 +1032,8 @@
     "password_manager/account_storage/account_password_store_factory.h",
     "password_manager/bulk_leak_check_service_factory.cc",
     "password_manager/bulk_leak_check_service_factory.h",
+    "password_manager/change_password_url_service_factory.cc",
+    "password_manager/change_password_url_service_factory.h",
     "password_manager/chrome_biometric_authenticator.h",
     "password_manager/chrome_password_manager_client.cc",
     "password_manager/chrome_password_manager_client.h",
@@ -3128,8 +3130,6 @@
       "enterprise/reporting/prefs.h",
       "enterprise/reporting/profile_report_generator_desktop.cc",
       "enterprise/reporting/profile_report_generator_desktop.h",
-      "enterprise/reporting/report_generator.cc",
-      "enterprise/reporting/report_generator.h",
       "enterprise/reporting/report_generator_desktop.cc",
       "enterprise/reporting/report_generator_desktop.h",
       "enterprise/reporting/report_scheduler.cc",
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc
index 0d6f0d6..bd2bba2 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -151,7 +151,8 @@
   browser_app_launcher_ = std::make_unique<apps::BrowserAppLauncher>(profile_);
 
   app_service_impl_ = std::make_unique<apps::AppServiceImpl>(
-      profile_->GetPrefs(), profile_->GetPath());
+      profile_->GetPrefs(), profile_->GetPath(),
+      base::FeatureList::IsEnabled(features::kIntentHandlingSharing));
   app_service_impl_->BindReceiver(app_service_.BindNewPipeAndPassReceiver());
 
   if (app_service_.is_connected()) {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index ee5ba8e..7a952a38 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -191,6 +191,8 @@
       </if>
       <if expr="is_win or is_macosx or desktop_linux">
         <include name="IDR_SIGNIN_DICE_WEB_INTERCEPT_HTML" file="resources\signin\dice_web_signin_intercept\dice_web_signin_intercept.html" type="BINDATA" />
+        <include name="IDR_SIGNIN_DICE_WEB_INTERCEPT_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\dice_web_signin_intercept\dice_web_signin_intercept_app.js" use_base_dir="false" type="BINDATA" />
+        <include name="IDR_SIGNIN_DICE_WEB_INTERCEPT_BROWSER_PROXY_JS" file="resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js" type="BINDATA" />
         <include name="IDR_SIGNIN_EMAIL_CONFIRMATION_HTML" file="resources\signin\signin_email_confirmation\signin_email_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
         <include name="IDR_SIGNIN_EMAIL_CONFIRMATION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\signin_email_confirmation\signin_email_confirmation_app.js" use_base_dir="false" preprocess="true" type="BINDATA" />
         <include name="IDR_SIGNIN_ERROR_HTML" file="resources\signin\signin_error\signin_error.html" type="BINDATA" />
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 2bc798dd..8ccdab59 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -26,7 +26,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
@@ -37,6 +36,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/hang_watcher.h"
 #include "base/threading/platform_thread.h"
@@ -1698,7 +1698,7 @@
   // across versions.
   RecordBrowserStartupTime();
 
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   performance_monitor::ProcessMonitor::GetInstance()->StartGatherCycle();
 
diff --git a/chrome/browser/chrome_browser_main_android.cc b/chrome/browser/chrome_browser_main_android.cc
index 42a1287..65092b08 100644
--- a/chrome/browser/chrome_browser_main_android.cc
+++ b/chrome/browser/chrome_browser_main_android.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/chrome_browser_main_android.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/trace_event/trace_event.h"
@@ -67,7 +67,7 @@
     "ChromeBrowserMainPartsAndroid::PreEarlyInitialization")
   content::Compositor::Initialize();
 
-  CHECK(base::MessageLoopCurrent::IsSet());
+  CHECK(base::CurrentThread::IsSet());
 
   return ChromeBrowserMainParts::PreEarlyInitialization();
 }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 9df37f5..e3b597d 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -210,6 +210,7 @@
     "//components/download/content/public",
     "//components/drive",
     "//components/drive:drive_chromeos",
+    "//components/enterprise",
     "//components/exo",
     "//components/feedback",
     "//components/flags_ui",
@@ -965,6 +966,8 @@
     "crostini/crostini_terminal.h",
     "crostini/crostini_unsupported_action_notifier.cc",
     "crostini/crostini_unsupported_action_notifier.h",
+    "crostini/crostini_upgrade_available_notification.cc",
+    "crostini/crostini_upgrade_available_notification.h",
     "crostini/crostini_upgrader.cc",
     "crostini/crostini_upgrader.h",
     "crostini/crostini_upgrader_ui_delegate.h",
@@ -3018,6 +3021,7 @@
     "crostini/crostini_shelf_utils_unittest.cc",
     "crostini/crostini_stability_monitor_unittest.cc",
     "crostini/crostini_unsupported_action_notifier_unittest.cc",
+    "crostini/crostini_upgrade_available_notification_unittest.cc",
     "crostini/crostini_util_unittest.cc",
     "crostini/crosvm_metrics_unittest.cc",
     "crostini/crosvm_process_list_unittest.cc",
diff --git a/chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.cc b/chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.cc
index e76fe97..c147557 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.cc
@@ -43,7 +43,7 @@
   {
     DictionaryPrefUpdate dict_update(local_state,
                                      prefs::kAllKioskUsersToRemove);
-    dict_update->RemoveWithoutPathExpansion(id.id(), nullptr);
+    dict_update->RemoveKey(id.id());
   }
   local_state->CommitPendingWrite();
 }
diff --git a/chrome/browser/chromeos/arc/icon_decode_request.h b/chrome/browser/chromeos/arc/icon_decode_request.h
index b151d08..5615cb11 100644
--- a/chrome/browser/chromeos/arc/icon_decode_request.h
+++ b/chrome/browser/chromeos/arc/icon_decode_request.h
@@ -27,7 +27,7 @@
   // Disables async safe decoding requests when unit tests are executed.
   // Icons are decoded at a separate process created by ImageDecoder. In unit
   // tests these tasks may not finish before the test exits, which causes a
-  // failure in the base::MessageLoopCurrent::Get()->IsIdleForTesting() check
+  // failure in the base::CurrentThread::Get()->IsIdleForTesting() check
   // in content::~BrowserTaskEnvironment().
   static void DisableSafeDecodingForTesting();
 
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
index b116961..ec21c7a 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -11,8 +11,8 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/arc/intent_helper/arc_settings_service.h"
 #include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h"
@@ -205,7 +205,7 @@
 }
 
 void RunUntilIdle() {
-  DCHECK(base::MessageLoopCurrent::Get());
+  DCHECK(base::CurrentThread::Get());
   base::RunLoop loop;
   loop.RunUntilIdle();
 }
diff --git a/chrome/browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc b/chrome/browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc
index 61f61d2..2f2a653 100644
--- a/chrome/browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc
@@ -4,8 +4,8 @@
 
 #include <memory>
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "chrome/browser/chromeos/arc/user_session/arc_user_session_service.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -37,7 +37,7 @@
 }
 
 void RunUntilIdle() {
-  DCHECK(base::MessageLoopCurrent::Get());
+  DCHECK(base::CurrentThread::Get());
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
index 8eaf77a..bd082ee 100644
--- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
+++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
@@ -243,7 +243,7 @@
   return true;
 }
 
-void CertificateProviderService::ReplyToSignRequest(
+bool CertificateProviderService::ReplyToSignRequest(
     const std::string& extension_id,
     int sign_request_id,
     const std::vector<uint8_t>& signature) {
@@ -257,10 +257,7 @@
   net::SSLPrivateKey::SignCallback callback;
   if (!sign_requests_.RemoveRequest(extension_id, sign_request_id, &certificate,
                                     &callback)) {
-    LOG(ERROR) << "request id unknown.";
-    // The request was aborted before, or the extension replied multiple times
-    // to the same request.
-    return;
+    return false;
   }
 
   const net::Error error_code = signature.empty() ? net::ERR_FAILED : net::OK;
@@ -270,6 +267,7 @@
     for (auto& observer : observers_)
       observer.OnSignCompleted(certificate, extension_id);
   }
+  return true;
 }
 
 bool CertificateProviderService::LookUpCertificate(
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h
index d0b2c8f8..9b24f64 100644
--- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h
+++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h
@@ -146,9 +146,8 @@
   // If the signature could be calculated by the extension, |signature| is
   // provided in the reply and should be the signature of the data sent in the
   // sign request. Otherwise, in case of a failure, |signature| must be empty.
-  // The call is ignored if |sign_request_id| is not referring to a pending
-  // request.
-  void ReplyToSignRequest(const std::string& extension_id,
+  // Returns false if |sign_request_id| is not referring to a pending request.
+  bool ReplyToSignRequest(const std::string& extension_id,
                           int sign_request_id,
                           const std::vector<uint8_t>& signature);
 
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 54e80555..dc3d23f 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/chromeos/crostini/crostini_reporting_util.h"
 #include "chrome/browser/chromeos/crostini/crostini_stability_monitor.h"
 #include "chrome/browser/chromeos/crostini/crostini_types.mojom.h"
+#include "chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h"
 #include "chrome/browser/chromeos/crostini/throttle/crostini_throttle.h"
 #include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
@@ -1053,6 +1054,10 @@
     VLOG(1) << "Not online, so can't check now for cros-termina upgrade.";
     return;
   }
+  if (ShouldPromptContainerUpgrade(DefaultContainerId())) {
+    upgrade_available_notification_ =
+        CrostiniUpgradeAvailableNotification::Show(profile_, base::DoNothing());
+  }
   InstallTerminaComponent(base::DoNothing());
 }
 
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 43823f8..007ed735 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -40,6 +40,7 @@
 namespace crostini {
 
 class CrostiniStabilityMonitor;
+class CrostiniUpgradeAvailableNotification;
 
 class LinuxPackageOperationProgressObserver {
  public:
@@ -970,6 +971,9 @@
 
   std::unique_ptr<CrostiniStabilityMonitor> crostini_stability_monitor_;
 
+  std::unique_ptr<CrostiniUpgradeAvailableNotification>
+      upgrade_available_notification_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.cc b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.cc
new file mode 100644
index 0000000..fdee36f6
--- /dev/null
+++ b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.cc
@@ -0,0 +1,142 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h"
+
+#include "ash/public/cpp/notification_utils.h"
+#include "base/callback.h"
+#include "base/metrics/histogram_functions.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
+#include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace crostini {
+
+const char kNotifierCrostiniUpgradeAvailable[] = "crostini.upgrade_available";
+
+class CrostiniUpgradeAvailableNotificationDelegate
+    : public message_center::NotificationDelegate {
+ public:
+  explicit CrostiniUpgradeAvailableNotificationDelegate(
+      Profile* profile,
+      base::WeakPtr<CrostiniUpgradeAvailableNotification> notification,
+      base::OnceClosure closure)
+      : profile_(profile),
+        notification_(notification),
+        closure_(std::move(closure)) {
+    CrostiniManager::GetForProfile(profile_)->UpgradePromptShown(
+        ContainerId::GetDefault());
+  }
+
+  void Click(const base::Optional<int>& button_index,
+             const base::Optional<base::string16>& reply) override {
+    disposition_ =
+        CrostiniUpgradeAvailableNotificationClosed::kNotificationBody;
+    if (button_index && button_index.value() == 0) {
+      disposition_ = CrostiniUpgradeAvailableNotificationClosed::kUpgradeButton;
+      HandleButtonClick();
+      return;
+    }
+    HandleBodyClick();
+  }
+
+  void HandleButtonClick() {
+    chromeos::CrostiniUpgraderDialog::Show(profile_, base::DoNothing());
+    if (notification_) {
+      notification_->UpgradeDialogShown();
+    }
+    Close(false);
+  }
+
+  void HandleBodyClick() {
+    chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
+        profile_, chromeos::settings::mojom::kCrostiniDetailsSubpagePath);
+    Close(false);
+  }
+
+  void Close(bool by_user) override {
+    if (by_user) {
+      disposition_ = CrostiniUpgradeAvailableNotificationClosed::kByUser;
+    }
+    // Run the callback now. The notification might hang around after the
+    // closure has been run, so we need to guard it.
+    if (closure_) {
+      std::move(closure_).Run();
+    }
+    base::UmaHistogramEnumeration("Crostini.UpgradeAvailable", disposition_);
+  }
+
+ private:
+  ~CrostiniUpgradeAvailableNotificationDelegate() override = default;
+
+  CrostiniUpgradeAvailableNotificationClosed disposition_ =
+      CrostiniUpgradeAvailableNotificationClosed::kUnknown;
+  Profile* profile_;  // Not owned.
+  base::WeakPtr<CrostiniUpgradeAvailableNotification> notification_;
+  base::OnceClosure closure_;
+
+  base::WeakPtrFactory<CrostiniUpgradeAvailableNotificationDelegate>
+      weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(CrostiniUpgradeAvailableNotificationDelegate);
+};
+
+std::unique_ptr<CrostiniUpgradeAvailableNotification>
+CrostiniUpgradeAvailableNotification::Show(Profile* profile,
+                                           base::OnceClosure closure) {
+  return std::make_unique<CrostiniUpgradeAvailableNotification>(
+      profile, std::move(closure));
+}
+
+CrostiniUpgradeAvailableNotification::CrostiniUpgradeAvailableNotification(
+    Profile* profile,
+    base::OnceClosure closure)
+    : profile_(profile) {
+  message_center::RichNotificationData rich_notification_data;
+  rich_notification_data.small_image = gfx::Image(gfx::CreateVectorIcon(
+      vector_icons::kFileDownloadIcon, 64, gfx::kGoogleBlue800));
+  rich_notification_data.accent_color = ash::kSystemNotificationColorNormal;
+  rich_notification_data.buttons.emplace_back(
+      message_center::ButtonInfo(l10n_util::GetStringUTF16(
+          IDS_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_UPGRADE)));
+
+  notification_ = std::make_unique<message_center::Notification>(
+      message_center::NOTIFICATION_TYPE_MULTIPLE,
+      kNotifierCrostiniUpgradeAvailable,
+      l10n_util::GetStringUTF16(
+          IDS_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_TITLE),
+      l10n_util::GetStringUTF16(
+          IDS_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_BODY),
+      gfx::Image(), base::string16(), GURL(),
+      message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
+                                 kNotifierCrostiniUpgradeAvailable),
+      rich_notification_data,
+      base::MakeRefCounted<CrostiniUpgradeAvailableNotificationDelegate>(
+          profile_, weak_ptr_factory_.GetWeakPtr(), std::move(closure)));
+
+  notification_->SetSystemPriority();
+  ForceRedisplay();
+}
+
+CrostiniUpgradeAvailableNotification::~CrostiniUpgradeAvailableNotification() =
+    default;
+
+void CrostiniUpgradeAvailableNotification::UpgradeDialogShown() {
+  notification_->set_buttons({});
+  notification_->set_never_timeout(false);
+  notification_->set_pinned(false);
+  ForceRedisplay();
+}
+
+void CrostiniUpgradeAvailableNotification::ForceRedisplay() {
+  NotificationDisplayService::GetForProfile(profile_)->Display(
+      NotificationHandler::Type::TRANSIENT, *notification_,
+      /*metadata=*/nullptr);
+}
+
+}  // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h
new file mode 100644
index 0000000..afc42a6
--- /dev/null
+++ b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h
@@ -0,0 +1,62 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_H_
+#define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/message_center/public/cpp/notification.h"
+
+class Profile;
+
+namespace crostini {
+
+extern const char kNotifierCrostiniUpgradeAvailable[];
+
+// Reasons the notification may be closed. These are used in histograms so do
+// not remove/reorder entries. Only add at the end just before kMaxValue. Also
+// remember to update the enum listing in
+// tools/metrics/histograms/histograms.xml.
+enum class CrostiniUpgradeAvailableNotificationClosed {
+  // The notification was dismissed but not by the user (either automatically
+  // or because the device was unplugged).
+  kUnknown,
+  // The user closed the notification via the close box.
+  kByUser,
+  // The user clicked on the Upgrade button of the notification.
+  kUpgradeButton,
+  // The user clicked on the body of the notification.
+  kNotificationBody,
+  // Maximum value for the enum.
+  kMaxValue = kNotificationBody,
+};
+
+class CrostiniUpgradeAvailableNotification {
+ public:
+  explicit CrostiniUpgradeAvailableNotification(Profile* profile,
+                                                base::OnceClosure closure);
+  virtual ~CrostiniUpgradeAvailableNotification();
+
+  static std::unique_ptr<CrostiniUpgradeAvailableNotification> Show(
+      Profile* profile,
+      base::OnceClosure closure);
+
+  void ForceRedisplay();
+  void UpgradeDialogShown();
+
+  message_center::Notification* Get() { return notification_.get(); }
+
+ private:
+  Profile* profile_;  // Not owned.
+  std::unique_ptr<message_center::Notification> notification_;
+  base::WeakPtrFactory<CrostiniUpgradeAvailableNotification> weak_ptr_factory_{
+      this};
+};
+
+}  // namespace crostini
+
+#endif  // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UPGRADE_AVAILABLE_NOTIFICATION_H_
diff --git a/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification_unittest.cc b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification_unittest.cc
new file mode 100644
index 0000000..3b3623ca
--- /dev/null
+++ b/chrome/browser/chromeos/crostini/crostini_upgrade_available_notification_unittest.cc
@@ -0,0 +1,196 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h"
+
+#include "base/feature_list.h"
+#include "base/metrics/histogram_base.h"
+#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "build/branding_buildflags.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/chromeos/crostini/crostini_test_helper.h"
+#include "chrome/browser/chromeos/crostini/crostini_upgrade_available_notification.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
+#include "chrome/browser/notifications/system_notification_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/dbus/cicerone/cicerone_service.pb.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/public/cpp/notification.h"
+
+namespace crostini {
+
+class WebContentsWaiter : public content::WebContentsObserver {
+ public:
+  enum Operation { LOAD };  // Add other operations as required.
+  explicit WebContentsWaiter(content::WebContents* contents,
+                             Operation operation)
+      : content::WebContentsObserver(contents), operation_(operation) {
+    LOG(INFO) << "Waiting for web contents";
+  }
+
+  ~WebContentsWaiter() override = default;
+
+  void Wait() {
+    LOG(INFO) << "And Waiting";
+    run_loop_.Run();
+  }
+
+  // content::WebContentsObserver:
+  void DidFinishLoad(content::RenderFrameHost* render_frame_host,
+                     const GURL& validated_url) override {
+    if (operation_ == LOAD) {
+      run_loop_.Quit();
+    }
+  }
+
+ private:
+  base::RunLoop run_loop_;
+  Operation operation_;
+};
+
+class CrostiniUpgradeAvailableNotificationTest
+    : public BrowserWithTestWindowTest {
+ public:
+  CrostiniUpgradeAvailableNotificationTest()
+      : BrowserWithTestWindowTest(
+            Browser::TYPE_NORMAL,
+            content::BrowserTaskEnvironment::REAL_IO_THREAD) {}
+
+  ~CrostiniUpgradeAvailableNotificationTest() override {}
+
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+    chromeos::DBusThreadManager::Initialize();
+
+    TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper(
+        std::make_unique<SystemNotificationHelper>());
+    display_service_ = std::make_unique<NotificationDisplayServiceTester>(
+        nullptr /* profile */);
+  }
+
+  void TearDown() override {
+    RunUntilIdle();
+    display_service_.reset();
+    BrowserWithTestWindowTest::TearDown();
+    chromeos::DBusThreadManager::Shutdown();
+  }
+
+  chromeos::CrostiniUpgraderDialog* GetCrostiniUpgraderDialog() {
+    auto url = GURL{chrome::kChromeUICrostiniUpgraderUrl};
+    return reinterpret_cast<chromeos::CrostiniUpgraderDialog*>(
+        chromeos::SystemWebDialogDelegate::FindInstance(url.spec()));
+  }
+
+  void SafelyCloseDialog() {
+    auto* upgrader_dialog = GetCrostiniUpgraderDialog();
+
+    if (!upgrader_dialog) {
+      return;
+    }
+    // Make sure the WebUI has launches sufficiently. Closing immediately would
+    // miss breakages in the underlying plumbing.
+    if (upgrader_dialog->GetWebUIForTest()) {
+      auto* web_contents = upgrader_dialog->GetWebUIForTest()->GetWebContents();
+      WebContentsWaiter(web_contents, WebContentsWaiter::LOAD).Wait();
+    }
+
+    // Now there should be enough WebUI hooked up to close properly.
+    base::RunLoop run_loop;
+    upgrader_dialog->SetDeletionClosureForTesting(run_loop.QuitClosure());
+    upgrader_dialog->Close();
+    run_loop.Run();
+  }
+
+  void ExpectDialog() {
+    // A new Widget was created in ShowUi() or since the last VerifyUi().
+    EXPECT_TRUE(crostini_manager()->GetCrostiniDialogStatus(
+        crostini::DialogType::UPGRADER));
+
+    EXPECT_NE(nullptr, GetCrostiniUpgraderDialog());
+  }
+
+  void ExpectNoDialog() {
+    // No new Widget was created in ShowUi() or since the last VerifyUi().
+    EXPECT_FALSE(crostini_manager()->GetCrostiniDialogStatus(
+        crostini::DialogType::UPGRADER));
+    // Our dialog has really been deleted.
+    EXPECT_EQ(nullptr, GetCrostiniUpgraderDialog());
+  }
+
+  void DowngradeOSRelease() {
+    vm_tools::cicerone::OsRelease os_release;
+    os_release.set_id("debian");
+    os_release.set_version_id("9");
+    auto container_id = crostini::DefaultContainerId();
+    crostini_manager()->SetContainerOsRelease(container_id, os_release);
+  }
+
+  crostini::CrostiniManager* crostini_manager() {
+    return crostini::CrostiniManager::GetForProfile(profile());
+  }
+
+  void RunUntilIdle() { task_environment()->RunUntilIdle(); }
+
+  base::Optional<message_center::Notification> GetNotification(std::string id) {
+    return display_service_->GetNotification(id);
+  }
+
+ private:
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
+  session_manager::SessionManager session_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrostiniUpgradeAvailableNotificationTest);
+};
+
+TEST_F(CrostiniUpgradeAvailableNotificationTest, ShowsWhenNotified) {
+  base::HistogramTester histogram_tester;
+
+  DowngradeOSRelease();
+
+  base::RunLoop run_loop;
+  auto notification = CrostiniUpgradeAvailableNotification::Show(
+      profile(), run_loop.QuitClosure());
+
+  ExpectNoDialog();
+
+  // Wait for notification, press Upgrade
+  ASSERT_TRUE(notification);
+  notification->Get()->delegate()->Click(0, base::nullopt);
+  run_loop.Run();
+
+  // Dialog should show because we clicked button 0 (Upgrade).
+  ExpectDialog();
+
+  RunUntilIdle();
+  // There should no longer be a button to click
+  EXPECT_TRUE(notification->Get()->buttons().empty());
+
+  SafelyCloseDialog();
+  ExpectNoDialog();
+
+  histogram_tester.ExpectUniqueSample(
+      "Crostini.UpgradeDialogEvent",
+      static_cast<base::HistogramBase::Sample>(
+          crostini::UpgradeDialogEvent::kDialogShown),
+      1);
+
+  histogram_tester.ExpectUniqueSample(
+      "Crostini.UpgradeAvailable",
+      static_cast<base::HistogramBase::Sample>(
+          crostini::CrostiniUpgradeAvailableNotificationClosed::kUpgradeButton),
+      1);
+}
+
+}  // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_util.cc b/chrome/browser/chromeos/crostini/crostini_util.cc
index d513a01..c12521e2 100644
--- a/chrome/browser/chromeos/crostini/crostini_util.cc
+++ b/chrome/browser/chromeos/crostini/crostini_util.cc
@@ -407,13 +407,12 @@
         files, std::move(callback));
   }
 
-  if (crostini_manager->ShouldPromptContainerUpgrade(
-          ContainerId(registration->VmName(), registration->ContainerName())) ||
-      crostini_manager->GetCrostiniDialogStatus(DialogType::UPGRADER)) {
-    chromeos::CrostiniUpgraderDialog::Show(base::BindOnce(
-        &LaunchCrostiniAppImpl, profile, app_id, std::move(*registration),
-        display_id, files, std::move(callback)));
-    VLOG(1) << "Upgrade dialog";
+  if (crostini_manager->GetCrostiniDialogStatus(DialogType::UPGRADER)) {
+    // Reshow the existing dialog.
+    chromeos::CrostiniUpgraderDialog::Reshow();
+    VLOG(1) << "Reshowing upgrade dialog";
+    std::move(callback).Run(
+        false, "LaunchCrostiniApp called while upgrade dialog showing");
     return;
   }
   LaunchCrostiniAppImpl(profile, app_id, std::move(*registration), display_id,
diff --git a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
index f7561f1..7c14293 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
@@ -12,11 +12,11 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "base/version.h"
@@ -279,7 +279,7 @@
   // Spin the loop until the cache shutdown callback is invoked. Verify that at
   // that point, no further file I/O tasks are pending.
   run_loop.Run();
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 }
 
 // Verifies that when a force-install list policy referencing an extension is
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index d617efa..f14e2cf 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -16,13 +16,13 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -614,7 +614,7 @@
 // static
 void ScreenLocker::Show() {
   base::RecordAction(UserMetricsAction("ScreenLocker_Show"));
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   // Check whether the currently logged in user is a guest account and if so,
   // refuse to lock the screen (crosbug.com/23764).
@@ -639,7 +639,7 @@
 
 // static
 void ScreenLocker::Hide() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   // For a guest user, screen_locker_ would have never been initialized.
   if (user_manager::UserManager::Get()->IsLoggedInAsGuest()) {
     VLOG(1) << "Refusing to hide lock screen for guest account";
@@ -709,7 +709,7 @@
 
 ScreenLocker::~ScreenLocker() {
   VLOG(1) << "Destroying ScreenLocker " << this;
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
 
   GetLoginScreenCertProviderService()
diff --git a/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc b/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc
index db5555b3..408f69f 100644
--- a/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc
+++ b/chrome/browser/chromeos/login/test/wizard_in_process_browser_test.cc
@@ -43,7 +43,7 @@
 }
 
 void WizardInProcessBrowserTest::TearDownOnMainThread() {
-  ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet());
+  ASSERT_TRUE(base::CurrentUIThread::IsSet());
 
   if (!host_)
     return;
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
index ac6ad1a..1997685 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl_unittest.cc
@@ -8,10 +8,10 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -930,9 +930,9 @@
   EXPECT_EQ(state_, AUTO_ENROLLMENT_STATE_PENDING);
 
   // Cancel while a request is in flight.
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   release_client()->CancelAndDeleteSoon();
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 
   // The client cleans itself up once a reply is received.
   service_->DoURLCompletion(&job, net::OK,
@@ -940,7 +940,7 @@
                             em::DeviceManagementResponse());
   EXPECT_EQ(nullptr, job);
   // The DeleteSoon task has been posted:
-  EXPECT_FALSE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_FALSE(base::CurrentThread::Get()->IsIdleForTesting());
   EXPECT_EQ(state_, AUTO_ENROLLMENT_STATE_PENDING);
 }
 
@@ -954,10 +954,10 @@
   EXPECT_EQ(state_, AUTO_ENROLLMENT_STATE_PENDING);
 
   // Cancel while a request is in flight.
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   AutoEnrollmentClientImpl* client = release_client();
   client->CancelAndDeleteSoon();
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 
   // Network change events are ignored while a request is pending.
   client->OnConnectionChanged(
@@ -971,7 +971,7 @@
                             em::DeviceManagementResponse());
   EXPECT_EQ(nullptr, job);
   // The DeleteSoon task has been posted:
-  EXPECT_FALSE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_FALSE(base::CurrentThread::Get()->IsIdleForTesting());
   EXPECT_EQ(state_, AUTO_ENROLLMENT_STATE_PENDING);
 
   // Network changes that have been posted before are also ignored:
@@ -1000,10 +1000,10 @@
 
   // The client will delete itself immediately if there are no pending
   // requests.
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   release_client()->CancelAndDeleteSoon();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 }
 
 TEST_P(AutoEnrollmentClientImplTest, CancelAndDeleteSoonAfterNetworkFailure) {
@@ -1016,10 +1016,10 @@
 
   // The client will delete itself immediately if there are no pending
   // requests.
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   release_client()->CancelAndDeleteSoon();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 }
 
 TEST_P(AutoEnrollmentClientImplTest, NetworkFailureThenRequireUpdatedModulus) {
diff --git a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
index 15c2a985..3c6715c 100644
--- a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
+++ b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
@@ -8,9 +8,9 @@
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/json/json_writer.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
index 08829f6..e1622ed4 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
 #include "chrome/browser/chromeos/policy/remote_commands/user_commands_factory_chromeos.h"
 #include "chrome/browser/chromeos/policy/wildcard_login_checker.h"
-#include "chrome/browser/enterprise/reporting/report_generator.h"
 #include "chrome/browser/enterprise/reporting/report_scheduler.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
@@ -41,6 +40,7 @@
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_features.h"
 #include "chromeos/constants/chromeos_switches.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 773a02ce..299fc870 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -12,6 +12,7 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
@@ -870,17 +871,21 @@
         base::FilePath() /* profile_path */,
         nullptr /* shared_cors_origin_access_list */);
   } else if (content::HasWebUIScheme(gurl)) {
-    content::WebContents* target_tab;
-#ifndef NDEBUG
-    // In debug builds, allow retrieving files from the chrome:// and
-    // devtools:// schemes
-    target_tab = DevToolsWindow::AsDevToolsWindow(web_contents_)
-                     ->GetInspectedWebContents();
-    const bool allow_web_ui_scheme =
-        target_tab && content::HasWebUIScheme(target_tab->GetURL());
+    // In debug builds, or when a custom devtools is used, allow retrieving
+    // files from the chrome:// and devtools:// schemes.
+#if defined(NDEBUG)
+    const bool devtools_should_be_debuggable = true;
 #else
-    const bool allow_web_ui_scheme = false;
+    const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+    const bool devtools_should_be_debuggable =
+        cmd_line->HasSwitch(switches::kCustomDevtoolsFrontend);
 #endif
+    content::WebContents* target_tab =
+        DevToolsWindow::AsDevToolsWindow(web_contents_)
+            ->GetInspectedWebContents();
+    const bool allow_web_ui_scheme =
+        devtools_should_be_debuggable && target_tab &&
+        content::HasWebUIScheme(target_tab->GetURL());
     if (allow_web_ui_scheme) {
       std::vector<std::string> allowed_webui_hosts;
       content::RenderFrameHost* frame_host = web_contents()->GetMainFrame();
@@ -889,6 +894,7 @@
           std::move(allowed_webui_hosts));
     } else {
       base::DictionaryValue response;
+      response.SetBoolean("schemeSupported", false);
       response.SetInteger("statusCode", 403);
       callback.Run(&response);
       return;
diff --git a/chrome/browser/enterprise/reporting/report_generator_desktop.h b/chrome/browser/enterprise/reporting/report_generator_desktop.h
index eed1c8e..1c8d946 100644
--- a/chrome/browser/enterprise/reporting/report_generator_desktop.h
+++ b/chrome/browser/enterprise/reporting/report_generator_desktop.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_DESKTOP_H_
 #define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_DESKTOP_H_
 
-#include "chrome/browser/enterprise/reporting/report_generator.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/enterprise/reporting/report_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
index 32ae217..3487aff 100644
--- a/chrome/browser/enterprise/reporting/report_generator_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_generator_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 "chrome/browser/enterprise/reporting/report_generator.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 
 #include <set>
 
diff --git a/chrome/browser/enterprise/reporting/report_scheduler.h b/chrome/browser/enterprise/reporting/report_scheduler.h
index adc127c0..38574a9 100644
--- a/chrome/browser/enterprise/reporting/report_scheduler.h
+++ b/chrome/browser/enterprise/reporting/report_scheduler.h
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "base/util/timer/wall_clock_timer.h"
 #include "chrome/browser/enterprise/reporting/notification/extension_request_observer_factory.h"
-#include "chrome/browser/enterprise/reporting/report_generator.h"
 #include "chrome/browser/upgrade_detector/build_state_observer.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 #include "components/enterprise/browser/reporting/report_uploader.h"
 #include "components/prefs/pref_change_registrar.h"
 
diff --git a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc
index f64cc5d..c085e9f1 100644
--- a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc
+++ b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc
@@ -13,7 +13,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/reporting/prefs.h"
-#include "chrome/browser/enterprise/reporting/report_generator.h"
 #include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/upgrade_detector/build_state.h"
@@ -24,6 +23,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/version_info/version_info.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h b/chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h
index b864623..f1c8f6d2 100644
--- a/chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h
+++ b/chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h
@@ -9,9 +9,9 @@
 
 #include <memory>
 
-#include "chrome/browser/enterprise/reporting/report_generator.h"
 #include "components/enterprise/browser/reporting/browser_report_generator.h"
 #include "components/enterprise/browser/reporting/profile_report_generator.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 
 namespace enterprise_reporting {
 
@@ -32,7 +32,8 @@
   std::unique_ptr<ProfileReportGenerator::Delegate>
   GetProfileReportGeneratorDelegate() override;
 
-  std::unique_ptr<ReportGenerator::Delegate> GetReportGeneratorDelegate();
+  std::unique_ptr<ReportGenerator::Delegate> GetReportGeneratorDelegate()
+      override;
 };
 
 }  // namespace enterprise_reporting
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
index cc923e6..b6d2c84 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -505,7 +505,13 @@
   if (params->signature)
     signature.assign(params->signature->begin(), params->signature->end());
 
-  service->ReplyToSignRequest(extension_id(), params->request_id, signature);
+  if (!service->ReplyToSignRequest(extension_id(), params->request_id,
+                                   signature)) {
+    // The request was aborted before, or the extension managed to bypass the
+    // checks in the API bindings and specified a bad or an already used id.
+    DLOG(WARNING) << "Unexpected reply of extension " << extension_id()
+                  << " to sign request " << params->request_id;
+  }
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 5d119dee..9ee28a4 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -23,7 +23,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
@@ -31,6 +30,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time_to_iso8601.h"
 #include "base/values.h"
diff --git a/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc b/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
index 47c5964..92e11af 100644
--- a/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
+++ b/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
@@ -7,8 +7,8 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -68,7 +68,7 @@
                  policy::POLICY_SOURCE_CLOUD,
                  base::WrapUnique(new base::Value(true)), nullptr);
     provider_.UpdateChromePolicy(policies);
-    DCHECK(base::MessageLoopCurrent::Get());
+    DCHECK(base::CurrentThread::Get());
     base::RunLoop loop;
     loop.RunUntilIdle();
   }
diff --git a/chrome/browser/geolocation/geolocation_permission_context_delegate_android.cc b/chrome/browser/geolocation/geolocation_permission_context_delegate_android.cc
index 56c64e7..0dbb91a5 100644
--- a/chrome/browser/geolocation/geolocation_permission_context_delegate_android.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context_delegate_android.cc
@@ -18,6 +18,7 @@
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "url/gurl.h"
 
 GeolocationPermissionContextDelegateAndroid::
@@ -34,8 +35,8 @@
     bool user_gesture,
     permissions::BrowserPermissionCallback* callback,
     permissions::GeolocationPermissionContext* context) {
-  if (InstalledWebappBridge::ShouldDelegateLocationPermission(
-          requesting_origin)) {
+  if (web_contents->GetDelegate() &&
+      web_contents->GetDelegate()->GetInstalledWebappGeolocationContext()) {
     InstalledWebappBridge::PermissionResponseCallback permission_callback =
         base::BindOnce(
             &permissions::GeolocationPermissionContext::NotifyPermissionSet,
diff --git a/chrome/browser/installable/installed_webapp_bridge.cc b/chrome/browser/installable/installed_webapp_bridge.cc
index 3d3d741..f130447 100644
--- a/chrome/browser/installable/installed_webapp_bridge.cc
+++ b/chrome/browser/installable/installed_webapp_bridge.cc
@@ -63,21 +63,6 @@
       base::android::AttachCurrentThread(), (jlong) provider);
 }
 
-bool InstalledWebappBridge::ShouldDelegateLocationPermission(
-    const GURL& origin_url) {
-  if (!base::FeatureList::IsEnabled(
-          chrome::android::kTrustedWebActivityLocationDelegation)) {
-    return false;
-  }
-
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> j_origin =
-      base::android::ConvertUTF8ToJavaString(env, origin_url.spec());
-  jboolean result = Java_InstalledWebappBridge_shouldDelegateLocationPermission(
-      env, j_origin);
-  return result;
-}
-
 void InstalledWebappBridge::DecidePermission(
     const GURL& origin_url,
     PermissionResponseCallback callback) {
diff --git a/chrome/browser/installable/installed_webapp_bridge.h b/chrome/browser/installable/installed_webapp_bridge.h
index 79f7d64..3f77307 100644
--- a/chrome/browser/installable/installed_webapp_bridge.h
+++ b/chrome/browser/installable/installed_webapp_bridge.h
@@ -22,9 +22,6 @@
 
   static void SetProviderInstance(InstalledWebappProvider* provider);
 
-  // Returns whether permission should be delegate to TWA.
-  static bool ShouldDelegateLocationPermission(const GURL& origin_url);
-
   static void DecidePermission(const GURL& origin_url,
                                PermissionResponseCallback callback);
 
diff --git a/chrome/browser/nearby_sharing/instantmessaging/constants.h b/chrome/browser/nearby_sharing/instantmessaging/constants.h
index 1e0b0d2e6..326cfd5 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/constants.h
+++ b/chrome/browser/nearby_sharing/instantmessaging/constants.h
@@ -24,4 +24,7 @@
 // Template for optional OAuth2 authorization HTTP header.
 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
 
+// Timeout for network calls to instantmessaging servers.
+const base::TimeDelta kNetworkTimeout = base::TimeDelta::FromMilliseconds(2500);
+
 #endif  // CHROME_BROWSER_NEARBY_SHARING_INSTANTMESSAGING_CONSTANTS_H_
diff --git a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
index 1e1acc112..a00969d7 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
+++ b/chrome/browser/nearby_sharing/instantmessaging/receive_messages_express.cc
@@ -106,6 +106,7 @@
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
                                                  kTrafficAnnotation);
+  url_loader_->SetTimeoutDuration(kNetworkTimeout);
   url_loader_->AttachStringForUpload(request.SerializeAsString(),
                                      "application/x-protobuf");
   url_loader_->DownloadAsStream(url_loader_factory_.get(), this);
diff --git a/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc b/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
index 63c47c30..3a4561e 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
+++ b/chrome/browser/nearby_sharing/instantmessaging/send_message_express.cc
@@ -105,6 +105,7 @@
   std::unique_ptr<network::SimpleURLLoader> send_url_loader =
       network::SimpleURLLoader::Create(std::move(resource_request),
                                        kTrafficAnnotation);
+  send_url_loader->SetTimeoutDuration(kNetworkTimeout);
   send_url_loader->AttachStringForUpload(request.SerializeAsString(),
                                          "application/x-protobuf");
   send_url_loader->DownloadToString(
diff --git a/chrome/browser/nearby_sharing/instantmessaging/token_fetcher.cc b/chrome/browser/nearby_sharing/instantmessaging/token_fetcher.cc
index 5d8e4dc..9dbf07a 100644
--- a/chrome/browser/nearby_sharing/instantmessaging/token_fetcher.cc
+++ b/chrome/browser/nearby_sharing/instantmessaging/token_fetcher.cc
@@ -18,11 +18,8 @@
 
 void TokenFetcher::GetAccessToken(
     base::OnceCallback<void(const std::string& token)> callback) {
-  // Using Mode::kWaitUntilRefreshTokenAvailable waits for the account to have a
-  // refresh token which can take forever if the user is not signed in (and
-  // doesnt sign in). Since nearby sharing is only available for already signed
-  // in users, we are using this mode to ensure that best effort in trying to
-  // get a token.
+  // Using Mode::Immediate since Nearby Share is only available for signed-in
+  // users.
 
   token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
       identity_manager_->GetPrimaryAccountId(
@@ -30,7 +27,7 @@
       kOAuthConsumerName, {GaiaConstants::kTachyonOAuthScope},
       base::BindOnce(&TokenFetcher::OnOAuthTokenFetched,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
-      signin::AccessTokenFetcher::Mode::kWaitUntilRefreshTokenAvailable);
+      signin::AccessTokenFetcher::Mode::kImmediate);
 }
 
 void TokenFetcher::OnOAuthTokenFetched(
diff --git a/chrome/browser/nearby_sharing/nearby_process_manager.cc b/chrome/browser/nearby_sharing/nearby_process_manager.cc
index 037dae56..f02fc56 100644
--- a/chrome/browser/nearby_sharing/nearby_process_manager.cc
+++ b/chrome/browser/nearby_sharing/nearby_process_manager.cc
@@ -21,16 +21,23 @@
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sharing/webrtc/ice_config_fetcher.h"
 #include "chrome/browser/sharing/webrtc/sharing_mojo_service.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "content/public/browser/network_context_client_base.h"
+#include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/service_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "device/bluetooth/adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/public/mojom/p2p.mojom.h"
+#include "services/network/public/mojom/p2p_trusted.mojom.h"
 
 namespace {
 
@@ -80,6 +87,33 @@
   return profile && entry->GetPath() == profile->GetPath();
 }
 
+template <typename T>
+struct MojoPipe {
+  mojo::PendingRemote<T> remote;
+  mojo::PendingReceiver<T> receiver{remote.InitWithNewPipeAndPassReceiver()};
+};
+
+class P2PTrustedSocketManagerClientImpl
+    : public network::mojom::P2PTrustedSocketManagerClient {
+ public:
+  explicit P2PTrustedSocketManagerClientImpl(
+      mojo::PendingRemote<network::mojom::P2PTrustedSocketManager>
+          socket_manager)
+      : socket_manager_(std::move(socket_manager)) {}
+  ~P2PTrustedSocketManagerClientImpl() override = default;
+
+  // network::mojom::P2PTrustedSocketManagerClient:
+  void InvalidSocketPortRangeRequested() override { NOTIMPLEMENTED(); }
+  void DumpPacket(const std::vector<uint8_t>& packet_header,
+                  uint64_t packet_length,
+                  bool incoming) override {
+    NOTIMPLEMENTED();
+  }
+
+ private:
+  mojo::Remote<network::mojom::P2PTrustedSocketManager> socket_manager_;
+};
+
 }  // namespace
 
 // static
@@ -233,8 +267,8 @@
   GetBluetoothAdapter(dependencies_ptr,
                       base::ScopedClosureRunner(done_closure));
 
-  GetWebRtcSignalingMessenger(dependencies_ptr,
-                              base::ScopedClosureRunner(done_closure));
+  GetWebRtcDependencies(dependencies_ptr,
+                        base::ScopedClosureRunner(done_closure));
 
   // Terminate the process if the Nearby Connections interface disconnects as
   // that indicated an incorrect state and we have to restart the process.
@@ -281,24 +315,55 @@
   dependencies->bluetooth_adapter = std::move(pending_adapter);
 }
 
-void NearbyProcessManager::GetWebRtcSignalingMessenger(
+void NearbyProcessManager::GetWebRtcDependencies(
     location::nearby::connections::mojom::NearbyConnectionsDependencies*
         dependencies,
     base::ScopedClosureRunner done_closure) {
   DCHECK(active_profile_);
 
+  auto* network_context =
+      content::BrowserContext::GetDefaultStoragePartition(active_profile_)
+          ->GetNetworkContext();
+
   auto url_loader_factory = active_profile_->GetURLLoaderFactory();
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(active_profile_);
 
-  mojo::PendingRemote<sharing::mojom::WebRtcSignalingMessenger> messenger;
-  mojo::MakeSelfOwnedReceiver(
-      std::make_unique<WebRtcSignalingMessenger>(identity_manager,
-                                                 std::move(url_loader_factory)),
-      messenger.InitWithNewPipeAndPassReceiver());
+  MojoPipe<network::mojom::P2PTrustedSocketManagerClient> socket_manager_client;
+  MojoPipe<network::mojom::P2PTrustedSocketManager> trusted_socket_manager;
+  MojoPipe<network::mojom::P2PSocketManager> socket_manager;
+  MojoPipe<network::mojom::MdnsResponder> mdns_responder;
 
-  NS_LOG(VERBOSE) << __func__ << " Got WebRTC signaling messenger";
-  dependencies->webrtc_signaling_messenger = std::move(messenger);
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<P2PTrustedSocketManagerClientImpl>(
+          std::move(trusted_socket_manager.remote)),
+      std::move(socket_manager_client.receiver));
+
+  // Create socket manager.
+  network_context->CreateP2PSocketManager(
+      net::NetworkIsolationKey::CreateTransient(),
+      std::move(socket_manager_client.remote),
+      std::move(trusted_socket_manager.receiver),
+      std::move(socket_manager.receiver));
+
+  // Create mdns responder.
+  network_context->CreateMdnsResponder(std::move(mdns_responder.receiver));
+
+  // Create ice config fetcher.
+  MojoPipe<sharing::mojom::IceConfigFetcher> ice_config_fetcher;
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<IceConfigFetcher>(url_loader_factory),
+      std::move(ice_config_fetcher.receiver));
+
+  MojoPipe<sharing::mojom::WebRtcSignalingMessenger> messenger;
+  mojo::MakeSelfOwnedReceiver(std::make_unique<WebRtcSignalingMessenger>(
+                                  identity_manager, url_loader_factory),
+                              std::move(messenger.receiver));
+
+  dependencies->webrtc_dependencies =
+      location::nearby::connections::mojom::WebRtcDependencies::New(
+          std::move(socket_manager.remote), std::move(mdns_responder.remote),
+          std::move(ice_config_fetcher.remote), std::move(messenger.remote));
 }
 
 void NearbyProcessManager::OnDependenciesGathered(
diff --git a/chrome/browser/nearby_sharing/nearby_process_manager.h b/chrome/browser/nearby_sharing/nearby_process_manager.h
index 385a35e3..4c9930f9 100644
--- a/chrome/browser/nearby_sharing/nearby_process_manager.h
+++ b/chrome/browser/nearby_sharing/nearby_process_manager.h
@@ -143,7 +143,7 @@
       base::ScopedClosureRunner done_closure,
       scoped_refptr<device::BluetoothAdapter> adapter);
 
-  void GetWebRtcSignalingMessenger(
+  void GetWebRtcDependencies(
       location::nearby::connections::mojom::NearbyConnectionsDependencies*
           dependencies,
       base::ScopedClosureRunner done_closure);
diff --git a/chrome/browser/nearby_sharing/nearby_process_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_process_manager_unittest.cc
index 0d1d6c1..6d89876 100644
--- a/chrome/browser/nearby_sharing/nearby_process_manager_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_process_manager_unittest.cc
@@ -163,7 +163,8 @@
         profile->GetProfileUserName());
   }
 
-  content::BrowserTaskEnvironment task_environment_;
+  content::BrowserTaskEnvironment task_environment_{
+      content::BrowserTaskEnvironment::MainThreadType::IO};
   content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
   TestingProfileManager testing_profile_manager_{
       TestingBrowserProcess::GetGlobal()};
@@ -308,7 +309,7 @@
   fake_sharing_service.WaitForConnections();
 
   EXPECT_TRUE(fake_sharing_service.dependencies()->bluetooth_adapter);
-  EXPECT_TRUE(fake_sharing_service.dependencies()->webrtc_signaling_messenger);
+  EXPECT_TRUE(fake_sharing_service.dependencies()->webrtc_dependencies);
 }
 
 TEST_F(NearbyProcessManagerTest,
@@ -331,7 +332,7 @@
   fake_sharing_service.WaitForConnections();
 
   EXPECT_FALSE(fake_sharing_service.dependencies()->bluetooth_adapter);
-  EXPECT_TRUE(fake_sharing_service.dependencies()->webrtc_signaling_messenger);
+  EXPECT_TRUE(fake_sharing_service.dependencies()->webrtc_dependencies);
 }
 
 TEST_F(NearbyProcessManagerTest, ResetNearbyProcess) {
diff --git a/chrome/browser/net/samesite_cookies_policy_browsertest.cc b/chrome/browser/net/samesite_cookies_policy_browsertest.cc
index e2b61208..07fc3f2 100644
--- a/chrome/browser/net/samesite_cookies_policy_browsertest.cc
+++ b/chrome/browser/net/samesite_cookies_policy_browsertest.cc
@@ -26,15 +26,17 @@
 }  // namespace
 
 // Test fixture that enables (if param is true) and disables (if param is false)
-// SameSite-by-default and Cookies-without-SameSite-must-be-Secure, to test the
-// policies that override those features, under both conditions.
+// SameSite-by-default, Cookies-without-SameSite-must-be-Secure, and Schemeful
+// Same-Site to test the policies that override those features, under both
+// conditions.
 class SameSiteCookiesPolicyTest : public PolicyTest,
                                   public ::testing::WithParamInterface<bool> {
  public:
   SameSiteCookiesPolicyTest() {
     std::vector<base::Feature> samesite_features = {
         net::features::kSameSiteByDefaultCookies,
-        net::features::kCookiesWithoutSameSiteMustBeSecure};
+        net::features::kCookiesWithoutSameSiteMustBeSecure,
+        net::features::kSchemefulSameSite};
     if (AreSameSiteFeaturesEnabled()) {
       feature_list_.InitWithFeatures(samesite_features /* enabled */, {});
     } else {
@@ -90,6 +92,25 @@
                                 net::CookieOptions::SameSiteCookieContext(
                                     net::CookieOptions::SameSiteCookieContext::
                                         ContextType::CROSS_SITE)));
+
+  // When Schemeful Same-Site is enabled a context downgrade to an insufficient
+  // context should still be allowed with legacy access. This'll always work if
+  // Schemeful Same-Site is disabled because the schemeless context is Lax
+  // which is sufficient.
+  EXPECT_TRUE(content::SetCookie(
+      profile, url, "samesite-lax=1; SameSite=Lax",
+      net::CookieOptions::SameSiteCookieContext(
+          net::CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX,
+          net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE)));
+  // Similarly when we try to get the cookie.
+  EXPECT_THAT(
+      content::GetCookies(profile, url,
+                          net::CookieOptions::SameSiteCookieContext(
+                              net::CookieOptions::SameSiteCookieContext::
+                                  ContextType::SAME_SITE_LAX,
+                              net::CookieOptions::SameSiteCookieContext::
+                                  ContextType::CROSS_SITE)),
+      testing::HasSubstr("samesite-lax=1"));
 }
 
 IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
@@ -132,6 +153,48 @@
                                 net::CookieOptions::SameSiteCookieContext(
                                     net::CookieOptions::SameSiteCookieContext::
                                         ContextType::CROSS_SITE)));
+
+  // When Schemeful Same-Site is enabled a context downgrade to an insufficient
+  // context should always be blocked. If Schemeful Same-Site is disabled then
+  // this shouldn't be blocked.
+  // Similarly when we try to get the cookie.
+  if (AreSameSiteFeaturesEnabled()) {
+    EXPECT_FALSE(
+        content::SetCookie(profile, url, "samesite-lax=1; SameSite=Lax",
+                           net::CookieOptions::SameSiteCookieContext(
+                               net::CookieOptions::SameSiteCookieContext::
+                                   ContextType::SAME_SITE_LAX,
+                               net::CookieOptions::SameSiteCookieContext::
+                                   ContextType::CROSS_SITE)));
+    // We should be able to get the cookie which was previously added.
+    EXPECT_EQ("samesite-unspecified=1", content::GetCookies(profile, url));
+    // But no cookies should be returned for a downgrade to an insufficient
+    // context, since SameSite-by-default is active which requires a minimum of
+    // a Lax context.
+    EXPECT_EQ(
+        "", content::GetCookies(profile, url,
+                                net::CookieOptions::SameSiteCookieContext(
+                                    net::CookieOptions::SameSiteCookieContext::
+                                        ContextType::SAME_SITE_LAX,
+                                    net::CookieOptions::SameSiteCookieContext::
+                                        ContextType::CROSS_SITE)));
+  } else {
+    EXPECT_TRUE(
+        content::SetCookie(profile, url, "samesite-lax=1; SameSite=Lax",
+                           net::CookieOptions::SameSiteCookieContext(
+                               net::CookieOptions::SameSiteCookieContext::
+                                   ContextType::SAME_SITE_LAX,
+                               net::CookieOptions::SameSiteCookieContext::
+                                   ContextType::CROSS_SITE)));
+    EXPECT_THAT(
+        content::GetCookies(profile, url,
+                            net::CookieOptions::SameSiteCookieContext(
+                                net::CookieOptions::SameSiteCookieContext::
+                                    ContextType::SAME_SITE_LAX,
+                                net::CookieOptions::SameSiteCookieContext::
+                                    ContextType::CROSS_SITE)),
+        testing::HasSubstr("samesite-lax=1"));
+  }
 }
 
 IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
@@ -190,6 +253,25 @@
                                 net::CookieOptions::SameSiteCookieContext(
                                     net::CookieOptions::SameSiteCookieContext::
                                         ContextType::CROSS_SITE)));
+  // When Schemeful Same-Site is enabled a context downgrade to an insufficient
+  // context should still be allowed with legacy access. This'll always work if
+  // Schemeful Same-Site is disabled because the schemeless context is Lax
+  // which is sufficient.
+  EXPECT_TRUE(content::SetCookie(
+      profile, legacy_allowed_domain_url, "samesite-lax=1; SameSite=Lax",
+      net::CookieOptions::SameSiteCookieContext(
+          net::CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX,
+          net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE)));
+  // Similarly when we try to get the cookie.
+  EXPECT_THAT(
+      content::GetCookies(profile, legacy_allowed_domain_url,
+                          net::CookieOptions::SameSiteCookieContext(
+                              net::CookieOptions::SameSiteCookieContext::
+                                  ContextType::SAME_SITE_LAX,
+                              net::CookieOptions::SameSiteCookieContext::
+                                  ContextType::CROSS_SITE)),
+      testing::HasSubstr("samesite-lax=1"));
+
   // For the domain that is not Legacy by policy, we expect it to work only if
   // the SameSite features are disabled.
   if (AreSameSiteFeaturesEnabled()) {
@@ -205,6 +287,26 @@
                                 net::CookieOptions::SameSiteCookieContext(
                                     net::CookieOptions::SameSiteCookieContext::
                                         ContextType::CROSS_SITE)));
+    EXPECT_FALSE(content::SetCookie(
+        profile, other_domain_url, "samesite-lax=1; SameSite=Lax",
+        net::CookieOptions::SameSiteCookieContext(
+            net::CookieOptions::SameSiteCookieContext::ContextType::
+                SAME_SITE_LAX,
+            net::CookieOptions::SameSiteCookieContext::ContextType::
+                CROSS_SITE)));
+    // We should be able to get the cookie which was previously added.
+    EXPECT_EQ("samesite-unspecified=1",
+              content::GetCookies(profile, other_domain_url));
+    // But no cookies should be returned for a downgrade to an insufficient
+    // context, since SameSite-by-default is active which requires a minimum of
+    // a Lax context.
+    EXPECT_EQ(
+        "", content::GetCookies(profile, other_domain_url,
+                                net::CookieOptions::SameSiteCookieContext(
+                                    net::CookieOptions::SameSiteCookieContext::
+                                        ContextType::SAME_SITE_LAX,
+                                    net::CookieOptions::SameSiteCookieContext::
+                                        ContextType::CROSS_SITE)));
   } else {
     EXPECT_TRUE(
         content::SetCookie(profile, other_domain_url, "samesite-unspecified=2",
@@ -219,6 +321,22 @@
                             net::CookieOptions::SameSiteCookieContext(
                                 net::CookieOptions::SameSiteCookieContext::
                                     ContextType::CROSS_SITE)));
+
+    EXPECT_TRUE(content::SetCookie(
+        profile, other_domain_url, "samesite-lax=1; SameSite=Lax",
+        net::CookieOptions::SameSiteCookieContext(
+            net::CookieOptions::SameSiteCookieContext::ContextType::
+                SAME_SITE_LAX,
+            net::CookieOptions::SameSiteCookieContext::ContextType::
+                CROSS_SITE)));
+    EXPECT_THAT(
+        content::GetCookies(profile, other_domain_url,
+                            net::CookieOptions::SameSiteCookieContext(
+                                net::CookieOptions::SameSiteCookieContext::
+                                    ContextType::SAME_SITE_LAX,
+                                net::CookieOptions::SameSiteCookieContext::
+                                    ContextType::CROSS_SITE)),
+        testing::HasSubstr("samesite-lax=1"));
   }
 }
 
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn
index 3a3c66af..2c651b3 100644
--- a/chrome/browser/password_check/android/internal/BUILD.gn
+++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -3,7 +3,9 @@
 # found in the LICENSE file.
 
 import("//build/config/android/rules.gni")
+import("//build/config/locales.gni")
 import("//chrome/android/features/android_library_factory_tmpl.gni")
+import("//chrome/common/features.gni")
 
 _factory_sources = [ "java/src/org/chromium/chrome/browser/password_check/PasswordCheckFactory.java" ]
 _public_target = "//chrome/browser/password_check/android:public_java"
@@ -88,9 +90,21 @@
 }
 
 android_resources("java_resources") {
+  deps = [ ":java_strings_grd" ]
   sources = [
     "java/res/layout/password_check_compromised_credential_item.xml",
     "java/res/layout/password_check_header_item.xml",
+    "java/res/values/dimens.xml",
   ]
   custom_package = "org.chromium.chrome.browser.password_check.internal"
 }
+
+java_strings_grd("java_strings_grd") {
+  defines = chrome_grit_defines
+  grd_file = "java/strings/android_password_check_strings.grd"
+  outputs =
+      [ "values/android_password_check_strings.xml" ] +
+      process_file_template(
+          android_bundle_locales_as_resources,
+          [ "values-{{source_name_part}}/android_password_check_strings.xml" ])
+}
diff --git a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml
index c6c487cd..04cceccb 100644
--- a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml
+++ b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml
@@ -2,9 +2,62 @@
 <!-- Copyright 2020 The Chromium Authors. All rights reserved.
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/credential_origin"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillViewport="true"
+    android:gravity="center"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
-    android:textAppearance="@style/TextAppearance.TextMedium.Secondary" />
+    android:orientation="horizontal">
+
+    <!-- TODO(crbug.com/1106277): Remove the paddingStart if favicons fill that space. -->
+    <LinearLayout
+        android:gravity="start"
+        android:layout_gravity="top"
+        android:layout_height="wrap_content"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:paddingStart="@dimen/compromised_credential_row_padding_start"
+        android:paddingBottom="@dimen/compromised_credential_row_padding_bottom"
+        android:paddingTop="@dimen/compromised_credential_row_padding_top">
+
+        <TextView
+            android:id="@+id/credential_origin"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
+
+        <TextView
+            android:id="@+id/compromised_username"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:textAppearance="@style/TextAppearance.TextMedium.Secondary" />
+
+        <TextView
+            android:id="@+id/compromised_reason"
+            android:layout_marginTop="@dimen/compromised_credential_row_reason_margin_top"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
+
+        <org.chromium.ui.widget.ButtonCompat
+            android:id="@+id/credential_change_button"
+            android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:text="@string/password_check_credential_row_change_button_caption"
+            style="@style/FilledButton.Flat" />
+
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/credential_menu_button"
+        android:contentDescription="@string/more"
+        android:paddingEnd="@dimen/compromised_credential_row_more_padding_end"
+        android:paddingStart="@dimen/compromised_credential_row_more_padding_start"
+        android:layout_gravity="top"
+        android:layout_height="@dimen/compromised_credential_row_more_size"
+        android:layout_width="@dimen/compromised_credential_row_more_size"
+        android:src="@drawable/ic_more_vert_24dp" />
+
+</LinearLayout>
diff --git a/chrome/browser/password_check/android/internal/java/res/values/dimens.xml b/chrome/browser/password_check/android/internal/java/res/values/dimens.xml
new file mode 100644
index 0000000..692319d
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/res/values/dimens.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<resources>
+  <dimen name="compromised_credential_row_button_margin_top">16dp</dimen>
+  <dimen name="compromised_credential_row_more_padding_end">8dp</dimen>
+  <dimen name="compromised_credential_row_more_padding_start">16dp</dimen>
+  <dimen name="compromised_credential_row_more_size">48dp</dimen>
+  <dimen name="compromised_credential_row_padding_bottom">16dp</dimen>
+  <dimen name="compromised_credential_row_padding_start">16dp</dimen>
+  <dimen name="compromised_credential_row_padding_top">12dp</dimen>
+  <dimen name="compromised_credential_row_reason_margin_top">2dp</dimen>
+</resources>
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
index 597491a..61e831a4 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
@@ -22,10 +22,10 @@
 
     PasswordCheckCoordinator(PasswordCheckFragmentView fragmentView) {
         mFragmentView = fragmentView;
-        PropertyModel model = new PropertyModel.Builder(PasswordCheckProperties.ALL_KEYS).build();
+        PropertyModel model = PasswordCheckProperties.createDefaultModel();
         PasswordCheckMediator mediator = new PasswordCheckMediator();
-        mediator.initialize(model);
         PasswordCheckCoordinator.setUpModelChangeProcessors(model, mFragmentView);
+        mediator.initialize(model);
     }
 
     // TODO(crbug.com/1101256): Move to view code.
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
index 7b69bcb..ce51737 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
@@ -92,6 +92,14 @@
             formattedOrigin =
                     formattedOrigin.replaceFirst("/$", ""); // Strip possibly trailing slash.
             pslOriginText.setText(formattedOrigin);
+
+            TextView username = view.findViewById(R.id.compromised_username);
+            username.setText(credential.getUsername());
+
+            TextView reason = view.findViewById(R.id.compromised_reason);
+            reason.setText(credential.isPhished()
+                            ? R.string.password_check_credential_row_reason_phished
+                            : R.string.password_check_credential_row_reason_leaked);
         } else {
             assert false : "Unhandled update to property:" + propertyKey;
         }
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd
new file mode 100644
index 0000000..8823387
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<grit current_release="1" latest_public_release="0" output_all_resource_defines="false">
+  <outputs>
+    <output filename="values-af/android_password_check_strings.xml" lang="af" type="android" />
+    <output filename="values-am/android_password_check_strings.xml" lang="am" type="android" />
+    <output filename="values-ar/android_password_check_strings.xml" lang="ar" type="android" />
+    <output filename="values-as/android_password_check_strings.xml" lang="as" type="android" />
+    <output filename="values-az/android_password_check_strings.xml" lang="az" type="android" />
+    <output filename="values-be/android_password_check_strings.xml" lang="be" type="android" />
+    <output filename="values-bg/android_password_check_strings.xml" lang="bg" type="android" />
+    <output filename="values-bn/android_password_check_strings.xml" lang="bn" type="android" />
+    <output filename="values-bs/android_password_check_strings.xml" lang="bs" type="android" />
+    <output filename="values-ca/android_password_check_strings.xml" lang="ca" type="android" />
+    <output filename="values-cs/android_password_check_strings.xml" lang="cs" type="android" />
+    <output filename="values-da/android_password_check_strings.xml" lang="da" type="android" />
+    <output filename="values-de/android_password_check_strings.xml" lang="de" type="android" />
+    <output filename="values-el/android_password_check_strings.xml" lang="el" type="android" />
+    <output filename="values/android_password_check_strings.xml" lang="en" type="android" />
+    <output filename="values-en-rGB/android_password_check_strings.xml" lang="en-GB" type="android" />
+    <output filename="values-es/android_password_check_strings.xml" lang="es" type="android" />
+    <output filename="values-es-rUS/android_password_check_strings.xml" lang="es-419" type="android" />
+    <output filename="values-et/android_password_check_strings.xml" lang="et" type="android" />
+    <output filename="values-eu/android_password_check_strings.xml" lang="eu" type="android" />
+    <output filename="values-fa/android_password_check_strings.xml" lang="fa" type="android" />
+    <output filename="values-fi/android_password_check_strings.xml" lang="fi" type="android" />
+    <output filename="values-tl/android_password_check_strings.xml" lang="fil" type="android" />
+    <output filename="values-fr/android_password_check_strings.xml" lang="fr" type="android" />
+    <output filename="values-fr-rCA/android_password_check_strings.xml" lang="fr-CA" type="android" />
+    <output filename="values-gl/android_password_check_strings.xml" lang="gl" type="android" />
+    <output filename="values-gu/android_password_check_strings.xml" lang="gu" type="android" />
+    <output filename="values-hi/android_password_check_strings.xml" lang="hi" type="android" />
+    <output filename="values-hr/android_password_check_strings.xml" lang="hr" type="android" />
+    <output filename="values-hu/android_password_check_strings.xml" lang="hu" type="android" />
+    <output filename="values-hy/android_password_check_strings.xml" lang="hy" type="android" />
+    <output filename="values-in/android_password_check_strings.xml" lang="id" type="android" />
+    <output filename="values-is/android_password_check_strings.xml" lang="is" type="android" />
+    <output filename="values-it/android_password_check_strings.xml" lang="it" type="android" />
+    <output filename="values-iw/android_password_check_strings.xml" lang="iw" type="android" />
+    <output filename="values-ja/android_password_check_strings.xml" lang="ja" type="android" />
+    <output filename="values-ka/android_password_check_strings.xml" lang="ka" type="android" />
+    <output filename="values-kk/android_password_check_strings.xml" lang="kk" type="android" />
+    <output filename="values-km/android_password_check_strings.xml" lang="km" type="android" />
+    <output filename="values-kn/android_password_check_strings.xml" lang="kn" type="android" />
+    <output filename="values-ko/android_password_check_strings.xml" lang="ko" type="android" />
+    <output filename="values-ky/android_password_check_strings.xml" lang="ky" type="android" />
+    <output filename="values-lo/android_password_check_strings.xml" lang="lo" type="android" />
+    <output filename="values-lt/android_password_check_strings.xml" lang="lt" type="android" />
+    <output filename="values-lv/android_password_check_strings.xml" lang="lv" type="android" />
+    <output filename="values-mk/android_password_check_strings.xml" lang="mk" type="android" />
+    <output filename="values-ml/android_password_check_strings.xml" lang="ml" type="android" />
+    <output filename="values-mn/android_password_check_strings.xml" lang="mn" type="android" />
+    <output filename="values-mr/android_password_check_strings.xml" lang="mr" type="android" />
+    <output filename="values-ms/android_password_check_strings.xml" lang="ms" type="android" />
+    <output filename="values-my/android_password_check_strings.xml" lang="my" type="android" />
+    <output filename="values-ne/android_password_check_strings.xml" lang="ne" type="android" />
+    <output filename="values-nl/android_password_check_strings.xml" lang="nl" type="android" />
+    <output filename="values-nb/android_password_check_strings.xml" lang="no" type="android" />
+    <output filename="values-or/android_password_check_strings.xml" lang="or" type="android" />
+    <output filename="values-pa/android_password_check_strings.xml" lang="pa" type="android" />
+    <output filename="values-pl/android_password_check_strings.xml" lang="pl" type="android" />
+    <output filename="values-pt-rBR/android_password_check_strings.xml" lang="pt-BR" type="android" />
+    <output filename="values-pt-rPT/android_password_check_strings.xml" lang="pt-PT" type="android" />
+    <output filename="values-ro/android_password_check_strings.xml" lang="ro" type="android" />
+    <output filename="values-ru/android_password_check_strings.xml" lang="ru" type="android" />
+    <output filename="values-si/android_password_check_strings.xml" lang="si" type="android" />
+    <output filename="values-sk/android_password_check_strings.xml" lang="sk" type="android" />
+    <output filename="values-sl/android_password_check_strings.xml" lang="sl" type="android" />
+    <output filename="values-sq/android_password_check_strings.xml" lang="sq" type="android" />
+    <output filename="values-sr/android_password_check_strings.xml" lang="sr" type="android" />
+    <output filename="values-b+sr+Latn/android_password_check_strings.xml" lang="sr-Latn" type="android" />
+    <output filename="values-sv/android_password_check_strings.xml" lang="sv" type="android" />
+    <output filename="values-sw/android_password_check_strings.xml" lang="sw" type="android" />
+    <output filename="values-ta/android_password_check_strings.xml" lang="ta" type="android" />
+    <output filename="values-te/android_password_check_strings.xml" lang="te" type="android" />
+    <output filename="values-th/android_password_check_strings.xml" lang="th" type="android" />
+    <output filename="values-tr/android_password_check_strings.xml" lang="tr" type="android" />
+    <output filename="values-uk/android_password_check_strings.xml" lang="uk" type="android" />
+    <output filename="values-ur/android_password_check_strings.xml" lang="ur" type="android" />
+    <output filename="values-uz/android_password_check_strings.xml" lang="uz" type="android" />
+    <output filename="values-vi/android_password_check_strings.xml" lang="vi" type="android" />
+    <output filename="values-zh-rCN/android_password_check_strings.xml" lang="zh-CN" type="android" />
+    <output filename="values-zh-rHK/android_password_check_strings.xml" lang="zh-HK" type="android" />
+    <output filename="values-zh-rTW/android_password_check_strings.xml" lang="zh-TW" type="android" />
+    <output filename="values-zu/android_password_check_strings.xml" lang="zu" type="android" />
+  </outputs>
+  <translations>
+    <file lang="af" path="translations/android_password_check_strings_af.xtb" />
+    <file lang="am" path="translations/android_password_check_strings_am.xtb" />
+    <file lang="ar" path="translations/android_password_check_strings_ar.xtb" />
+    <file lang="as" path="translations/android_password_check_strings_as.xtb" />
+    <file lang="az" path="translations/android_password_check_strings_az.xtb" />
+    <file lang="be" path="translations/android_password_check_strings_be.xtb" />
+    <file lang="bg" path="translations/android_password_check_strings_bg.xtb" />
+    <file lang="bn" path="translations/android_password_check_strings_bn.xtb" />
+    <file lang="bs" path="translations/android_password_check_strings_bs.xtb" />
+    <file lang="ca" path="translations/android_password_check_strings_ca.xtb" />
+    <file lang="cs" path="translations/android_password_check_strings_cs.xtb" />
+    <file lang="da" path="translations/android_password_check_strings_da.xtb" />
+    <file lang="de" path="translations/android_password_check_strings_de.xtb" />
+    <file lang="el" path="translations/android_password_check_strings_el.xtb" />
+    <file lang="en-GB" path="translations/android_password_check_strings_en-GB.xtb" />
+    <file lang="es" path="translations/android_password_check_strings_es.xtb" />
+    <file lang="es-419" path="translations/android_password_check_strings_es-419.xtb" />
+    <file lang="et" path="translations/android_password_check_strings_et.xtb" />
+    <file lang="eu" path="translations/android_password_check_strings_eu.xtb" />
+    <file lang="fa" path="translations/android_password_check_strings_fa.xtb" />
+    <file lang="fi" path="translations/android_password_check_strings_fi.xtb" />
+    <file lang="fil" path="translations/android_password_check_strings_fil.xtb" />
+    <file lang="fr" path="translations/android_password_check_strings_fr.xtb" />
+    <file lang="fr-CA" path="translations/android_password_check_strings_fr-CA.xtb" />
+    <file lang="gl" path="translations/android_password_check_strings_gl.xtb" />
+    <file lang="gu" path="translations/android_password_check_strings_gu.xtb" />
+    <file lang="hi" path="translations/android_password_check_strings_hi.xtb" />
+    <file lang="hr" path="translations/android_password_check_strings_hr.xtb" />
+    <file lang="hu" path="translations/android_password_check_strings_hu.xtb" />
+    <file lang="hy" path="translations/android_password_check_strings_hy.xtb" />
+    <file lang="id" path="translations/android_password_check_strings_id.xtb" />
+    <file lang="is" path="translations/android_password_check_strings_is.xtb" />
+    <file lang="it" path="translations/android_password_check_strings_it.xtb" />
+    <file lang="iw" path="translations/android_password_check_strings_iw.xtb" />
+    <file lang="ja" path="translations/android_password_check_strings_ja.xtb" />
+    <file lang="ka" path="translations/android_password_check_strings_ka.xtb" />
+    <file lang="kk" path="translations/android_password_check_strings_kk.xtb" />
+    <file lang="km" path="translations/android_password_check_strings_km.xtb" />
+    <file lang="kn" path="translations/android_password_check_strings_kn.xtb" />
+    <file lang="ko" path="translations/android_password_check_strings_ko.xtb" />
+    <file lang="ky" path="translations/android_password_check_strings_ky.xtb" />
+    <file lang="lo" path="translations/android_password_check_strings_lo.xtb" />
+    <file lang="lt" path="translations/android_password_check_strings_lt.xtb" />
+    <file lang="lv" path="translations/android_password_check_strings_lv.xtb" />
+    <file lang="mk" path="translations/android_password_check_strings_mk.xtb" />
+    <file lang="ml" path="translations/android_password_check_strings_ml.xtb" />
+    <file lang="mn" path="translations/android_password_check_strings_mn.xtb" />
+    <file lang="mr" path="translations/android_password_check_strings_mr.xtb" />
+    <file lang="ms" path="translations/android_password_check_strings_ms.xtb" />
+    <file lang="my" path="translations/android_password_check_strings_my.xtb" />
+    <file lang="ne" path="translations/android_password_check_strings_ne.xtb" />
+    <file lang="nl" path="translations/android_password_check_strings_nl.xtb" />
+    <file lang="no" path="translations/android_password_check_strings_no.xtb" />
+    <file lang="or" path="translations/android_password_check_strings_or.xtb" />
+    <file lang="pa" path="translations/android_password_check_strings_pa.xtb" />
+    <file lang="pl" path="translations/android_password_check_strings_pl.xtb" />
+    <file lang="pt-BR" path="translations/android_password_check_strings_pt-BR.xtb" />
+    <file lang="pt-PT" path="translations/android_password_check_strings_pt-PT.xtb" />
+    <file lang="ro" path="translations/android_password_check_strings_ro.xtb" />
+    <file lang="ru" path="translations/android_password_check_strings_ru.xtb" />
+    <file lang="si" path="translations/android_password_check_strings_si.xtb" />
+    <file lang="sk" path="translations/android_password_check_strings_sk.xtb" />
+    <file lang="sl" path="translations/android_password_check_strings_sl.xtb" />
+    <file lang="sq" path="translations/android_password_check_strings_sq.xtb" />
+    <file lang="sr" path="translations/android_password_check_strings_sr.xtb" />
+    <file lang="sr-Latn" path="translations/android_password_check_strings_sr-Latn.xtb" />
+    <file lang="sv" path="translations/android_password_check_strings_sv.xtb" />
+    <file lang="sw" path="translations/android_password_check_strings_sw.xtb" />
+    <file lang="ta" path="translations/android_password_check_strings_ta.xtb" />
+    <file lang="te" path="translations/android_password_check_strings_te.xtb" />
+    <file lang="th" path="translations/android_password_check_strings_th.xtb" />
+    <file lang="tr" path="translations/android_password_check_strings_tr.xtb" />
+    <file lang="uk" path="translations/android_password_check_strings_uk.xtb" />
+    <file lang="ur" path="translations/android_password_check_strings_ur.xtb" />
+    <file lang="uz" path="translations/android_password_check_strings_uz.xtb" />
+    <file lang="vi" path="translations/android_password_check_strings_vi.xtb" />
+    <file lang="zh-CN" path="translations/android_password_check_strings_zh-CN.xtb" />
+    <file lang="zh-HK" path="translations/android_password_check_strings_zh-HK.xtb" />
+    <file lang="zh-TW" path="translations/android_password_check_strings_zh-TW.xtb" />
+    <file lang="zu" path="translations/android_password_check_strings_zu.xtb" />
+  </translations>
+  <release allow_pseudo="false" seq="1">
+    <messages fallback_to_english="true">
+      <!-- Password Check -->
+      <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_CAPTION" desc="Caption for the button that links to a site where the user can change a compromised credential.">
+        Change password
+      </message>
+      <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_LEAKED" desc="Small description explaining that a credential is compromised because it was part of a data breach.">
+        Found in data breach
+      </message>
+      <message name="IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_PHISHED" desc="Small description explaining that a credential is compromised because it was entered on a deceptive site.">
+        Entered on a deceptive site
+      </message>
+    </messages>
+  </release>
+</grit>
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_CAPTION.png.sha1 b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_CAPTION.png.sha1
new file mode 100644
index 0000000..32e161a4
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_CHANGE_BUTTON_CAPTION.png.sha1
@@ -0,0 +1 @@
+662ab4bd4aec81ac0ef54848efad843452a0a601
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_LEAKED.png.sha1 b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_LEAKED.png.sha1
new file mode 100644
index 0000000..32e161a4
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_LEAKED.png.sha1
@@ -0,0 +1 @@
+662ab4bd4aec81ac0ef54848efad843452a0a601
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_PHISHED.png.sha1 b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_PHISHED.png.sha1
new file mode 100644
index 0000000..45892d9
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/android_password_check_strings_grd/IDS_PASSWORD_CHECK_CREDENTIAL_ROW_REASON_PHISHED.png.sha1
@@ -0,0 +1 @@
+952ee79c665274f11d86424f83fa10ee1bfc3c13
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_af.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_af.xtb
new file mode 100644
index 0000000..b369e833
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_af.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="af">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_am.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_am.xtb
new file mode 100644
index 0000000..92406ec2
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_am.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="am">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ar.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ar.xtb
new file mode 100644
index 0000000..198ea62
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ar.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ar">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_as.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_as.xtb
new file mode 100644
index 0000000..9aebd78
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_as.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="as">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_az.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_az.xtb
new file mode 100644
index 0000000..db47f35
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_az.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="az">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_be.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_be.xtb
new file mode 100644
index 0000000..ccab734
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_be.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="be">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bg.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bg.xtb
new file mode 100644
index 0000000..6681995
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bg.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bg">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bn.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bn.xtb
new file mode 100644
index 0000000..eca68d46
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bn.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bn">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bs.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bs.xtb
new file mode 100644
index 0000000..07aea3c6
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_bs.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bs">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ca.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ca.xtb
new file mode 100644
index 0000000..71cdd772
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ca.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ca">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_cs.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_cs.xtb
new file mode 100644
index 0000000..dc153a85
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_cs.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="cs">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_da.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_da.xtb
new file mode 100644
index 0000000..1256832
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_da.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="da">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_de.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_de.xtb
new file mode 100644
index 0000000..43dd909
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_de.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="de">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_el.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_el.xtb
new file mode 100644
index 0000000..1b096642
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_el.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="el">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_en-GB.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_en-GB.xtb
new file mode 100644
index 0000000..12c3fa00
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_en-GB.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="en-GB">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es-419.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es-419.xtb
new file mode 100644
index 0000000..b652ed0
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es-419.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es-419">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es.xtb
new file mode 100644
index 0000000..4d4f400
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_es.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_et.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_et.xtb
new file mode 100644
index 0000000..ab777bc5
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_et.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="et">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_eu.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_eu.xtb
new file mode 100644
index 0000000..6910975
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_eu.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="eu">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fa.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fa.xtb
new file mode 100644
index 0000000..4cff15d
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fa.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fa">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fi.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fi.xtb
new file mode 100644
index 0000000..60ba9aa
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fil.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fil.xtb
new file mode 100644
index 0000000..8f6a880
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fil.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fil">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr-CA.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr-CA.xtb
new file mode 100644
index 0000000..e2557d0
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr-CA.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr-CA">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr.xtb
new file mode 100644
index 0000000..bf48975a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_fr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gl.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gl.xtb
new file mode 100644
index 0000000..e04c577
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="gl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gu.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gu.xtb
new file mode 100644
index 0000000..7969d06
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_gu.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="gu">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hi.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hi.xtb
new file mode 100644
index 0000000..279503cd
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hr.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hr.xtb
new file mode 100644
index 0000000..9ec62af
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hu.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hu.xtb
new file mode 100644
index 0000000..bdc02ee
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hu.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hu">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hy.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hy.xtb
new file mode 100644
index 0000000..c9b28dd
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_hy.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hy">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_id.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_id.xtb
new file mode 100644
index 0000000..5f2882d
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_id.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="id">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_is.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_is.xtb
new file mode 100644
index 0000000..6d0302a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_is.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="is">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_it.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_it.xtb
new file mode 100644
index 0000000..e7df702
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_it.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="it">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_iw.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_iw.xtb
new file mode 100644
index 0000000..a29d4ad
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_iw.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="iw">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ja.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ja.xtb
new file mode 100644
index 0000000..d8a3543
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ja.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ja">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ka.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ka.xtb
new file mode 100644
index 0000000..b5877bc
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ka.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ka">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kk.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kk.xtb
new file mode 100644
index 0000000..94816dea
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="kk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_km.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_km.xtb
new file mode 100644
index 0000000..6a62979
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_km.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="km">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kn.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kn.xtb
new file mode 100644
index 0000000..4ecb12ba
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_kn.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="kn">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ko.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ko.xtb
new file mode 100644
index 0000000..558b05b
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ko.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ko">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ky.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ky.xtb
new file mode 100644
index 0000000..6dae058
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ky.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ky">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lo.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lo.xtb
new file mode 100644
index 0000000..27449193
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lo.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lo">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lt.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lt.xtb
new file mode 100644
index 0000000..f20c0fa2
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lt.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lt">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lv.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lv.xtb
new file mode 100644
index 0000000..6f3afbc
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_lv.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lv">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mk.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mk.xtb
new file mode 100644
index 0000000..02ed730
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="mk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ml.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ml.xtb
new file mode 100644
index 0000000..e01197e
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ml.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ml">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mn.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mn.xtb
new file mode 100644
index 0000000..0713767
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mn.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="mn">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mr.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mr.xtb
new file mode 100644
index 0000000..b137924e
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_mr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="mr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ms.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ms.xtb
new file mode 100644
index 0000000..518685dd
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ms.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ms">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_my.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_my.xtb
new file mode 100644
index 0000000..60d303e4
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_my.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="my">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ne.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ne.xtb
new file mode 100644
index 0000000..66f9f15
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ne.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ne">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_nl.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_nl.xtb
new file mode 100644
index 0000000..05ab957
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_nl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="nl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_no.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_no.xtb
new file mode 100644
index 0000000..ede4de30
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_no.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="no">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_or.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_or.xtb
new file mode 100644
index 0000000..27b3d81c
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_or.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="or">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pa.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pa.xtb
new file mode 100644
index 0000000..389088af
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pa.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pa">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pl.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pl.xtb
new file mode 100644
index 0000000..1bf17bd5
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-BR.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-BR.xtb
new file mode 100644
index 0000000..de39dfa
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-BR.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-BR">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-PT.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-PT.xtb
new file mode 100644
index 0000000..0b98ee77
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_pt-PT.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-PT">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ro.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ro.xtb
new file mode 100644
index 0000000..7129eb4
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ro.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ro">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ru.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ru.xtb
new file mode 100644
index 0000000..6dfaa442
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ru.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ru">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_si.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_si.xtb
new file mode 100644
index 0000000..cc50fd5
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_si.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="si">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sk.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sk.xtb
new file mode 100644
index 0000000..202e515a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sl.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sl.xtb
new file mode 100644
index 0000000..31b5a1a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sl.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sl">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sq.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sq.xtb
new file mode 100644
index 0000000..a954869
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sq.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sq">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr-Latn.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr-Latn.xtb
new file mode 100644
index 0000000..c205597
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr-Latn.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sr-Latn">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr.xtb
new file mode 100644
index 0000000..984d7192
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sv.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sv.xtb
new file mode 100644
index 0000000..9a787b8
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sv.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sv">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sw.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sw.xtb
new file mode 100644
index 0000000..9aa61cb
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_sw.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sw">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ta.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ta.xtb
new file mode 100644
index 0000000..c983c75f2
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ta.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ta">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_te.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_te.xtb
new file mode 100644
index 0000000..7affb9a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_te.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="te">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_th.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_th.xtb
new file mode 100644
index 0000000..dbe6a601
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_th.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="th">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_tr.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_tr.xtb
new file mode 100644
index 0000000..d99480c0
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_tr.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="tr">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uk.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uk.xtb
new file mode 100644
index 0000000..6e80099d
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uk.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="uk">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ur.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ur.xtb
new file mode 100644
index 0000000..624b043
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_ur.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ur">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uz.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uz.xtb
new file mode 100644
index 0000000..63653888
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_uz.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="uz">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_vi.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_vi.xtb
new file mode 100644
index 0000000..8a42ab1
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_vi.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="vi">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-CN.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-CN.xtb
new file mode 100644
index 0000000..c7d76e8
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-CN.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-CN">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-HK.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-HK.xtb
new file mode 100644
index 0000000..b78b9774
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-HK.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-HK">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-TW.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-TW.xtb
new file mode 100644
index 0000000..3e0c306
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zh-TW.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-TW">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zu.xtb b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zu.xtb
new file mode 100644
index 0000000..be432e9a
--- /dev/null
+++ b/chrome/browser/password_check/android/internal/java/strings/translations/android_password_check_strings_zu.xtb
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zu">
+</translationbundle>
\ No newline at end of file
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java
index ff783aa..3d63888 100644
--- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java
+++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java
@@ -8,6 +8,7 @@
 import android.os.Bundle;
 import android.view.MenuItem;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceFragmentCompat;
 
@@ -35,6 +36,11 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         getActivity().setTitle(R.string.passwords_check_title);
         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getStyledContext()));
+    }
+
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
         mComponentDelegate = sComponentFactory.create(this);
     }
 
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
index 72c2e06..80178b18 100644
--- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
+++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
@@ -5,16 +5,20 @@
 package org.chromium.chrome.browser.password_check;
 
 import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 
 import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.CompromisedCredentialProperties.COMPROMISED_CREDENTIAL;
 import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS;
 import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS;
-import static org.chromium.components.embedder_support.util.UrlUtilities.stripScheme;
 import static org.chromium.content_public.browser.test.util.CriteriaHelper.pollUiThread;
 
+import android.view.View;
+import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.annotation.IdRes;
+import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.filters.MediumTest;
 
 import org.junit.Before;
@@ -27,12 +31,14 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties;
+import org.chromium.chrome.browser.password_check.internal.R;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.modelutil.MVCListAdapter;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.widget.ButtonCompat;
 
 /**
  * View tests for the Password Check component ensure model changes are reflected in the check UI.
@@ -41,7 +47,11 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PasswordCheckViewTest {
     private static final CompromisedCredential ANA =
-            new CompromisedCredential("https://some-url.com", "Ana", "password", false);
+            new CompromisedCredential("some-url.com", "Ana", "password", false);
+    private static final CompromisedCredential PHISHED =
+            new CompromisedCredential("example.com", "Baub", "DoSomething", true);
+    private static final CompromisedCredential LEAKED =
+            new CompromisedCredential("some-other-url.com", "AZiegler", "N0M3rcy", false);
 
     private PropertyModel mModel = PasswordCheckProperties.createDefaultModel();
     private PasswordCheckFragmentView mPasswordCheckView;
@@ -76,10 +86,40 @@
                                     .build()));
             mModel.get(ITEMS).add(buildCredentialItem(ANA));
         });
-        pollUiThread(
-                () -> Criteria.checkThat(mPasswordCheckView.getListView().getChildCount(), is(2)));
-        TextView entry = (TextView) mPasswordCheckView.getListView().getChildAt(1);
-        assertThat(entry.getText(), is(stripScheme(ANA.getOriginUrl())));
+        pollUiThread(() -> Criteria.checkThat(getCredentials().getChildCount(), is(2)));
+        // Has a change passwords button.
+        assertNotNull(getCredentialChangeButtonAt(1));
+        assertThat(getCredentialChangeButtonAt(1).getVisibility(), is(View.VISIBLE));
+        assertThat(getCredentialChangeButtonAt(1).getText(),
+                is(getString(R.string.password_check_credential_row_change_button_caption)));
+
+        // Has a more button.
+        assertNotNull(getCredentialMoreButtonAt(1));
+        assertThat(getCredentialMoreButtonAt(1).getVisibility(), is(View.VISIBLE));
+        assertThat(getCredentialMoreButtonAt(1).getContentDescription(),
+                is(getString(org.chromium.chrome.R.string.more)));
+    }
+
+    @Test
+    @MediumTest
+    public void testCrendentialDisplaysNameOriginAndReason() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mModel.get(ITEMS).add(buildCredentialItem(PHISHED));
+            mModel.get(ITEMS).add(buildCredentialItem(LEAKED));
+        });
+        pollUiThread(() -> Criteria.checkThat(getCredentials().getChildCount(), is(2)));
+
+        // The phished credential is rendered first:
+        assertThat(getCredentialOriginAt(0).getText(), is(PHISHED.getOriginUrl()));
+        assertThat(getCredentialUserAt(0).getText(), is(PHISHED.getUsername()));
+        assertThat(getCredentialReasonAt(0).getText(),
+                is(getString(R.string.password_check_credential_row_reason_phished)));
+
+        // The leaked credential is rendered second:
+        assertThat(getCredentialOriginAt(1).getText(), is(LEAKED.getOriginUrl()));
+        assertThat(getCredentialUserAt(1).getText(), is(LEAKED.getUsername()));
+        assertThat(getCredentialReasonAt(1).getText(),
+                is(getString(R.string.password_check_credential_row_reason_leaked)));
     }
 
     private static MVCListAdapter.ListItem buildCredentialItem(CompromisedCredential credential) {
@@ -89,4 +129,32 @@
                         .with(COMPROMISED_CREDENTIAL, credential)
                         .build());
     }
+
+    private RecyclerView getCredentials() {
+        return mPasswordCheckView.getListView();
+    }
+
+    private TextView getCredentialOriginAt(int index) {
+        return getCredentials().getChildAt(index).findViewById(R.id.credential_origin);
+    }
+
+    private TextView getCredentialUserAt(int index) {
+        return getCredentials().getChildAt(index).findViewById(R.id.compromised_username);
+    }
+
+    private TextView getCredentialReasonAt(int index) {
+        return getCredentials().getChildAt(index).findViewById(R.id.compromised_reason);
+    }
+
+    private ButtonCompat getCredentialChangeButtonAt(int index) {
+        return getCredentials().getChildAt(index).findViewById(R.id.credential_change_button);
+    }
+
+    private ImageView getCredentialMoreButtonAt(int index) {
+        return getCredentials().getChildAt(index).findViewById(R.id.credential_menu_button);
+    }
+
+    private String getString(@IdRes int stringResource) {
+        return mTestRule.getActivity().getString(stringResource);
+    }
 }
diff --git a/chrome/browser/password_manager/android/auto_signin_first_run_dialog_android.cc b/chrome/browser/password_manager/android/auto_signin_first_run_dialog_android.cc
index b744a45..224de7b 100644
--- a/chrome/browser/password_manager/android/auto_signin_first_run_dialog_android.cc
+++ b/chrome/browser/password_manager/android/auto_signin_first_run_dialog_android.cc
@@ -42,15 +42,17 @@
 AutoSigninFirstRunDialogAndroid::~AutoSigninFirstRunDialogAndroid() {}
 
 void AutoSigninFirstRunDialogAndroid::ShowDialog() {
+  gfx::NativeWindow native_window = web_contents_->GetTopLevelNativeWindow();
+  if (!native_window) {
+    return;
+  }
+
   JNIEnv* env = AttachCurrentThread();
   Profile* profile =
       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
-
   base::string16 explanation = l10n_util::GetStringFUTF16(
       IDS_AUTO_SIGNIN_FIRST_RUN_TEXT,
       l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_TITLE_BRAND));
-  gfx::NativeWindow native_window = web_contents_->GetTopLevelNativeWindow();
-  base::android::ScopedJavaGlobalRef<jobject> java_dialog_global;
   base::string16 message = l10n_util::GetStringUTF16(
       IsSyncingAutosignSetting(profile)
           ? IDS_AUTO_SIGNIN_FIRST_RUN_TITLE_MANY_DEVICES
@@ -59,12 +61,16 @@
       l10n_util::GetStringUTF16(IDS_AUTO_SIGNIN_FIRST_RUN_OK);
   base::string16 turn_off_button_text = l10n_util::GetStringUTF16(IDS_TURN_OFF);
 
-  dialog_jobject_.Reset(Java_AutoSigninFirstRunDialog_createAndShowDialog(
-      env, native_window->GetJavaObject(), reinterpret_cast<intptr_t>(this),
-      base::android::ConvertUTF16ToJavaString(env, message),
-      base::android::ConvertUTF16ToJavaString(env, explanation), 0, 0,
-      base::android::ConvertUTF16ToJavaString(env, ok_button_text),
-      base::android::ConvertUTF16ToJavaString(env, turn_off_button_text)));
+  base::android::ScopedJavaLocalRef<jobject> java_dialog =
+      native_window->GetJavaObject();
+  if (java_dialog) {
+    dialog_jobject_.Reset(Java_AutoSigninFirstRunDialog_createAndShowDialog(
+        env, java_dialog, reinterpret_cast<intptr_t>(this),
+        base::android::ConvertUTF16ToJavaString(env, message),
+        base::android::ConvertUTF16ToJavaString(env, explanation), 0, 0,
+        base::android::ConvertUTF16ToJavaString(env, ok_button_text),
+        base::android::ConvertUTF16ToJavaString(env, turn_off_button_text)));
+  }
 }
 
 void AutoSigninFirstRunDialogAndroid::Destroy(JNIEnv* env, jobject obj) {
@@ -97,13 +103,15 @@
 }
 
 void AutoSigninFirstRunDialogAndroid::WebContentsDestroyed() {
-  JNIEnv* env = AttachCurrentThread();
-  Java_AutoSigninFirstRunDialog_dismissDialog(env, dialog_jobject_);
+  if (dialog_jobject_) {
+    JNIEnv* env = AttachCurrentThread();
+    Java_AutoSigninFirstRunDialog_dismissDialog(env, dialog_jobject_);
+  }
 }
 
 void AutoSigninFirstRunDialogAndroid::OnVisibilityChanged(
     content::Visibility visibility) {
-  if (visibility == content::Visibility::HIDDEN) {
+  if (dialog_jobject_ && visibility == content::Visibility::HIDDEN) {
     // TODO(https://crbug.com/610700): once bug is fixed, this code should be
     // gone.
     JNIEnv* env = AttachCurrentThread();
diff --git a/chrome/browser/password_manager/android/password_accessory_controller_impl.cc b/chrome/browser/password_manager/android/password_accessory_controller_impl.cc
index 5318934..d224e9b 100644
--- a/chrome/browser/password_manager/android/password_accessory_controller_impl.cc
+++ b/chrome/browser/password_manager/android/password_accessory_controller_impl.cc
@@ -283,6 +283,8 @@
 
   if (base::FeatureList::IsEnabled(
           password_manager::features::kRecoverFromNeverSaveAndroid) &&
+      base::FeatureList::IsEnabled(
+          autofill::features::kAutofillKeyboardAccessory) &&
       is_password_field &&
       password_client_->IsSavingAndFillingEnabled(origin.GetURL())) {
     BlacklistedStatus blacklisted_status =
diff --git a/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc b/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc
index 3cddf44..9511557 100644
--- a/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc
+++ b/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc
@@ -603,8 +603,10 @@
 
 TEST_F(PasswordAccessoryControllerTest, AddsSaveToggleIfIsBlacklisted) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      password_manager::features::kRecoverFromNeverSaveAndroid);
+  scoped_feature_list.InitWithFeatures(
+      {password_manager::features::kRecoverFromNeverSaveAndroid,
+       autofill::features::kAutofillKeyboardAccessory},
+      {});
   cache()->SaveCredentialsAndBlacklistedForOrigin(
       {}, CredentialCache::IsOriginBlacklisted(true),
       url::Origin::Create(GURL(kExampleSite)));
@@ -628,8 +630,10 @@
 TEST_F(PasswordAccessoryControllerTest,
        NoSaveToggleIfIsBlacklistedAndSavingDisabled) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      password_manager::features::kRecoverFromNeverSaveAndroid);
+  scoped_feature_list.InitWithFeatures(
+      {password_manager::features::kRecoverFromNeverSaveAndroid,
+       autofill::features::kAutofillKeyboardAccessory},
+      {});
 
   // Simulate saving being disabled (e.g. being in incognito or having password
   // saving disabled from settings).
@@ -653,8 +657,10 @@
 
 TEST_F(PasswordAccessoryControllerTest, AddsSaveToggleIfWasBlacklisted) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      password_manager::features::kRecoverFromNeverSaveAndroid);
+  scoped_feature_list.InitWithFeatures(
+      {password_manager::features::kRecoverFromNeverSaveAndroid,
+       autofill::features::kAutofillKeyboardAccessory},
+      {});
   cache()->SaveCredentialsAndBlacklistedForOrigin(
       {}, CredentialCache::IsOriginBlacklisted(true),
       url::Origin::Create(GURL(kExampleSite)));
@@ -682,8 +688,10 @@
 TEST_F(PasswordAccessoryControllerTest,
        RecordsAccessoryImpressionsForBlacklisted) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      password_manager::features::kRecoverFromNeverSaveAndroid);
+  scoped_feature_list.InitWithFeatures(
+      {password_manager::features::kRecoverFromNeverSaveAndroid,
+       autofill::features::kAutofillKeyboardAccessory},
+      {});
 
   base::HistogramTester histogram_tester;
 
@@ -704,9 +712,10 @@
 
 TEST_F(PasswordAccessoryControllerTest, NoAccessoryImpressionsIfUnblacklisted) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      password_manager::features::kRecoverFromNeverSaveAndroid);
-
+  scoped_feature_list.InitWithFeatures(
+      {password_manager::features::kRecoverFromNeverSaveAndroid,
+       autofill::features::kAutofillKeyboardAccessory},
+      {});
   base::HistogramTester histogram_tester;
 
   cache()->SaveCredentialsAndBlacklistedForOrigin(
diff --git a/chrome/browser/password_manager/change_password_url_service_factory.cc b/chrome/browser/password_manager/change_password_url_service_factory.cc
new file mode 100644
index 0000000..0c59d18
--- /dev/null
+++ b/chrome/browser/password_manager/change_password_url_service_factory.cc
@@ -0,0 +1,40 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/password_manager/change_password_url_service_factory.h"
+
+#include "base/no_destructor.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/password_manager/core/browser/change_password_url_service_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+
+ChangePasswordUrlServiceFactory::ChangePasswordUrlServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "ChangePasswordUrlService",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+ChangePasswordUrlServiceFactory::~ChangePasswordUrlServiceFactory() = default;
+
+// static
+ChangePasswordUrlServiceFactory*
+ChangePasswordUrlServiceFactory::GetInstance() {
+  static base::NoDestructor<ChangePasswordUrlServiceFactory> instance;
+  return instance.get();
+}
+
+// static
+password_manager::ChangePasswordUrlService*
+ChangePasswordUrlServiceFactory::GetForBrowserContext(
+    content::BrowserContext* browser_context) {
+  return static_cast<password_manager::ChangePasswordUrlService*>(
+      GetInstance()->GetServiceForBrowserContext(browser_context, true));
+}
+
+KeyedService* ChangePasswordUrlServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  return new password_manager::ChangePasswordUrlServiceImpl(
+      content::BrowserContext::GetDefaultStoragePartition(context)
+          ->GetURLLoaderFactoryForBrowserProcess());
+}
diff --git a/chrome/browser/password_manager/change_password_url_service_factory.h b/chrome/browser/password_manager/change_password_url_service_factory.h
new file mode 100644
index 0000000..460ad3c
--- /dev/null
+++ b/chrome/browser/password_manager/change_password_url_service_factory.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PASSWORD_MANAGER_CHANGE_PASSWORD_URL_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_CHANGE_PASSWORD_URL_SERVICE_FACTORY_H_
+
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+namespace password_manager {
+class ChangePasswordUrlService;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+// Creates instances of ChangePasswordUrl per BrowserContext.
+class ChangePasswordUrlServiceFactory
+    : public BrowserContextKeyedServiceFactory {
+ public:
+  ChangePasswordUrlServiceFactory();
+  ~ChangePasswordUrlServiceFactory() override;
+
+  static ChangePasswordUrlServiceFactory* GetInstance();
+  static password_manager::ChangePasswordUrlService* GetForBrowserContext(
+      content::BrowserContext* browser_context);
+
+ private:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+};
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_CHANGE_PASSWORD_URL_SERVICE_FACTORY_H_
diff --git a/chrome/browser/policy/chrome_browser_cloud_management_controller.cc b/chrome/browser/policy/chrome_browser_cloud_management_controller.cc
index 9053f09..c0e5c8a7 100644
--- a/chrome/browser/policy/chrome_browser_cloud_management_controller.cc
+++ b/chrome/browser/policy/chrome_browser_cloud_management_controller.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/device_identity/device_identity_provider.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
-#include "chrome/browser/enterprise/reporting/report_generator.h"
 #include "chrome/browser/enterprise/reporting/report_scheduler.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/net/system_network_context_manager.h"
@@ -36,6 +35,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/enterprise/browser/controller/browser_dm_token_storage.h"
 #include "components/enterprise/browser/controller/chrome_browser_cloud_management_helper.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 #include "components/gcm_driver/instance_id/instance_id_driver.h"
 #include "components/invalidation/impl/fcm_invalidation_service.h"
 #include "components/invalidation/impl/fcm_network_handler.h"
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 5d115c6..cb86739 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -39,7 +39,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/statistics_recorder.h"
@@ -52,6 +51,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/chrome/browser/policy/policy_test_utils.cc b/chrome/browser/policy/policy_test_utils.cc
index ef22665..f904d23 100644
--- a/chrome/browser/policy/policy_test_utils.cc
+++ b/chrome/browser/policy/policy_test_utils.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/policy/policy_test_utils.h"
 
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
@@ -189,7 +189,7 @@
   SetEnterpriseUsersDefaults(&policy_with_defaults);
 #endif
   provider_.UpdateChromePolicy(policy_with_defaults);
-  DCHECK(base::MessageLoopCurrent::Get());
+  DCHECK(base::CurrentThread::Get());
   base::RunLoop loop;
   loop.RunUntilIdle();
 }
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 8a743d0..37bdfd9 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -13,10 +13,10 @@
 #include "base/location.h"
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc
index 688c3d67..87d60fa 100644
--- a/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_stats_collector_unittest.cc
@@ -10,8 +10,8 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/metrics_hashes.h"
+#include "base/task/current_thread.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
@@ -55,7 +55,7 @@
             std::make_unique<base::TestMockTimeTaskRunner::ScopedContext>(
                 task_runner_)),
         scoped_set_tick_clock_for_testing_(task_runner_->GetMockTickClock()) {
-    base::MessageLoopCurrent::Get()->SetTaskRunner(task_runner_);
+    base::CurrentThread::Get()->SetTaskRunner(task_runner_);
 
     // Start with a non-zero time.
     task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(42));
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
index b3de446..7a7ca82b 100644
--- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -14,10 +14,10 @@
 #include "base/check.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/notreached.h"
 #include "base/strings/string16.h"
+#include "base/task/current_thread.h"
 #include "base/test/mock_entropy_provider.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
@@ -117,7 +117,7 @@
             std::make_unique<base::TestMockTimeTaskRunner::ScopedContext>(
                 task_runner_)),
         scoped_set_tick_clock_for_testing_(task_runner_->GetMockTickClock()) {
-    base::MessageLoopCurrent::Get()->SetTaskRunner(task_runner_);
+    base::CurrentThread::Get()->SetTaskRunner(task_runner_);
 
     // Start with a non-zero time.
     task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(42));
diff --git a/chrome/browser/resources/nearby_share/BUILD.gn b/chrome/browser/resources/nearby_share/BUILD.gn
index 016739d..7b20767 100644
--- a/chrome/browser/resources/nearby_share/BUILD.gn
+++ b/chrome/browser/resources/nearby_share/BUILD.gn
@@ -39,6 +39,7 @@
 
 js_library("nearby_device") {
   deps = [
+    "//third_party/polymer/v3_0/components-chromium/iron-icon",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
 }
diff --git a/chrome/browser/resources/nearby_share/nearby_device.html b/chrome/browser/resources/nearby_share/nearby_device.html
index ea3a426..a152f128 100644
--- a/chrome/browser/resources/nearby_share/nearby_device.html
+++ b/chrome/browser/resources/nearby_share/nearby_device.html
@@ -6,7 +6,28 @@
     box-sizing: border-box;
     display: flex;
     height: 40px;
-    margin-top: 6px;
+    margin-block-end: 6px;
+    padding-block-end: 6px;
+    padding-block-start: 6px;
+    padding-inline-end: 9px;
+    padding-inline-start: 9px;
+  }
+
+  #icon {
+    color: rgb(26, 115, 232);
+    height: 15px;
+    width: 15px;
+  }
+
+  #icon-container {
+    align-items: center;
+    background-color: rgb(232, 240, 254);
+    border-radius: 13px;
+    display: flex;
+    flex-shrink: 0;
+    height: 26px;
+    justify-content: center;
+    width: 26px;
   }
 
   #name {
@@ -15,11 +36,13 @@
     font-size: 11px;
     font-weight: 500;
     letter-spacing: 0.3px;
+    margin-inline-start: 11px;
     overflow: hidden;
-    text-align: center;
     text-overflow: ellipsis;
     white-space: nowrap;
   }
 </style>
-
+<div id="icon-container">
+  <iron-icon id="icon" icon="nearby-share:smartphone"></iron-icon>
+</div>
 <div id="name">[[name]]</div>
diff --git a/chrome/browser/resources/nearby_share/nearby_device.js b/chrome/browser/resources/nearby_share/nearby_device.js
index 22da70a..390119c 100644
--- a/chrome/browser/resources/nearby_share/nearby_device.js
+++ b/chrome/browser/resources/nearby_share/nearby_device.js
@@ -6,6 +6,9 @@
  * @fileoverview The 'nearby-device' component shows details of a remote device.
  */
 
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import './icons.js';
+
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 Polymer({
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.html b/chrome/browser/resources/nearby_share/nearby_discovery_page.html
index 585ccbd..4e3f0e7 100644
--- a/chrome/browser/resources/nearby_share/nearby_discovery_page.html
+++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.html
@@ -1,39 +1,61 @@
 <style>
+  :host {
+    --nearby-page-space-block: 26px;
+    --nearby-page-space-inline: 32px;
+    --nearby-page-space-large-inline: 42px;
+  }
+
   #actions {
-    margin-top: 17px;
+    margin-block-end: var(--nearby-page-space-block);
+    margin-block-start: 17px;
+    margin-inline-end:  var(--nearby-page-space-inline);
+    margin-inline-start: var(--nearby-page-space-inline);
     text-align: end;
   }
 
+  #center-content {
+    background: radial-gradient(160% 50% at 0 100%, rgba(138, 180, 248, 0.25),
+        rgba(255, 255, 255, 0));
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+    flex-grow: 1;
+    overflow: hidden;
+  }
+
   #device-list {
     overflow: auto;
+    padding-inline-end:  var(--nearby-page-space-large-inline);
+    padding-inline-start:  var(--nearby-page-space-large-inline);
     width: 191px;
   }
 
   nearby-preview {
-    margin-inline-end: 10px;
-    margin-inline-start: 10px;
+    margin-inline-end:  var(--nearby-page-space-large-inline);
+    margin-inline-start:  var(--nearby-page-space-large-inline);
   }
 
   #help {
     color: rgb(95, 99, 104);
     font-size: 9px;
     line-height: 12px;
-    margin: 12px auto;
+    margin-block-end: 12px;
+    margin-block-start: 12px;
+    margin-inline-end:  var(--nearby-page-space-inline);
+    margin-inline-start: var(--nearby-page-space-inline);
   }
 
   #page-content {
-    box-sizing: border-box;
     display: flex;
     flex-direction: column;
     height: 100%;
-    padding: 27px 32px 25px 37px;
   }
 
   #process-row {
     display: flex;
     flex-grow: 1;
     justify-content: space-between;
-    margin-top: 48px;
+    margin-block-start: 48px;
     overflow: hidden;
   }
 
@@ -42,7 +64,10 @@
     font-size: 100%;
     font-weight: normal;
     line-height: 154%;
-    margin: 0;
+    margin-block-end: 0;
+    margin-block-start: 0;
+    margin-inline-end:  var(--nearby-page-space-inline);
+    margin-inline-start: var(--nearby-page-space-inline);
   }
 
   #title {
@@ -51,7 +76,10 @@
     font-weight: normal;
     letter-spacing: 0.27px;
     line-height: 150%;
-    margin: 0;
+    margin-block-end: 0;
+    margin-block-start: var(--nearby-page-space-block);
+    margin-inline-end:  var(--nearby-page-space-inline);
+    margin-inline-start: var(--nearby-page-space-inline);
   }
 </style>
 
@@ -59,29 +87,23 @@
   <h1 id="title">Nearby Share</h1>
   <h2 id="subtitle">Select people you would like to share with</h2>
 
-  <div id="process-row">
-    <nearby-preview title="Doggo.jpg"></nearby-preview>
-    <div id="device-list">
-      <nearby-device name="Alyssa's Pixel"></nearby-device>
-      <nearby-device name="Shangela's Pixel 2XL Name Is Looong"></nearby-device>
-      <nearby-device name="MirasChromebookIsAllInOneWord"></nearby-device>
-      <nearby-device name="One"></nearby-device>
-      <nearby-device name="Two"></nearby-device>
-      <nearby-device name="Three"></nearby-device>
-      <nearby-device name="Four"></nearby-device>
-      <nearby-device name="Five"></nearby-device>
-      <nearby-device name="Six"></nearby-device>
-      <nearby-device name="Seven"></nearby-device>
-      <nearby-device name="Eight"></nearby-device>
-      <nearby-device name="Nine"></nearby-device>
-      <nearby-device name="Ten"></nearby-device>
-    </div>
-  </div>
+  <div id="center-content">
 
-  <div id="help">
-    Make sure both devices are unlocked, close together (within 1 ft), and have
-    Bluetooth turned on. If you’re sharing with a Chromebook make sure Nearby
-    Share is turned on from quick settings.
+    <div id="process-row">
+      <nearby-preview title="Doggo.jpg"></nearby-preview>
+      <div id="device-list">
+        <nearby-device name="Alyssa's Pixel"></nearby-device>
+        <nearby-device name="Shangela's Pixel 2XL"></nearby-device>
+        <nearby-device name="Mira's Chromebook"></nearby-device>
+      </div>
+    </div>
+
+    <div id="help">
+      Make sure both devices are unlocked, close together (within 1 ft), and
+      have Bluetooth turned on. If you’re sharing with a Chromebook make sure
+      Nearby Share is turned on from quick settings.
+    </div>
+
   </div>
 
   <div id="actions">
diff --git a/chrome/browser/resources/signin/BUILD.gn b/chrome/browser/resources/signin/BUILD.gn
index f3e1f7e..b5724b7 100644
--- a/chrome/browser/resources/signin/BUILD.gn
+++ b/chrome/browser/resources/signin/BUILD.gn
@@ -8,6 +8,7 @@
   deps = [ "sync_confirmation:closure_compile" ]
   if (!is_chromeos) {
     deps += [
+      "dice_web_signin_intercept:closure_compile",
       "profile_picker:closure_compile",
       "signin_email_confirmation:closure_compile",
       "signin_error:closure_compile",
@@ -23,6 +24,7 @@
   ]
   if (!is_chromeos) {
     public_deps += [
+      "dice_web_signin_intercept:web_components",
       "signin_email_confirmation:web_components",
       "signin_error:web_components",
       "signin_reauth:web_components",
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/BUILD.gn b/chrome/browser/resources/signin/dice_web_signin_intercept/BUILD.gn
new file mode 100644
index 0000000..0a0cd742
--- /dev/null
+++ b/chrome/browser/resources/signin/dice_web_signin_intercept/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  deps = [
+    ":dice_web_signin_intercept_app",
+    ":dice_web_signin_intercept_browser_proxy",
+  ]
+}
+
+js_library("dice_web_signin_intercept_app") {
+  deps = [
+    ":dice_web_signin_intercept_browser_proxy",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+js_library("dice_web_signin_intercept_browser_proxy") {
+  deps = [ "//ui/webui/resources/js:cr.m" ]
+  externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "dice_web_signin_intercept_app.js" ]
+}
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept.html b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept.html
index 8ddf6a3..b9a1ff69 100644
--- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept.html
+++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept.html
@@ -4,5 +4,7 @@
     <meta charset="utf-8">
   </head>
   <body>
+    <dice-web-signin-intercept-app></dice-web-signin-intercept-app>
+    <script type="module" src="dice_web_signin_intercept_app.js"></script>
   </body>
 </html>
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html
new file mode 100644
index 0000000..95dfaa3c
--- /dev/null
+++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html
@@ -0,0 +1,13 @@
+<div>
+  <h1>$i18n{diceWebSigninInterceptTitle}</h1>
+  <div>$i18n{diceWebSigninInterceptDesc}</div>
+</div>
+<div>
+  <cr-button id="cancelButton" on-click="onCancel_">
+    $i18n{diceWebSigninInterceptCancelLabel}
+  </cr-button>
+  <cr-button id="acceptButton" class="action-button" on-click="onAccept_"
+      autofocus>
+    $i18n{diceWebSigninInterceptAcceptLabel}
+  </cr-button>
+</div>
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js
new file mode 100644
index 0000000..aa425c84
--- /dev/null
+++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js
@@ -0,0 +1,35 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import './strings.m.js';
+
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {DiceWebSigninInterceptBrowserProxy, DiceWebSigninInterceptBrowserProxyImpl} from './dice_web_signin_intercept_browser_proxy.js';
+
+Polymer({
+  is: 'dice-web-signin-intercept-app',
+
+  _template: html`{__html_template__}`,
+
+  /** @private {?DiceWebSigninInterceptBrowserProxy} */
+  diceWebSigninInterceptBrowserProxy_: null,
+
+  /** @override */
+  attached() {
+    this.diceWebSigninInterceptBrowserProxy_ =
+        DiceWebSigninInterceptBrowserProxyImpl.getInstance();
+  },
+
+  /** @private */
+  onAccept_() {
+    this.diceWebSigninInterceptBrowserProxy_.accept();
+  },
+
+  /** @private */
+  onCancel_() {
+    this.diceWebSigninInterceptBrowserProxy_.cancel();
+  },
+});
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js
new file mode 100644
index 0000000..be3525d
--- /dev/null
+++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used by the dice web signin intercept bubble to
+ * interact with the browser.
+ */
+import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
+
+/** @interface */
+export class DiceWebSigninInterceptBrowserProxy {
+  /** Called when the user accepts the interception bubble. */
+  accept() {}
+
+  /** Called when the user cancels the interception. */
+  cancel() {}
+}
+
+/** @implements {DiceWebSigninInterceptBrowserProxy} */
+export class DiceWebSigninInterceptBrowserProxyImpl {
+  /** @override */
+  accept() {
+    chrome.send('accept');
+  }
+
+  /** @override */
+  cancel() {
+    chrome.send('cancel');
+  }
+}
+
+addSingletonGetter(DiceWebSigninInterceptBrowserProxyImpl);
diff --git a/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chrome/browser/resources/signin/profile_picker/BUILD.gn
index 7d75746..20917e62 100644
--- a/chrome/browser/resources/signin/profile_picker/BUILD.gn
+++ b/chrome/browser/resources/signin/profile_picker/BUILD.gn
@@ -5,8 +5,20 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
 
-js_type_check("closure_compile") {
+group("closure_compile") {
+  deps = [
+    ":profile_picker_files",
+    "profile_creation_flow:closure_compile",
+  ]
+}
+
+js_type_check("profile_picker_files") {
   is_polymer3 = true
+  closure_flags =
+      default_closure_args + [
+        "js_module_root=../../chrome/browser/resources/signin/profile_picker/",
+        "js_module_root=./gen/chrome/browser/resources/signin/profile_picker/",
+      ]
   deps = [
     ":profile_picker_app",
     ":profile_picker_main_view",
@@ -45,7 +57,14 @@
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
-html_to_js("web_components") {
+group("web_components") {
+  public_deps = [
+    ":web_components_local",
+    "profile_creation_flow:web_components",
+  ]
+}
+
+html_to_js("web_components_local") {
   js_files = [
     "profile_picker_app.js",
     "profile_picker_main_view.js",
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
new file mode 100644
index 0000000..7fac0693
--- /dev/null
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  deps = [ ":profile_type_choice" ]
+}
+
+js_library("profile_type_choice") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "profile_type_choice.js" ]
+}
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
new file mode 100644
index 0000000..3560311
--- /dev/null
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
@@ -0,0 +1 @@
+<div> Profile type choice </div>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
index 9c06b6719..9785b6b8 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js
@@ -7,5 +7,5 @@
 Polymer({
   is: 'profile-type-choice',
 
-  _template: html`<div> Profile type choice </div>`,
+  _template: html`{__html_template__}`,
 });
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd
index a8e1f0d5..194e84cc 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd
+++ b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd
@@ -28,6 +28,9 @@
       <include name="IDR_PROFILE_PICKER_PROFILE_CARD_JS"
                file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/profile_card.js"
                use_base_dir="false" type="BINDATA" preprocess="true"/>
+      <include name="IDR_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_JS"
+               file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.js"
+               use_base_dir="false" type="BINDATA"/>
     </includes>
     <structures>
       <structure
@@ -56,11 +59,6 @@
           type="chrome_html"
           compress="false"/>
       <structure
-          name="IDR_PROFILE_PICKER_PROFILE_TYPE_INPUT_JS"
-          file="profile_creation_flow/profile_type_choice.js"
-          type="chrome_html"
-          compress="false"/>
-      <structure
           name="IDR_PROFILE_PICKER_MANAGE_PROFILES_BROWSER_PROXY_JS"
           file="manage_profiles_browser_proxy.js"
           type="chrome_html"
diff --git a/chrome/browser/sharing/webrtc/ice_config_fetcher.cc b/chrome/browser/sharing/webrtc/ice_config_fetcher.cc
index 6dee784..58f10400 100644
--- a/chrome/browser/sharing/webrtc/ice_config_fetcher.cc
+++ b/chrome/browser/sharing/webrtc/ice_config_fetcher.cc
@@ -68,7 +68,7 @@
 
 IceConfigFetcher::~IceConfigFetcher() = default;
 
-void IceConfigFetcher::GetIceServers(IceServerCallback callback) {
+void IceConfigFetcher::GetIceServers(GetIceServersCallback callback) {
   url_loader_.reset();
 
   auto resource_request = std::make_unique<network::ResourceRequest>();
@@ -91,7 +91,7 @@
 }
 
 void IceConfigFetcher::OnIceServersResponse(
-    IceServerCallback callback,
+    GetIceServersCallback callback,
     std::unique_ptr<std::string> response_body) {
   std::vector<sharing::mojom::IceServerPtr> ice_servers;
 
diff --git a/chrome/browser/sharing/webrtc/ice_config_fetcher.h b/chrome/browser/sharing/webrtc/ice_config_fetcher.h
index 630cca19..859bafe 100644
--- a/chrome/browser/sharing/webrtc/ice_config_fetcher.h
+++ b/chrome/browser/sharing/webrtc/ice_config_fetcher.h
@@ -21,23 +21,20 @@
 class SimpleURLLoader;
 }  // namespace network
 
-class IceConfigFetcher {
+class IceConfigFetcher : public sharing::mojom::IceConfigFetcher {
  public:
-  using IceServerCallback =
-      base::OnceCallback<void(std::vector<sharing::mojom::IceServerPtr>)>;
-
   explicit IceConfigFetcher(
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-  ~IceConfigFetcher();
+  ~IceConfigFetcher() override;
 
   IceConfigFetcher(const IceConfigFetcher& other) = delete;
   IceConfigFetcher& operator=(const IceConfigFetcher& other) = delete;
 
   // TODO(himanshujaju) - Cache configs fetched from server.
-  void GetIceServers(IceServerCallback callback);
+  void GetIceServers(GetIceServersCallback callback) override;
 
  private:
-  void OnIceServersResponse(IceServerCallback callback,
+  void OnIceServersResponse(GetIceServersCallback callback,
                             std::unique_ptr<std::string> response_body);
 
   std::vector<sharing::mojom::IceServerPtr> ParseIceConfigJson(
diff --git a/chrome/browser/ssl/ocsp_browsertest.cc b/chrome/browser/ssl/ocsp_browsertest.cc
index 6ec682f..a8d68eb 100644
--- a/chrome/browser/ssl/ocsp_browsertest.cc
+++ b/chrome/browser/ssl/ocsp_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include <memory>
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/system_network_context_manager.h"
@@ -194,7 +194,7 @@
  private:
   void UpdateChromePolicy(const policy::PolicyMap& policies) {
     policy_provider_.UpdateChromePolicy(policies);
-    ASSERT_TRUE(base::MessageLoopCurrent::Get());
+    ASSERT_TRUE(base::CurrentThread::Get());
 
     base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 84f6820d..ebb8d03 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -15,7 +15,6 @@
 #include "base/json/json_reader.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -26,6 +25,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_command_line.h"
@@ -838,7 +838,7 @@
 
   void UpdateChromePolicy(const policy::PolicyMap& policies) {
     policy_provider_.UpdateChromePolicy(policies);
-    ASSERT_TRUE(base::MessageLoopCurrent::Get());
+    ASSERT_TRUE(base::CurrentThread::Get());
 
     base::RunLoop().RunUntilIdle();
 
@@ -1691,7 +1691,7 @@
  private:
   void UpdateChromePolicy(const policy::PolicyMap& policies) {
     policy_provider_.UpdateChromePolicy(policies);
-    ASSERT_TRUE(base::MessageLoopCurrent::Get());
+    ASSERT_TRUE(base::CurrentThread::Get());
 
     base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
index 04004c4..d1fe511 100644
--- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
+++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.cc
@@ -59,23 +59,23 @@
 }
 
 void PerProfileWorkerTaskTracker::OnWorkerCreated(
-    const blink::mojom::DedicatedWorkerToken& worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     int worker_process_id,
     content::GlobalFrameRoutingId ancestor_render_frame_host_id) {
-  CreateWorkerTask(worker_token, Task::Type::DEDICATED_WORKER,
+  CreateWorkerTask(dedicated_worker_id, Task::Type::DEDICATED_WORKER,
                    worker_process_id, &dedicated_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnBeforeWorkerDestroyed(
-    const blink::mojom::DedicatedWorkerToken& worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     content::GlobalFrameRoutingId ancestor_render_frame_host_id) {
-  DeleteWorkerTask(worker_token, &dedicated_worker_tasks_);
+  DeleteWorkerTask(dedicated_worker_id, &dedicated_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnFinalResponseURLDetermined(
-    const blink::mojom::DedicatedWorkerToken& worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     const GURL& url) {
-  SetWorkerTaskScriptUrl(worker_token, url, &dedicated_worker_tasks_);
+  SetWorkerTaskScriptUrl(dedicated_worker_id, url, &dedicated_worker_tasks_);
 }
 
 void PerProfileWorkerTaskTracker::OnWorkerCreated(
diff --git a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
index 9e40efe..760d8b1f 100644
--- a/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
+++ b/chrome/browser/task_manager/providers/per_profile_worker_task_tracker.h
@@ -10,12 +10,12 @@
 #include "base/containers/flat_map.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/task_manager/providers/task.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/dedicated_worker_service.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/service_worker_context_observer.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "content/public/browser/shared_worker_service.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 class Profile;
 
@@ -43,14 +43,14 @@
 
   // content::DedicatedWorkerService::Observer:
   void OnWorkerCreated(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       int worker_process_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
   void OnBeforeWorkerDestroyed(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
   void OnFinalResponseURLDetermined(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       const GURL& url) override;
 
   // content::SharedWorkerService::Observer:
@@ -115,8 +115,7 @@
                  content::DedicatedWorkerService::Observer>
       scoped_dedicated_worker_service_observer_{this};
 
-  base::flat_map<blink::mojom::DedicatedWorkerToken,
-                 std::unique_ptr<WorkerTask>>
+  base::flat_map<content::DedicatedWorkerId, std::unique_ptr<WorkerTask>>
       dedicated_worker_tasks_;
 
   // For shared workers:
diff --git a/chrome/browser/touch_to_fill/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
index 66dfa82c..29c6f33 100644
--- a/chrome/browser/touch_to_fill/android/internal/BUILD.gn
+++ b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
@@ -49,7 +49,6 @@
     "java/res/drawable/touch_to_fill_header_image.xml",
     "java/res/layout/touch_to_fill_credential_item.xml",
     "java/res/layout/touch_to_fill_fill_button.xml",
-    "java/res/layout/touch_to_fill_footer.xml",
     "java/res/layout/touch_to_fill_header_item.xml",
     "java/res/layout/touch_to_fill_sheet.xml",
     "java/res/values/dimens.xml",
diff --git a/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_footer.xml b/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_footer.xml
deleted file mode 100644
index 66d35e9..0000000
--- a/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_footer.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
- <!-- Please update R.dimens.touch_to_fill_sheet_height_branding when modifying
-      the margins. -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/touch_to_fill_branding_message"
-    android:layout_height="wrap_content"
-    android:layout_marginTop="16dp"
-    android:layout_width="match_parent"
-    android:gravity="center"
-    android:minHeight="20dp"
-    android:textAppearance="@style/TextAppearance.TextMedium.Secondary" />
diff --git a/chrome/browser/touch_to_fill/android/internal/java/res/values/dimens.xml b/chrome/browser/touch_to_fill/android/internal/java/res/values/dimens.xml
index 0401cf38..4f58fbe5 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/res/values/dimens.xml
+++ b/chrome/browser/touch_to_fill/android/internal/java/res/values/dimens.xml
@@ -27,16 +27,10 @@
          + Bottom margin (2 dp) -->
     <dimen name="touch_to_fill_sheet_height_button">60dp</dimen>
 
-    <!-- Top padding between RecyclerView elements (8 dp)
-        + Top margin (16 dp)
-        + Text height (20 dp) -->
-    <dimen name="touch_to_fill_sheet_height_branding">44dp</dimen>
-
     <!-- Depending on the experiments that are active we might show a call to
          action button or branding message to the users, at which point we need
          different bottom paddings. They are exposed here, so that they can be
          added dynamically, depending on the state of the experiments. -->
     <dimen name="touch_to_fill_sheet_bottom_padding_credentials">16dp</dimen>
     <dimen name="touch_to_fill_sheet_bottom_padding_button">8dp</dimen>
-    <dimen name="touch_to_fill_sheet_bottom_padding_branding">16dp</dimen>
 </resources>
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java
index a6b9488..b2a66a9 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java
+++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java
@@ -8,9 +8,6 @@
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.FAVICON_OR_FALLBACK;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.FORMATTED_ORIGIN;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.ON_CLICK_LISTENER;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FIELD_TRIAL_PARAM_BRANDING_MESSAGE;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FIELD_TRIAL_PARAM_SHOW_CONFIRMATION_BUTTON;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FooterProperties.BRANDING_MESSAGE_ID;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.FORMATTED_URL;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.ORIGIN_SECURE;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.SINGLE_CREDENTIAL;
@@ -21,7 +18,6 @@
 import androidx.annotation.Px;
 
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.touch_to_fill.TouchToFillComponent.UserAction;
 import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties;
 import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties;
@@ -91,11 +87,6 @@
             }
         }
 
-        sheetItems.add(new ListItem(TouchToFillProperties.ItemType.FOOTER,
-                new PropertyModel.Builder(TouchToFillProperties.FooterProperties.ALL_KEYS)
-                        .with(BRANDING_MESSAGE_ID, getBrandingMessageId())
-                        .build()));
-
         mModel.set(VISIBLE, true);
     }
 
@@ -161,29 +152,7 @@
      * @return True if a confirmation button should be shown at the end of the bottom sheet.
      */
     private boolean shouldCreateConfirmationButton(List<Credential> credentials) {
-        return credentials.size() == 1
-                && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                        ChromeFeatureList.TOUCH_TO_FILL_ANDROID,
-                        FIELD_TRIAL_PARAM_SHOW_CONFIRMATION_BUTTON, false);
-    }
-
-    /**
-     * Returns the id of the branding message to be shown. Returns 0 in case no message should be
-     * displayed.
-     */
-    private int getBrandingMessageId() {
-        int id = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                ChromeFeatureList.TOUCH_TO_FILL_ANDROID, FIELD_TRIAL_PARAM_BRANDING_MESSAGE, 0);
-        switch (id) {
-            case 1:
-                return R.string.touch_to_fill_branding_variation_1;
-            case 2:
-                return R.string.touch_to_fill_branding_variation_2;
-            case 3:
-                return R.string.touch_to_fill_branding_variation_3;
-            default:
-                return 0;
-        }
+        return credentials.size() == 1;
     }
 
     private PropertyModel createModel(Credential credential) {
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java
index 597d5fc..d108533 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java
+++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java
@@ -23,9 +23,6 @@
  * Properties defined here reflect the visible state of the TouchToFill-components.
  */
 class TouchToFillProperties {
-    static final String FIELD_TRIAL_PARAM_SHOW_CONFIRMATION_BUTTON = "show_confirmation_button";
-    static final String FIELD_TRIAL_PARAM_BRANDING_MESSAGE = "branding_message";
-
     static final PropertyModel.WritableBooleanPropertyKey VISIBLE =
             new PropertyModel.WritableBooleanPropertyKey("visible");
     static final PropertyModel
@@ -98,14 +95,7 @@
         private HeaderProperties() {}
     }
 
-    static class FooterProperties {
-        static final PropertyModel.ReadableIntPropertyKey BRANDING_MESSAGE_ID =
-                new PropertyModel.ReadableIntPropertyKey("branding_message_id");
-        static final PropertyKey[] ALL_KEYS = {BRANDING_MESSAGE_ID};
-        private FooterProperties() {}
-    }
-
-    @IntDef({ItemType.HEADER, ItemType.CREDENTIAL, ItemType.FILL_BUTTON, ItemType.FOOTER})
+    @IntDef({ItemType.HEADER, ItemType.CREDENTIAL, ItemType.FILL_BUTTON})
     @Retention(RetentionPolicy.SOURCE)
     @interface ItemType {
         /**
@@ -122,11 +112,6 @@
          * The fill button at the end of the sheet that filling more obvious for one suggestion.
          */
         int FILL_BUTTON = 3;
-
-        /**
-         * The branding message at the bottom of the sheet to draw attention to the feature.
-         */
-        int FOOTER = 4;
     }
 
     /**
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java
index 7689211..36303c0 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java
+++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java
@@ -4,23 +4,18 @@
 
 package org.chromium.chrome.browser.touch_to_fill;
 
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FIELD_TRIAL_PARAM_BRANDING_MESSAGE;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FIELD_TRIAL_PARAM_SHOW_CONFIRMATION_BUTTON;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
 
-import androidx.annotation.DimenRes;
 import androidx.annotation.Nullable;
 import androidx.annotation.Px;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.base.Callback;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
@@ -203,35 +198,15 @@
         if (hasMultipleCredentials) {
             totalHeight += resources.getDimensionPixelSize(
                     R.dimen.touch_to_fill_sheet_height_second_credential);
-        }
-
-        final boolean hasButton = !hasMultipleCredentials
-                && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                        ChromeFeatureList.TOUCH_TO_FILL_ANDROID,
-                        FIELD_TRIAL_PARAM_SHOW_CONFIRMATION_BUTTON, false);
-        if (hasButton) {
+            totalHeight += resources.getDimensionPixelSize(
+                    R.dimen.touch_to_fill_sheet_bottom_padding_credentials);
+        } else {
             totalHeight +=
                     resources.getDimensionPixelSize(R.dimen.touch_to_fill_sheet_height_button);
+            totalHeight += resources.getDimensionPixelSize(
+                    R.dimen.touch_to_fill_sheet_bottom_padding_button);
         }
 
-        final boolean hasBranding = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                                            ChromeFeatureList.TOUCH_TO_FILL_ANDROID,
-                                            FIELD_TRIAL_PARAM_BRANDING_MESSAGE, 0)
-                != 0;
-        if (hasBranding) {
-            totalHeight +=
-                    resources.getDimensionPixelSize(R.dimen.touch_to_fill_sheet_height_branding);
-        }
-
-        return totalHeight + getDesiredBottomPadding(hasButton, hasBranding);
-    }
-
-    private @Px int getDesiredBottomPadding(boolean hasButton, boolean hasBranding) {
-        @DimenRes
-        int bottomPaddingId = R.dimen.touch_to_fill_sheet_bottom_padding_credentials;
-        if (hasButton) bottomPaddingId = R.dimen.touch_to_fill_sheet_bottom_padding_button;
-        if (hasBranding) bottomPaddingId = R.dimen.touch_to_fill_sheet_bottom_padding_branding;
-
-        return mContext.getResources().getDimensionPixelSize(bottomPaddingId);
+        return totalHeight;
     }
 }
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
index 460659e9..9cf1950f 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
+++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
@@ -9,7 +9,6 @@
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.FORMATTED_ORIGIN;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.ON_CLICK_LISTENER;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.DISMISS_HANDLER;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FooterProperties.BRANDING_MESSAGE_ID;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.FORMATTED_URL;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.ORIGIN_SECURE;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.SINGLE_CREDENTIAL;
@@ -18,7 +17,6 @@
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.VISIBLE;
 import static org.chromium.components.embedder_support.util.UrlUtilities.stripScheme;
 
-import android.content.Context;
 import android.text.method.PasswordTransformationMethod;
 import android.view.View;
 import android.view.ViewGroup;
@@ -89,9 +87,6 @@
             case ItemType.FILL_BUTTON:
                 return new TouchToFillViewHolder(parent, R.layout.touch_to_fill_fill_button,
                         TouchToFillViewBinder::bindFillButtonView);
-            case ItemType.FOOTER:
-                return new TouchToFillViewHolder(parent, R.layout.touch_to_fill_footer,
-                        TouchToFillViewBinder::bindFooterView);
         }
         assert false : "Cannot create view for ItemType: " + itemType;
         return null;
@@ -204,22 +199,5 @@
         }
     }
 
-    private static void bindFooterView(PropertyModel model, View view, PropertyKey key) {
-        if (key == BRANDING_MESSAGE_ID) {
-            TextView brandingMessage = view.findViewById(R.id.touch_to_fill_branding_message);
-            @StringRes
-            int messageId = model.get(BRANDING_MESSAGE_ID);
-            if (messageId == 0) {
-                brandingMessage.setVisibility(View.GONE);
-            } else {
-                Context context = view.getContext();
-                brandingMessage.setText(String.format(context.getString(messageId),
-                        context.getString(org.chromium.chrome.R.string.app_name)));
-            }
-        } else {
-            assert false : "Unhandled update to property:" + key;
-        }
-    }
-
     private TouchToFillViewBinder() {}
 }
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
index a57ab8e..25f9480 100644
--- a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
+++ b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
@@ -199,15 +199,6 @@
       <message name="IDS_TOUCH_TO_FILL_CONTINUE" desc="Title of the button that continues filling with the only available set of credentials.">
         Continue
       </message>
-      <message name="IDS_TOUCH_TO_FILL_BRANDING_VARIATION_1" desc="Message shown at the bottom of the Touch To Fill sheet to draw attention to the feature.">
-        New in <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph>! Tap to sign in
-      </message>
-      <message name="IDS_TOUCH_TO_FILL_BRANDING_VARIATION_2" desc="Message shown at the bottom of the Touch To Fill sheet to draw attention to the feature.">
-        New in <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph>! Control how you sign in with one tap
-      </message>
-      <message name="IDS_TOUCH_TO_FILL_BRANDING_VARIATION_3" desc="Message shown at the bottom of the Touch To Fill sheet to draw attention to the feature.">
-        Powered by <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph>
-      </message>
     </messages>
   </release>
 </grit>
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_1.png.sha1 b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_1.png.sha1
deleted file mode 100644
index 01777bc..0000000
--- a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_1.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a94e225d5011d62757ca15149d0ad612d0f88221
\ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_2.png.sha1 b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_2.png.sha1
deleted file mode 100644
index 5602c01..0000000
--- a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_2.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1700099f27a481a876e00502886b3380cb5acf8a
\ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_3.png.sha1 b/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_3.png.sha1
deleted file mode 100644
index bb44aa68..0000000
--- a/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings_grd/IDS_TOUCH_TO_FILL_BRANDING_VARIATION_3.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3751227bb0f8bf20a6474e176f5735a722531e4d
\ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
index 1cd68320..544e183 100644
--- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
+++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
@@ -15,7 +15,6 @@
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.CREDENTIAL;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.FORMATTED_ORIGIN;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CredentialProperties.ON_CLICK_LISTENER;
-import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FooterProperties.BRANDING_MESSAGE_ID;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.FORMATTED_URL;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.ORIGIN_SECURE;
 import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties.SINGLE_CREDENTIAL;
@@ -45,7 +44,6 @@
 import org.chromium.base.test.util.ScalableTimeout;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FooterProperties;
 import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.HeaderProperties;
 import org.chromium.chrome.browser.touch_to_fill.data.Credential;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -196,46 +194,6 @@
 
     @Test
     @MediumTest
-    public void testBrandingVariationZeroHides() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mModel.get(SHEET_ITEMS)
-                    .add(new MVCListAdapter.ListItem(TouchToFillProperties.ItemType.FOOTER,
-                            new PropertyModel.Builder(FooterProperties.ALL_KEYS)
-                                    .with(BRANDING_MESSAGE_ID, 0)
-                                    .build()));
-            mModel.set(VISIBLE, true);
-        });
-        pollUiThread(() -> getBottomSheetState() == BottomSheetController.SheetState.HALF);
-        TextView brandingMessage =
-                mTouchToFillView.getContentView().findViewById(R.id.touch_to_fill_branding_message);
-
-        assertThat(brandingMessage.getVisibility(), is(View.GONE));
-    }
-
-    @Test
-    @MediumTest
-    public void testBrandingVariationOneDisplayed() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mModel.get(SHEET_ITEMS)
-                    .add(new MVCListAdapter.ListItem(TouchToFillProperties.ItemType.FOOTER,
-                            new PropertyModel.Builder(FooterProperties.ALL_KEYS)
-                                    .with(BRANDING_MESSAGE_ID,
-                                            R.string.touch_to_fill_branding_variation_1)
-                                    .build()));
-            mModel.set(VISIBLE, true);
-        });
-        pollUiThread(() -> getBottomSheetState() == BottomSheetController.SheetState.HALF);
-        TextView brandingMessage =
-                mTouchToFillView.getContentView().findViewById(R.id.touch_to_fill_branding_message);
-
-        String expectedBrandingMessage =
-                String.format(getActivity().getString(R.string.touch_to_fill_branding_variation_1),
-                        getActivity().getString(org.chromium.chrome.R.string.app_name));
-        assertThat(brandingMessage.getText(), is(expectedBrandingMessage));
-    }
-
-    @Test
-    @MediumTest
     public void testCredentialsChangedByModel() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTouchToFillView.setVisible(true);
diff --git a/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java b/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
index 2133e853..a2d706d2 100644
--- a/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
+++ b/chrome/browser/touch_to_fill/android/junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java
@@ -153,7 +153,7 @@
     public void testShowCredentialsSetsCredentialListAndRequestsFavicons() {
         mMediator.showCredentials(TEST_URL, true, Arrays.asList(ANA, CARL, BOB));
         ListModel<MVCListAdapter.ListItem> itemList = mModel.get(SHEET_ITEMS);
-        assertThat(itemList.size(), is(5)); // Header + Credentials + Footer
+        assertThat(itemList.size(), is(4)); // Header + three Credentials
         assertThat(itemList.get(1).type, is(ItemType.CREDENTIAL));
         assertThat(itemList.get(1).model.get(CREDENTIAL), is(ANA));
         assertThat(itemList.get(1).model.get(FAVICON_OR_FALLBACK), is(nullValue()));
@@ -176,7 +176,7 @@
     public void testFetchFaviconUpdatesModel() {
         mMediator.showCredentials(TEST_URL, true, Collections.singletonList(CARL));
         ListModel<MVCListAdapter.ListItem> itemList = mModel.get(SHEET_ITEMS);
-        assertThat(itemList.size(), is(3)); // Header + Credentials + Footer
+        assertThat(itemList.size(), is(3)); // Header + Credential + Continue Button
         assertThat(itemList.get(1).type, is(ItemType.CREDENTIAL));
         assertThat(itemList.get(1).model.get(CREDENTIAL), is(CARL));
         assertThat(itemList.get(1).model.get(FAVICON_OR_FALLBACK), is(nullValue()));
@@ -201,7 +201,7 @@
     @Test
     public void testShowCredentialsFormatPslOrigins() {
         mMediator.showCredentials(TEST_URL, true, Arrays.asList(ANA, BOB));
-        assertThat(mModel.get(SHEET_ITEMS).size(), is(4)); // Header + Credentials + Footer
+        assertThat(mModel.get(SHEET_ITEMS).size(), is(3)); // Header + two Credentials
         assertThat(mModel.get(SHEET_ITEMS).get(1).type, is(ItemType.CREDENTIAL));
         assertThat(mModel.get(SHEET_ITEMS).get(1).model.get(FORMATTED_ORIGIN),
                 is(format(ANA.getOriginUrl())));
@@ -214,7 +214,7 @@
     public void testClearsCredentialListWhenShowingAgain() {
         mMediator.showCredentials(TEST_URL, true, Collections.singletonList(ANA));
         ListModel<MVCListAdapter.ListItem> itemList = mModel.get(SHEET_ITEMS);
-        assertThat(itemList.size(), is(3)); // Header + Credentials + Footer
+        assertThat(itemList.size(), is(3)); // Header + Credential + Continue Button
         assertThat(itemList.get(1).type, is(ItemType.CREDENTIAL));
         assertThat(itemList.get(1).model.get(CREDENTIAL), is(ANA));
         assertThat(itemList.get(1).model.get(FAVICON_OR_FALLBACK), is(nullValue()));
@@ -222,7 +222,7 @@
         // Showing the sheet a second time should replace all changed credentials.
         mMediator.showCredentials(TEST_URL, true, Collections.singletonList(BOB));
         itemList = mModel.get(SHEET_ITEMS);
-        assertThat(itemList.size(), is(3)); // Header + Credentials + Footer
+        assertThat(itemList.size(), is(3)); // Header + Credential + Continue Button
         assertThat(itemList.get(1).type, is(ItemType.CREDENTIAL));
         assertThat(itemList.get(1).model.get(CREDENTIAL), is(BOB));
         assertThat(itemList.get(1).model.get(FAVICON_OR_FALLBACK), is(nullValue()));
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc
index c58551d..15f73a38 100644
--- a/chrome/browser/translate/translate_manager_browsertest.cc
+++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -2015,9 +2015,11 @@
 };
 
 // Test that iframes can be translated.
+//
+// TODO(https://crbug.com/1106620): Disabled due to flake and crashes.
 IN_PROC_BROWSER_TEST_F(
     TranslateManagerWithMainFrameLanguageDetectionBrowserTest,
-    TranslateIframe) {
+    DISABLED_TranslateIframe) {
   base::HistogramTester histograms;
   SetTranslateScript(kTestValidScript);
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 1fa7a23b..2548a43 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2707,6 +2707,8 @@
         "webui/signin/dice_turn_sync_on_helper.h",
         "webui/signin/dice_turn_sync_on_helper_delegate_impl.cc",
         "webui/signin/dice_turn_sync_on_helper_delegate_impl.h",
+        "webui/signin/dice_web_signin_intercept_handler.cc",
+        "webui/signin/dice_web_signin_intercept_handler.h",
         "webui/signin/dice_web_signin_intercept_ui.cc",
         "webui/signin/dice_web_signin_intercept_ui.h",
       ]
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
index 11d03ccd..1f2c7a2 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -18,11 +18,11 @@
 #include "base/files/file_util.h"
 #include "base/i18n/time_formatting.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/syslog_logging.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "build/build_config.h"
@@ -223,7 +223,7 @@
                     scoped_refptr<base::RefCountedMemory> png_data,
                     ScreenshotFileResult result,
                     const base::FilePath& local_path) {
-  DCHECK(!base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(!base::CurrentUIThread::IsSet());
   DCHECK(!screenshot_path.empty());
 
   ScreenshotResult screenshot_result = ScreenshotResult::SUCCESS;
@@ -257,7 +257,7 @@
 void EnsureLocalDirectoryExists(
     const base::FilePath& path,
     ChromeScreenshotGrabber::FileCallback callback) {
-  DCHECK(!base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(!base::CurrentUIThread::IsSet());
   DCHECK(!path.empty());
 
   if (!base::CreateDirectory(path.DirName())) {
diff --git a/chrome/browser/ui/ash/media_client_impl.cc b/chrome/browser/ui/ash/media_client_impl.cc
index 8b0e6dc..8c99f09 100644
--- a/chrome/browser/ui/ash/media_client_impl.cc
+++ b/chrome/browser/ui/ash/media_client_impl.cc
@@ -10,8 +10,8 @@
 #include "base/bind.h"
 #include "base/check_op.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/extensions/media_player_api.h"
 #include "chrome/browser/chromeos/extensions/media_player_event_router.h"
@@ -226,7 +226,7 @@
                                       int render_frame_id,
                                       blink::mojom::MediaStreamType stream_type,
                                       const content::MediaRequestState state) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   // The PostTask is necessary because the state of MediaStreamCaptureIndicator
   // gets updated after this.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm
index 47ff8c65..f9b2fa2 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -10,9 +10,9 @@
 #include "base/mac/bundle_locations.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/browser_process_impl.h"
 #include "chrome/browser/first_run/first_run.h"
@@ -55,7 +55,7 @@
 void FirstRunShowBridge::ShowDialog(const base::Closure& quit_closure) {
   // Proceeding past the modal dialog requires user interaction. Allow nested
   // tasks to run so that signal handlers operate correctly.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow_nested;
+  base::CurrentThread::ScopedNestableTaskAllower allow_nested;
   [controller_ show];
   quit_closure.Run();
 }
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
index e947df0..088c16cd 100644
--- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
+++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
@@ -11,10 +11,10 @@
 #import "base/mac/scoped_objc_class_swizzler.h"
 #import "base/mac/scoped_sending_event.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #import "base/message_loop/message_pump_mac.h"
 #include "base/no_destructor.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/task/current_thread.h"
 #import "chrome/browser/mac/nsprocessinfo_additions.h"
 #import "ui/base/cocoa/menu_controller.h"
 
@@ -224,7 +224,7 @@
 
   {
     // Make sure events can be pumped while the menu is up.
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedNestableTaskAllower allow;
 
     // Ensure the UI can update while the menu is fading out.
     base::ScopedPumpMessagesInPrivateModes pump_private;
diff --git a/chrome/browser/ui/recently_audible_helper_unittest.cc b/chrome/browser/ui/recently_audible_helper_unittest.cc
index 75640c8..279b96e 100644
--- a/chrome/browser/ui/recently_audible_helper_unittest.cc
+++ b/chrome/browser/ui/recently_audible_helper_unittest.cc
@@ -7,8 +7,8 @@
 #include <list>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
@@ -32,7 +32,7 @@
     scoped_context_ =
         std::make_unique<base::TestMockTimeTaskRunner::ScopedContext>(
             task_runner_);
-    base::MessageLoopCurrent::Get()->SetTaskRunner(task_runner_);
+    base::CurrentThread::Get()->SetTaskRunner(task_runner_);
 
     RecentlyAudibleHelper::CreateForWebContents(contents_);
     helper_ = RecentlyAudibleHelper::FromWebContents(contents_);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
index 47b6e6f..5ec506a 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -284,7 +284,7 @@
                 gfx::Point point,
                 int operation) {
   // Allow nested run loop so we get DnD events as we drag this around.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower nestable_task_allower;
+  base::CurrentThread::ScopedNestableTaskAllower nestable_task_allower;
 
   views::Widget* widget = views::Widget::GetWidgetForNativeView(native_view);
   if (widget) {
diff --git a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
index 2cfeb294..3a88c87 100644
--- a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
@@ -7,7 +7,7 @@
 #include "ash/public/cpp/accelerators.h"
 #include "ash/shell.h"
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -25,7 +25,7 @@
 views::ViewsDelegate::ProcessMenuAcceleratorResult
 ChromeViewsDelegate::ProcessAcceleratorWhileMenuShowing(
     const ui::Accelerator& accelerator) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   if (ash::AcceleratorController::Get()->OnMenuAccelerator(accelerator)) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
index e264532..14eb938 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -631,7 +631,9 @@
       browser_view()->GetActiveWebContents()));
 }
 
-IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest, TestScrollingPage) {
+// TODO(https://crbug.com/1106700): Flakily timing out.
+IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest,
+                       DISABLED_TestScrollingPage) {
   ToggleTabletMode();
   ASSERT_TRUE(GetTabletModeEnabled());
   EXPECT_TRUE(top_controls_slide_controller()->IsEnabled());
diff --git a/chrome/browser/ui/views/media_router/media_router_views_ui.cc b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
index 44ad41b..b5e06977 100644
--- a/chrome/browser/ui/views/media_router/media_router_views_ui.cc
+++ b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
@@ -54,11 +54,6 @@
 #include "ui/display/display.h"
 #include "url/origin.h"
 
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#include "ui/base/cocoa/permissions_utils.h"
-#endif
-
 namespace media_router {
 
 namespace {
@@ -373,15 +368,6 @@
     return false;
   }
 
-#if defined(OS_MACOSX)
-  if (base::mac::IsAtLeastOS10_15() &&
-      cast_mode == MediaCastMode::DESKTOP_MIRROR &&
-      !ui::IsScreenCaptureAllowed()) {
-    SendIssueForScreenPermission(sink_id);
-    return false;
-  }
-#endif
-
   GetIssueManager()->ClearNonBlockingIssues();
 
   auto on_document_available = base::BindOnce(
@@ -759,18 +745,6 @@
   AddIssue(issue_info);
 }
 
-#if defined(OS_MACOSX)
-void MediaRouterViewsUI::SendIssueForScreenPermission(
-    const MediaSink::Id& sink_id) {
-  std::string issue_title = l10n_util::GetStringUTF8(
-      IDS_MEDIA_ROUTER_ISSUE_MAC_SCREEN_CAPTURE_PERMISSION_ERROR);
-  IssueInfo issue_info(issue_title, IssueInfo::Action::DISMISS,
-                       IssueInfo::Severity::WARNING);
-  issue_info.sink_id = sink_id;
-  AddIssue(issue_info);
-}
-#endif
-
 void MediaRouterViewsUI::SendIssueForUnableToCast(
     MediaCastMode cast_mode,
     const MediaSink::Id& sink_id) {
diff --git a/chrome/browser/ui/views/media_router/media_router_views_ui.h b/chrome/browser/ui/views/media_router/media_router_views_ui.h
index 8d6038c..e6886889 100644
--- a/chrome/browser/ui/views/media_router/media_router_views_ui.h
+++ b/chrome/browser/ui/views/media_router/media_router_views_ui.h
@@ -233,14 +233,8 @@
       const MediaSink::Id& sink_id,
       const base::string16& presentation_request_source_name);
 
-// Creates and sends an issue if casting fails due to lack of screen
-// permissions.
-#if defined(OS_MACOSX)
-  void SendIssueForScreenPermission(const MediaSink::Id& sink_id);
-#endif
-
   // Creates and sends an issue if casting fails for any reason other than
-  // those above.
+  // timeout.
   void SendIssueForUnableToCast(MediaCastMode cast_mode,
                                 const MediaSink::Id& sink_id);
 
diff --git a/chrome/browser/ui/views/menu_model_adapter_test.cc b/chrome/browser/ui/views/menu_model_adapter_test.cc
index 73b126d..fba3e9d 100644
--- a/chrome/browser/ui/views/menu_model_adapter_test.cc
+++ b/chrome/browser/ui/views/menu_model_adapter_test.cc
@@ -6,9 +6,9 @@
 #include "base/callback.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/views/test/view_event_test_base.h"
 #include "chrome/test/base/interactive_test_utils.h"
@@ -224,7 +224,7 @@
 
     menu_model_adapter_.BuildMenu(menu_);
 
-    ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet());
+    ASSERT_TRUE(base::CurrentUIThread::IsSet());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, CreateEventTask(this, &MenuModelAdapterTest::Step3));
   }
diff --git a/chrome/browser/ui/views/message_box_dialog.cc b/chrome/browser/ui/views/message_box_dialog.cc
index 9a76f4f..ec3d816ed 100644
--- a/chrome/browser/ui/views/message_box_dialog.cc
+++ b/chrome/browser/ui/views/message_box_dialog.cc
@@ -10,8 +10,8 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/simple_message_box_internal.h"
@@ -108,7 +108,7 @@
 // ResourceBundle is not initialized yet.
 // Fallback to logging with a default response or a Windows MessageBox.
 #if defined(OS_WIN)
-  if (!base::MessageLoopCurrentForUI::IsSet() ||
+  if (!base::CurrentUIThread::IsSet() ||
       !base::RunLoop::IsRunningOnCurrentThread() ||
       !ui::ResourceBundle::HasSharedInstance()) {
     LOG_IF(ERROR, !checkbox_text.empty()) << "Dialog checkbox won't be shown";
@@ -120,7 +120,7 @@
     return chrome::MESSAGE_BOX_RESULT_DEFERRED;
   }
 #elif defined(OS_MACOSX)
-  if (!base::MessageLoopCurrentForUI::IsSet() ||
+  if (!base::CurrentUIThread::IsSet() ||
       !base::RunLoop::IsRunningOnCurrentThread() ||
       !ui::ResourceBundle::HasSharedInstance()) {
     // Even though this function could return a value synchronously here in
@@ -131,7 +131,7 @@
     return chrome::MESSAGE_BOX_RESULT_DEFERRED;
   }
 #else
-  if (!base::MessageLoopCurrentForUI::IsSet() ||
+  if (!base::CurrentUIThread::IsSet() ||
       !ui::ResourceBundle::HasSharedInstance() ||
       !display::Screen::GetScreen()) {
     LOG(ERROR) << "Unable to show a dialog outside the UI thread message loop: "
diff --git a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
index 82e58c3..309d1ff1 100644
--- a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
+++ b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
@@ -32,7 +32,7 @@
 #include "ui/views/layout/grid_layout.h"
 
 #if defined(OS_MACOSX)
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "chrome/browser/ui/views/policy/enterprise_startup_dialog_mac_util.h"
 #endif
 
@@ -164,7 +164,7 @@
 
 void EnterpriseStartupDialogView::StartModalDialog() {
 #if defined(OS_MACOSX)
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow_nested;
+  base::CurrentThread::ScopedNestableTaskAllower allow_nested;
   StartModal(GetWidget()->GetNativeWindow());
 #endif
 }
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
index 85b38391..13440971 100644
--- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
@@ -8,8 +8,8 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string16.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -363,7 +363,7 @@
   }
   // Enable recursive tasks on the message loop so we can get updates while
   // the context menu is being displayed.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  base::CurrentThread::ScopedNestableTaskAllower allow;
   RunMenuAt(top_level_widget, screen_point, params().source_type);
 
   auto* submenu_view = static_cast<ToolkitDelegateViews*>(toolkit_delegate())
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc
index 774cdfa..9356552 100644
--- a/chrome/browser/ui/views/uninstall_view.cc
+++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/ui/views/uninstall_view.h"
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/launch.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/ui/uninstall_browser_prompt.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -176,7 +176,7 @@
 namespace chrome {
 
 int ShowUninstallBrowserPrompt() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   int result = service_manager::RESULT_CODE_NORMAL_EXIT;
 
   base::RunLoop run_loop;
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
index 449cb542..f581fba 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
@@ -27,31 +27,47 @@
 
 namespace chromeos {
 
-void CrostiniUpgraderDialog::Show(base::OnceClosure launch_closure,
+void CrostiniUpgraderDialog::Show(Profile* profile,
+                                  base::OnceClosure launch_closure,
                                   bool only_run_launch_closure_on_restart) {
-  auto* instance = SystemWebDialogDelegate::FindInstance(GetUrl().spec());
-  if (instance) {
-    instance->Focus();
+  if (Reshow()) {
     return;
   }
 
-  instance = new CrostiniUpgraderDialog(std::move(launch_closure),
-                                        only_run_launch_closure_on_restart);
+  auto* instance = new CrostiniUpgraderDialog(
+      profile, std::move(launch_closure), only_run_launch_closure_on_restart);
   instance->ShowSystemDialog();
   EmitUpgradeDialogEventHistogram(crostini::UpgradeDialogEvent::kDialogShown);
 }
 
+bool CrostiniUpgraderDialog::Reshow() {
+  auto* instance = SystemWebDialogDelegate::FindInstance(GetUrl().spec());
+  if (instance) {
+    instance->Focus();
+    return true;
+  }
+  return false;
+}
+
 CrostiniUpgraderDialog::CrostiniUpgraderDialog(
+    Profile* profile,
     base::OnceClosure launch_closure,
     bool only_run_launch_closure_on_restart)
     : SystemWebDialogDelegate{GetUrl(), /*title=*/{}},
+      profile_(profile),
       only_run_launch_closure_on_restart_(only_run_launch_closure_on_restart),
-      launch_closure_{std::move(launch_closure)} {}
+      launch_closure_{std::move(launch_closure)} {
+  DCHECK(profile_);
+  crostini::CrostiniManager::GetForProfile(profile_)->SetCrostiniDialogStatus(
+      crostini::DialogType::UPGRADER, true);
+}
 
 CrostiniUpgraderDialog::~CrostiniUpgraderDialog() {
   if (deletion_closure_for_testing_) {
     std::move(deletion_closure_for_testing_).Run();
   }
+  crostini::CrostiniManager::GetForProfile(profile_)->SetCrostiniDialogStatus(
+      crostini::DialogType::UPGRADER, false);
 }
 
 void CrostiniUpgraderDialog::GetDialogSize(gfx::Size* size) const {
@@ -135,15 +151,10 @@
 }  // namespace
 
 void CrostiniUpgraderDialog::OnDialogShown(content::WebUI* webui) {
-  auto* crostini_manager =
-      crostini::CrostiniManager::GetForProfile(Profile::FromWebUI(webui));
-  crostini_manager->SetCrostiniDialogStatus(crostini::DialogType::UPGRADER,
-                                            true);
-  crostini_manager->UpgradePromptShown(crostini::ContainerId::GetDefault());
-
   upgrader_ui_ = static_cast<CrostiniUpgraderUI*>(webui->GetController());
   upgrader_ui_->set_launch_callback(base::BindOnce(
-      &RunLaunchClosure, crostini_manager->GetWeakPtr(),
+      &RunLaunchClosure,
+      crostini::CrostiniManager::GetForProfile(profile_)->GetWeakPtr(),
       std::move(launch_closure_), only_run_launch_closure_on_restart_));
   return SystemWebDialogDelegate::OnDialogShown(webui);
 }
@@ -151,10 +162,6 @@
 void CrostiniUpgraderDialog::OnCloseContents(content::WebContents* source,
                                              bool* out_close_dialog) {
   upgrader_ui_ = nullptr;
-  auto* crostini_manager = crostini::CrostiniManager::GetForProfile(
-      Profile::FromBrowserContext(source->GetBrowserContext()));
-  crostini_manager->SetCrostiniDialogStatus(crostini::DialogType::UPGRADER,
-                                            false);
   return SystemWebDialogDelegate::OnCloseContents(source, out_close_dialog);
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
index 4df0a35..f71205dc 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
@@ -8,6 +8,8 @@
 #include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
 #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
 
+class Profile;
+
 namespace chromeos {
 
 class CrostiniUpgraderUI;
@@ -20,9 +22,13 @@
   // not desired. This contrasts to being propmpted for container upgrade from
   // The app launcher, in which case the user could opt not to upgrade and the
   // app should still be launched.
-  static void Show(base::OnceClosure launch_closure,
+  static void Show(Profile* profile,
+                   base::OnceClosure launch_closure,
                    bool only_run_launch_closure_on_restart = false);
 
+  // Returns true if there was an existing instance to reshow.
+  static bool Reshow();
+
   void SetDeletionClosureForTesting(
       base::OnceClosure deletion_closure_for_testing);
 
@@ -30,7 +36,8 @@
       crostini::UpgradeDialogEvent event);
 
  private:
-  explicit CrostiniUpgraderDialog(base::OnceClosure launch_closure,
+  explicit CrostiniUpgraderDialog(Profile* profile,
+                                  base::OnceClosure launch_closure,
                                   bool only_run_launch_closure_on_restart);
   ~CrostiniUpgraderDialog() override;
 
@@ -46,6 +53,7 @@
                        bool* out_close_dialog) override;
 
   CrostiniUpgraderUI* upgrader_ui_ = nullptr;  // Not owned.
+  Profile* profile_;                           // Not owned
   const bool only_run_launch_closure_on_restart_;
   base::OnceClosure launch_closure_;
   base::OnceClosure deletion_closure_for_testing_;
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc
index d1c08e6..0df942b 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc
@@ -37,7 +37,8 @@
 
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
-    chromeos::CrostiniUpgraderDialog::Show(base::DoNothing(), false);
+    chromeos::CrostiniUpgraderDialog::Show(browser()->profile(),
+                                           base::DoNothing(), false);
   }
 
   chromeos::CrostiniUpgraderDialog* GetCrostiniUpgraderDialog() {
@@ -106,12 +107,29 @@
 };
 
 IN_PROC_BROWSER_TEST_F(CrostiniUpgraderDialogBrowserTest,
-                       NoDialogOnNormalStartup) {
+                       NoDialogBeforeLaunch) {
   base::HistogramTester histogram_tester;
   RegisterApp();
 
-  crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId);
+  bool is_successful_app_launch = false;
   ExpectNoDialog();
+  base::RunLoop run_loop;
+  crostini::LaunchCrostiniApp(
+      browser()->profile(), app_id(), kDisplayId, {},
+      base::BindOnce(
+          [](base::RunLoop* run_loop, bool* is_successful_app_launch,
+             bool success, const std::string& failure_reason) {
+            // In tests, we don't expect Crostini to restart successfully, but
+            // the error message should start as below.
+            auto pos = failure_reason.find("crostini restart to launch app");
+            *is_successful_app_launch = (pos == 0);
+            run_loop->Quit();
+          },
+          &run_loop, &is_successful_app_launch));
+  run_loop.Run();
+
+  ExpectNoDialog();
+  EXPECT_TRUE(is_successful_app_launch);
 }
 
 IN_PROC_BROWSER_TEST_F(CrostiniUpgraderDialogBrowserTest, ShowsOnAppLaunch) {
@@ -120,14 +138,27 @@
   DowngradeOSRelease();
   RegisterApp();
 
-  crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId);
+  chromeos::CrostiniUpgraderDialog::Show(browser()->profile(),
+                                         base::DoNothing());
   ExpectDialog();
 
-  SafelyCloseDialog();
-  ExpectNoDialog();
+  base::RunLoop run_loop;
+  bool is_successful_app_launch = false;
+  crostini::LaunchCrostiniApp(
+      browser()->profile(), app_id(), kDisplayId, {},
+      base::BindOnce(
+          [](base::RunLoop* run_loop, bool* is_successful_app_launch,
+             bool success, const std::string& failure_reason) {
+            *is_successful_app_launch = success;
+            run_loop->Quit();
+          },
+          &run_loop, &is_successful_app_launch));
 
-  // Once only - second time we launch an app, the dialog should not appear.
-  crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId);
+  run_loop.Run();
+  ExpectDialog();
+  EXPECT_FALSE(is_successful_app_launch);
+
+  SafelyCloseDialog();
   ExpectNoDialog();
 
   histogram_tester.ExpectUniqueSample(
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
index b16643e8..3f03c3e 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
@@ -40,7 +40,7 @@
 namespace {
 
 void Redisplay() {
-  CrostiniUpgraderDialog::Show(base::DoNothing());
+  CrostiniUpgraderDialog::Reshow();
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/devtools_ui_data_source.cc b/chrome/browser/ui/webui/devtools_ui_data_source.cc
index 63add823a..c40be35 100644
--- a/chrome/browser/ui/webui/devtools_ui_data_source.cc
+++ b/chrome/browser/ui/webui/devtools_ui_data_source.cc
@@ -64,6 +64,12 @@
   } else if (base::EndsWith(filename, ".png",
                             base::CompareCase::INSENSITIVE_ASCII)) {
     return "image/png";
+  } else if (base::EndsWith(filename, ".map",
+                            base::CompareCase::INSENSITIVE_ASCII)) {
+    return "application/json";
+  } else if (base::EndsWith(filename, ".ts",
+                            base::CompareCase::INSENSITIVE_ASCII)) {
+    return "application/x-typescript";
   } else if (base::EndsWith(filename, ".gif",
                             base::CompareCase::INSENSITIVE_ASCII)) {
     return "image/gif";
diff --git a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
index f3c630fd..2d0a890 100644
--- a/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
@@ -14,12 +14,12 @@
 #include "base/bind_helpers.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/supports_user_data.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -155,7 +155,7 @@
   gfx::NativeView view = web_contents->GetNativeView();
   {
     // Enable nested tasks during DnD, while |DragDownload()| blocks.
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedNestableTaskAllower allow;
     DragDownloadItem(file, icon, view);
   }
 }
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
index 308a8a8..c1e555ce4 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -14,10 +14,10 @@
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
@@ -188,7 +188,7 @@
     const content::WebUI::MessageCallback& handler,
     const base::ListValue* data) {
   // The handler might run a nested loop to wait for something.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower nestable_task_allower;
+  base::CurrentThread::ScopedNestableTaskAllower nestable_task_allower;
   handler.Run(data);
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
index 39e87b3..72c9b266 100644
--- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -512,6 +512,7 @@
     const base::ListValue* args) {
   CHECK_EQ(0U, args->GetList().size());
   chromeos::CrostiniUpgraderDialog::Show(
+      profile_,
       base::BindOnce(&CrostiniHandler::LaunchTerminal,
                      weak_ptr_factory_.GetWeakPtr()),
       // If the user cancels the upgrade, we won't need to restart Crostini and
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
new file mode 100644
index 0000000..098d7f8
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h"
+
+#include "base/bind.h"
+#include "content/public/browser/web_ui.h"
+
+DiceWebSigninInterceptHandler::DiceWebSigninInterceptHandler(
+    base::OnceCallback<void(bool)> callback)
+    : callback_(std::move(callback)) {
+  DCHECK(callback_);
+}
+
+DiceWebSigninInterceptHandler::~DiceWebSigninInterceptHandler() = default;
+
+void DiceWebSigninInterceptHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "accept",
+      base::BindRepeating(&DiceWebSigninInterceptHandler::HandleAccept,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "cancel",
+      base::BindRepeating(&DiceWebSigninInterceptHandler::HandleCancel,
+                          base::Unretained(this)));
+}
+
+void DiceWebSigninInterceptHandler::HandleAccept(const base::ListValue* args) {
+  if (callback_)
+    std::move(callback_).Run(true);
+}
+
+void DiceWebSigninInterceptHandler::HandleCancel(const base::ListValue* args) {
+  if (callback_)
+    std::move(callback_).Run(false);
+}
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h
new file mode 100644
index 0000000..80cc9e3b
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPT_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPT_HANDLER_H_
+
+#include "content/public/browser/web_ui_message_handler.h"
+
+#include "base/callback.h"
+
+namespace base {
+class ListValue;
+}
+
+// WebUI message handler for the Dice web signin intercept bubble.
+class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler {
+ public:
+  explicit DiceWebSigninInterceptHandler(
+      base::OnceCallback<void(bool)> callback);
+  ~DiceWebSigninInterceptHandler() override;
+
+  DiceWebSigninInterceptHandler(const DiceWebSigninInterceptHandler&) = delete;
+  DiceWebSigninInterceptHandler& operator=(
+      const DiceWebSigninInterceptHandler&) = delete;
+
+  // content::WebUIMessageHandler:
+  void RegisterMessages() override;
+
+ private:
+  void HandleAccept(const base::ListValue* args);
+  void HandleCancel(const base::ListValue* args);
+
+  base::OnceCallback<void(bool)> callback_;
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_WEB_SIGNIN_INTERCEPT_HANDLER_H_
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc
index c266df4e..002d68e 100644
--- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc
+++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc
@@ -5,23 +5,59 @@
 #include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h"
 
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h"
+#include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/browser_resources.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "services/network/public/mojom/content_security_policy.mojom.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/resources/grit/webui_resources.h"
 
 DiceWebSigninInterceptUI::DiceWebSigninInterceptUI(content::WebUI* web_ui)
     : content::WebUIController(web_ui) {
-  content::WebUIDataSource* html_source = content::WebUIDataSource::Create(
+  content::WebUIDataSource* source = content::WebUIDataSource::Create(
       chrome::kChromeUIDiceWebSigninInterceptHost);
-  html_source->SetDefaultResource(IDR_SIGNIN_DICE_WEB_INTERCEPT_HTML);
-  content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source);
+  source->SetDefaultResource(IDR_SIGNIN_DICE_WEB_INTERCEPT_HTML);
+  source->AddResourcePath("dice_web_signin_intercept_app.js",
+                          IDR_SIGNIN_DICE_WEB_INTERCEPT_APP_JS);
+  source->AddResourcePath("dice_web_signin_intercept_browser_proxy.js",
+                          IDR_SIGNIN_DICE_WEB_INTERCEPT_BROWSER_PROXY_JS);
+
+  // Localized strings.
+  source->UseStringsJs();
+  source->EnableReplaceI18nInJS();
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+      {"diceWebSigninInterceptTitle",
+       IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE},
+      {"diceWebSigninInterceptDesc",
+       IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC},
+      {"diceWebSigninInterceptAcceptLabel",
+       IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL},
+      {"diceWebSigninInterceptCancelLabel",
+       IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL},
+  };
+  webui::AddLocalizedStringsBulk(source, kLocalizedStrings);
+
+  // Resources for testing.
+  source->OverrideContentSecurityPolicy(
+      network::mojom::CSPDirectiveName::ScriptSrc,
+      "script-src chrome://resources chrome://test 'self';");
+  source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
+  source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
+
+  content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
 }
 
 DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default;
 
 void DiceWebSigninInterceptUI::Initialize(
     base::OnceCallback<void(bool)> callback) {
-  // TODO(droger): add a handler and call the callback based on user action.
+  web_ui()->AddMessageHandler(
+      std::make_unique<DiceWebSigninInterceptHandler>(std::move(callback)));
 }
 
 WEB_UI_CONTROLLER_TYPE_IMPL(DiceWebSigninInterceptUI)
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 99ce577..cbaf5439 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1594943787-51a385cad6026d977d7d0e8c786de56f21cce493.profdata
+chrome-mac-master-1594987060-434c51fdab164717c1b94e12633f94a30a81dd52.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 41c7b9a..503b2f7 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1594878809-f70bebc20790ac0846ac45f570a81eb656b74862.profdata
+chrome-win64-master-1594943787-7f5d9753ae33a53104b9969d76a646b53f10ccce.profdata
diff --git a/chrome/chrome_cleaner/logging/pending_logs_service.cc b/chrome/chrome_cleaner/logging/pending_logs_service.cc
index 31aa6cd..70ca915 100644
--- a/chrome/chrome_cleaner/logging/pending_logs_service.cc
+++ b/chrome/chrome_cleaner/logging/pending_logs_service.cc
@@ -12,7 +12,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
 #include "chrome/chrome_cleaner/logging/logging_service_api.h"
 #include "chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.pb.h"
@@ -40,7 +40,7 @@
     const ChromeCleanerReport& chrome_cleaner_report,
     base::FilePath* log_file,
     RegistryLogger* registry_logger) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(log_file);
   DCHECK(registry_logger);
   // This can happen when we fail while retrying. The logging service is not
@@ -124,7 +124,7 @@
 }
 
 PendingLogsService::PendingLogsService() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 }
 
 PendingLogsService::~PendingLogsService() = default;
diff --git a/chrome/common/service_process_util_posix.cc b/chrome/common/service_process_util_posix.cc
index b4913b0..dde9c9d8 100644
--- a/chrome/common/service_process_util_posix.cc
+++ b/chrome/common/service_process_util_posix.cc
@@ -13,9 +13,9 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "build/branding_buildflags.h"
 #include "chrome/common/multi_process_lock.h"
 
@@ -232,7 +232,7 @@
   DCHECK(task_runner->BelongsToCurrentThread());
   DCHECK_EQ(g_signal_socket, -1);
   DCHECK(!signal->IsSignaled());
-  *success = base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  *success = base::CurrentIOThread::Get()->WatchFileDescriptor(
       sockets[0], true, base::MessagePumpForIO::WATCH_READ, &watcher,
       terminate_monitor.get());
   if (!*success) {
diff --git a/chrome/services/sharing/BUILD.gn b/chrome/services/sharing/BUILD.gn
index fed32652..29953ab7 100644
--- a/chrome/services/sharing/BUILD.gn
+++ b/chrome/services/sharing/BUILD.gn
@@ -6,27 +6,12 @@
   sources = [
     "sharing_impl.cc",
     "sharing_impl.h",
-    "webrtc/ipc_network_manager.cc",
-    "webrtc/ipc_network_manager.h",
-    "webrtc/ipc_packet_socket_factory.cc",
-    "webrtc/ipc_packet_socket_factory.h",
-    "webrtc/mdns_responder_adapter.cc",
-    "webrtc/mdns_responder_adapter.h",
-    "webrtc/p2p_async_address_resolver.cc",
-    "webrtc/p2p_async_address_resolver.h",
-    "webrtc/p2p_port_allocator.cc",
-    "webrtc/p2p_port_allocator.h",
-    "webrtc/p2p_socket_client.cc",
-    "webrtc/p2p_socket_client.h",
-    "webrtc/p2p_socket_client_delegate.h",
-    "webrtc/sharing_webrtc_connection.cc",
-    "webrtc/sharing_webrtc_connection.h",
-    "webrtc/sharing_webrtc_timing_recorder.cc",
-    "webrtc/sharing_webrtc_timing_recorder.h",
   ]
 
   deps = [
     "nearby",
+    "nearby/platform_v2",
+    "webrtc",
     "//jingle:webrtc_glue",
     "//third_party/webrtc_overrides:webrtc_component",
   ]
@@ -42,17 +27,12 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "sharing_impl_unittest.cc",
-    "webrtc/sharing_webrtc_connection_integration_test.cc",
-    "webrtc/sharing_webrtc_connection_unittest.cc",
-    "webrtc/test/mock_sharing_connection_host.cc",
-    "webrtc/test/mock_sharing_connection_host.h",
-  ]
+  sources = [ "sharing_impl_unittest.cc" ]
 
   deps = [
     ":sharing",
     "nearby/test_support",
+    "webrtc/test",
     "//base/test:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/chrome/services/sharing/nearby/BUILD.gn b/chrome/services/sharing/nearby/BUILD.gn
index 5e114cd..68ebdb6 100644
--- a/chrome/services/sharing/nearby/BUILD.gn
+++ b/chrome/services/sharing/nearby/BUILD.gn
@@ -6,14 +6,9 @@
   sources = [
     "nearby_connections.cc",
     "nearby_connections.h",
-    "webrtc/incoming_messages_listener.cc",
-    "webrtc/incoming_messages_listener.h",
   ]
 
-  deps = [
-    "platform_v2",
-    "//third_party/nearby:core",
-  ]
+  deps = [ "//third_party/nearby:core" ]
 
   public_deps = [
     "decoder",
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc
index 7aa211a..7de0785 100644
--- a/chrome/services/sharing/nearby/nearby_connections.cc
+++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -34,8 +34,24 @@
     bluetooth_adapter_.set_disconnect_handler(base::BindOnce(
         &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
   }
+
+  socket_manager_.Bind(
+      std::move(dependencies->webrtc_dependencies->socket_manager));
+  socket_manager_.set_disconnect_handler(base::BindOnce(
+      &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
+
+  mdns_responder_.Bind(
+      std::move(dependencies->webrtc_dependencies->mdns_responder));
+  mdns_responder_.set_disconnect_handler(base::BindOnce(
+      &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
+
+  ice_config_fetcher_.Bind(
+      std::move(dependencies->webrtc_dependencies->ice_config_fetcher));
+  ice_config_fetcher_.set_disconnect_handler(base::BindOnce(
+      &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
+
   webrtc_signaling_messenger_.Bind(
-      std::move(dependencies->webrtc_signaling_messenger));
+      std::move(dependencies->webrtc_dependencies->messenger));
   webrtc_signaling_messenger_.set_disconnect_handler(base::BindOnce(
       &NearbyConnections::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));
 
@@ -63,6 +79,29 @@
   return bluetooth_adapter_.get();
 }
 
+network::mojom::P2PSocketManager*
+NearbyConnections::GetWebRtcP2PSocketManager() {
+  if (!socket_manager_.is_bound())
+    return nullptr;
+
+  return socket_manager_.get();
+}
+
+network::mojom::MdnsResponder* NearbyConnections::GetWebRtcMdnsResponder() {
+  if (!mdns_responder_.is_bound())
+    return nullptr;
+
+  return mdns_responder_.get();
+}
+
+sharing::mojom::IceConfigFetcher*
+NearbyConnections::GetWebRtcIceConfigFetcher() {
+  if (!ice_config_fetcher_.is_bound())
+    return nullptr;
+
+  return ice_config_fetcher_.get();
+}
+
 sharing::mojom::WebRtcSignalingMessenger*
 NearbyConnections::GetWebRtcSignalingMessenger() {
   if (!webrtc_signaling_messenger_.is_bound())
diff --git a/chrome/services/sharing/nearby/nearby_connections.h b/chrome/services/sharing/nearby/nearby_connections.h
index 0b1c759..f535275 100644
--- a/chrome/services/sharing/nearby/nearby_connections.h
+++ b/chrome/services/sharing/nearby/nearby_connections.h
@@ -49,6 +49,9 @@
   static NearbyConnections& GetInstance();
 
   bluetooth::mojom::Adapter* GetBluetoothAdapter();
+  network::mojom::P2PSocketManager* GetWebRtcP2PSocketManager();
+  network::mojom::MdnsResponder* GetWebRtcMdnsResponder();
+  sharing::mojom::IceConfigFetcher* GetWebRtcIceConfigFetcher();
   sharing::mojom::WebRtcSignalingMessenger* GetWebRtcSignalingMessenger();
 
  private:
@@ -59,6 +62,9 @@
 
   // Medium dependencies:
   mojo::Remote<bluetooth::mojom::Adapter> bluetooth_adapter_;
+  mojo::Remote<network::mojom::P2PSocketManager> socket_manager_;
+  mojo::Remote<network::mojom::MdnsResponder> mdns_responder_;
+  mojo::Remote<sharing::mojom::IceConfigFetcher> ice_config_fetcher_;
   mojo::Remote<sharing::mojom::WebRtcSignalingMessenger>
       webrtc_signaling_messenger_;
 
diff --git a/chrome/services/sharing/nearby/platform_v2/BUILD.gn b/chrome/services/sharing/nearby/platform_v2/BUILD.gn
index c255814..bb412ae4 100644
--- a/chrome/services/sharing/nearby/platform_v2/BUILD.gn
+++ b/chrome/services/sharing/nearby/platform_v2/BUILD.gn
@@ -25,15 +25,23 @@
     "submittable_executor.cc",
     "submittable_executor.h",
     "system_clock.cc",
+    "webrtc.cc",
+    "webrtc.h",
   ]
 
   public_deps = [
-    "//base",
     "//third_party/nearby:platform_v2_api_platform",
     "//third_party/nearby:platform_v2_impl_shared_file",
   ]
 
-  deps = [ "//crypto" ]
+  deps = [
+    "//base",
+    "//chrome/services/sharing/nearby",
+    "//chrome/services/sharing/public/mojom",
+    "//chrome/services/sharing/webrtc",
+    "//crypto",
+    "//jingle:webrtc_glue",
+  ]
 }
 
 source_set("unit_tests") {
@@ -50,11 +58,14 @@
     "recursive_mutex_unittest.cc",
     "scheduled_executor_unittest.cc",
     "single_thread_executor_unittest.cc",
+    "webrtc_test.cc",
   ]
 
   deps = [
     ":platform_v2",
     "//base/test:test_support",
+    "//chrome/services/sharing/nearby/test_support",
+    "//mojo/public/cpp/bindings",
     "//testing/gtest",
   ]
 }
diff --git a/chrome/services/sharing/nearby/platform_v2/platform.cc b/chrome/services/sharing/nearby/platform_v2/platform.cc
index 855424e..ef1cbe1 100644
--- a/chrome/services/sharing/nearby/platform_v2/platform.cc
+++ b/chrome/services/sharing/nearby/platform_v2/platform.cc
@@ -6,6 +6,7 @@
 
 #include "base/guid.h"
 #include "base/strings/string_number_conversions.h"
+#include "chrome/services/sharing/nearby/nearby_connections.h"
 #include "chrome/services/sharing/nearby/platform_v2/atomic_boolean.h"
 #include "chrome/services/sharing/nearby/platform_v2/atomic_uint32.h"
 #include "chrome/services/sharing/nearby/platform_v2/condition_variable.h"
@@ -15,6 +16,7 @@
 #include "chrome/services/sharing/nearby/platform_v2/recursive_mutex.h"
 #include "chrome/services/sharing/nearby/platform_v2/scheduled_executor.h"
 #include "chrome/services/sharing/nearby/platform_v2/submittable_executor.h"
+#include "chrome/services/sharing/nearby/platform_v2/webrtc.h"
 #include "third_party/nearby/src/cpp/platform_v2/api/atomic_boolean.h"
 #include "third_party/nearby/src/cpp/platform_v2/api/atomic_reference.h"
 #include "third_party/nearby/src/cpp/platform_v2/api/ble.h"
@@ -138,7 +140,22 @@
 }
 
 std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
-  return nullptr;
+  auto& connections = connections::NearbyConnections::GetInstance();
+
+  network::mojom::P2PSocketManager* socket_manager =
+      connections.GetWebRtcP2PSocketManager();
+  network::mojom::MdnsResponder* mdns_responder =
+      connections.GetWebRtcMdnsResponder();
+  sharing::mojom::IceConfigFetcher* ice_config_fetcher =
+      connections.GetWebRtcIceConfigFetcher();
+  sharing::mojom::WebRtcSignalingMessenger* messenger =
+      connections.GetWebRtcSignalingMessenger();
+
+  if (!socket_manager || !mdns_responder || !ice_config_fetcher || !messenger)
+    return nullptr;
+
+  return std::make_unique<chrome::WebRtcMedium>(socket_manager, mdns_responder,
+                                                ice_config_fetcher, messenger);
 }
 
 std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) {
diff --git a/chrome/services/sharing/nearby/platform_v2/webrtc.cc b/chrome/services/sharing/nearby/platform_v2/webrtc.cc
new file mode 100644
index 0000000..37a0c2fd
--- /dev/null
+++ b/chrome/services/sharing/nearby/platform_v2/webrtc.cc
@@ -0,0 +1,243 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/sharing/nearby/platform_v2/webrtc.h"
+
+#include "chrome/services/sharing/webrtc/ipc_network_manager.h"
+#include "chrome/services/sharing/webrtc/ipc_packet_socket_factory.h"
+#include "chrome/services/sharing/webrtc/mdns_responder_adapter.h"
+#include "chrome/services/sharing/webrtc/p2p_port_allocator.h"
+#include "jingle/glue/thread_wrapper.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/nearby/src/cpp/platform_v2/public/future.h"
+#include "third_party/webrtc/api/jsep.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc_overrides/task_queue_factory.h"
+
+namespace location {
+namespace nearby {
+namespace chrome {
+
+namespace {
+net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("nearby_webrtc_connection", R"(
+        semantics {
+          sender: "Chrome Nearby Share via WebRTC"
+          description:
+            "Chrome Nearby Share allows users to send data securely between "
+            "devices. WebRTC allows Chrome to establish a secure session with "
+            "another Nearby instance running on a different device and to "
+            "transmit and receive data that users want to share across "
+            "devices."
+          trigger:
+            "User uses the Nearby Share feature and selects a peer device to"
+            " send the data to."
+          data:
+            "Text and media encrypted via AES-256-CBC. Protocol-level messages "
+            "for the various subprotocols employed by WebRTC (including ICE, "
+            "DTLS, RTCP, etc.) are encrypted via DTLS-SRTP. Note that ICE "
+            "connectivity checks may leak the user's IP address(es), subject "
+            "to the restrictions/guidance in "
+            "https://datatracker.ietf.org/doc/draft-ietf-rtcweb-ip-handling."
+          destination: OTHER
+          destination_other:
+            "A peer Nearby device that receives this data"
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "This feature is only enabled for signed-in users who enable "
+            "Nearby Share"
+          chrome_policy {
+            BrowserSignin {
+              policy_options {mode: MANDATORY}
+              BrowserSignin: 0
+            }
+          }
+        }
+    )");
+
+class ProxyAsyncResolverFactory final : public webrtc::AsyncResolverFactory {
+ public:
+  explicit ProxyAsyncResolverFactory(
+      sharing::IpcPacketSocketFactory* socket_factory)
+      : socket_factory_(socket_factory) {
+    DCHECK(socket_factory_);
+  }
+
+  rtc::AsyncResolverInterface* Create() override {
+    return socket_factory_->CreateAsyncResolver();
+  }
+
+ private:
+  sharing::IpcPacketSocketFactory* socket_factory_;
+};
+
+// Used as a messenger in sending and receiving WebRTC messages between devices.
+// The messages sent and received are considered untrusted since they
+// originate in an untrusted sandboxed process on device.
+class WebRtcSignalingMessengerImpl
+    : public api::WebRtcSignalingMessenger,
+      public sharing::mojom::IncomingMessagesListener {
+ public:
+  using OnSignalingMessageCallback =
+      api::WebRtcSignalingMessenger::OnSignalingMessageCallback;
+
+  WebRtcSignalingMessengerImpl(
+      const std::string& self_id,
+      sharing::mojom::WebRtcSignalingMessenger* messenger)
+      : self_id_(self_id), messenger_(messenger) {}
+
+  ~WebRtcSignalingMessengerImpl() override = default;
+
+  WebRtcSignalingMessengerImpl(const WebRtcSignalingMessengerImpl& other) =
+      delete;
+  WebRtcSignalingMessengerImpl& operator=(
+      const WebRtcSignalingMessengerImpl& other) = delete;
+
+  // api::WebRtcSignalingMessenger:
+  bool SendMessage(absl::string_view peer_id,
+                   const ByteArray& message) override {
+    bool success = false;
+    if (!messenger_->SendMessage(self_id_, std::string(peer_id),
+                                 std::string(message), &success)) {
+      return false;
+    }
+
+    return success;
+  }
+
+  // api::WebRtcSignalingMessenger:
+  bool StartReceivingMessages(OnSignalingMessageCallback callback) override {
+    signaling_message_callback_ = std::move(callback);
+    incoming_messages_receiver_.reset();
+    bool success = false;
+
+    if (!messenger_->StartReceivingMessages(
+            self_id_, incoming_messages_receiver_.BindNewPipeAndPassRemote(),
+            &success) ||
+        !success) {
+      incoming_messages_receiver_.reset();
+      signaling_message_callback_ = nullptr;
+      return false;
+    }
+
+    incoming_messages_receiver_.set_disconnect_handler(
+        base::BindOnce(&WebRtcSignalingMessengerImpl::StopReceivingMessages,
+                       base::Unretained(this)));
+
+    return success;
+  }
+
+  // api::WebRtcSignalingMessenger:
+  void StopReceivingMessages() override {
+    incoming_messages_receiver_.reset();
+    signaling_message_callback_ = nullptr;
+    messenger_->StopReceivingMessages();
+  }
+
+ private:
+  // mojom::IncomingMessagesListener:
+  void OnMessage(const std::string& message) override {
+    if (signaling_message_callback_)
+      signaling_message_callback_(ByteArray(message));
+  }
+
+  std::string self_id_;
+  sharing::mojom::WebRtcSignalingMessenger* messenger_;
+  mojo::Receiver<sharing::mojom::IncomingMessagesListener>
+      incoming_messages_receiver_{this};
+  OnSignalingMessageCallback signaling_message_callback_;
+
+  base::WeakPtrFactory<WebRtcSignalingMessengerImpl> weak_ptr_factory_{this};
+};
+
+}  // namespace
+
+WebRtcMedium::WebRtcMedium(
+    network::mojom::P2PSocketManager* socket_manager,
+    network::mojom::MdnsResponder* mdns_responder,
+    sharing::mojom::IceConfigFetcher* ice_config_fetcher,
+    sharing::mojom::WebRtcSignalingMessenger* webrtc_signaling_messenger)
+    : p2p_socket_manager_(socket_manager),
+      mdns_responder_(mdns_responder),
+      ice_config_fetcher_(ice_config_fetcher),
+      webrtc_signaling_messenger_(webrtc_signaling_messenger) {}
+WebRtcMedium::~WebRtcMedium() = default;
+
+void WebRtcMedium::CreatePeerConnection(
+    webrtc::PeerConnectionObserver* observer,
+    PeerConnectionCallback callback) {
+  ice_config_fetcher_->GetIceServers(base::BindOnce(
+      &WebRtcMedium::OnIceServersFetched, weak_ptr_factory_.GetWeakPtr(),
+      observer, std::move(callback)));
+}
+
+void WebRtcMedium::OnIceServersFetched(
+    webrtc::PeerConnectionObserver* observer,
+    PeerConnectionCallback callback,
+    std::vector<sharing::mojom::IceServerPtr> ice_servers) {
+  // WebRTC is using the current thread instead of creating new threads since
+  // otherwise the |network_manager| is created on current thread and destroyed
+  // on network thread, and so the mojo Receiver stored in it is not called on
+  // the same sequence. The long terms correct fix is to resolve
+  // http://crbug.com/1044522 and reuse the code in blink layer which ensures
+  // that the objects are created on the same thread they would be destroyed in.
+  jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+  jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+
+  webrtc::PeerConnectionFactoryDependencies factory_dependencies;
+  factory_dependencies.task_queue_factory = CreateWebRtcTaskQueueFactory();
+  factory_dependencies.network_thread = rtc::Thread::Current();
+  factory_dependencies.worker_thread = rtc::Thread::Current();
+  factory_dependencies.signaling_thread = rtc::Thread::Current();
+
+  rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory =
+      webrtc::CreateModularPeerConnectionFactory(
+          std::move(factory_dependencies));
+
+  webrtc::PeerConnectionInterface::RTCConfiguration rtc_config;
+  for (const auto& ice_server : ice_servers) {
+    webrtc::PeerConnectionInterface::IceServer ice_turn_server;
+    for (const auto& url : ice_server->urls)
+      ice_turn_server.urls.push_back(url.spec());
+    if (ice_server->username)
+      ice_turn_server.username = *ice_server->username;
+    if (ice_server->credential)
+      ice_turn_server.password = *ice_server->credential;
+    rtc_config.servers.push_back(ice_turn_server);
+  }
+
+  if (!socket_factory_) {
+    socket_factory_ = std::make_unique<sharing::IpcPacketSocketFactory>(
+        p2p_socket_manager_, kTrafficAnnotation);
+  }
+
+  auto network_manager = std::make_unique<sharing::IpcNetworkManager>(
+      p2p_socket_manager_,
+      std::make_unique<sharing::MdnsResponderAdapter>(mdns_responder_));
+
+  webrtc::PeerConnectionDependencies dependencies(observer);
+  sharing::P2PPortAllocator::Config port_config;
+  port_config.enable_multiple_routes = true;
+  port_config.enable_nonproxied_udp = true;
+  dependencies.allocator = std::make_unique<sharing::P2PPortAllocator>(
+      std::move(network_manager), socket_factory_.get(), port_config);
+  dependencies.async_resolver_factory =
+      std::make_unique<ProxyAsyncResolverFactory>(socket_factory_.get());
+
+  rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection =
+      pc_factory->CreatePeerConnection(rtc_config, std::move(dependencies));
+  callback(std::move(peer_connection));
+}
+
+std::unique_ptr<api::WebRtcSignalingMessenger>
+WebRtcMedium::GetSignalingMessenger(absl::string_view self_id) {
+  return std::make_unique<WebRtcSignalingMessengerImpl>(
+      std::string(self_id), webrtc_signaling_messenger_);
+}
+
+}  // namespace chrome
+}  // namespace nearby
+}  // namespace location
diff --git a/chrome/services/sharing/nearby/platform_v2/webrtc.h b/chrome/services/sharing/nearby/platform_v2/webrtc.h
new file mode 100644
index 0000000..9e336200
--- /dev/null
+++ b/chrome/services/sharing/nearby/platform_v2/webrtc.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_WEBRTC_H_
+#define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_WEBRTC_H_
+
+#include "third_party/nearby/src/cpp/platform_v2/api/webrtc.h"
+
+#include <memory>
+
+#include "chrome/services/sharing/public/mojom/webrtc.mojom.h"
+#include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h"
+#include "services/network/public/mojom/mdns_responder.mojom.h"
+#include "services/network/public/mojom/p2p.mojom.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+
+namespace sharing {
+class IpcPacketSocketFactory;
+}  // namespace sharing
+
+namespace location {
+namespace nearby {
+namespace chrome {
+
+class WebRtcMedium : public api::WebRtcMedium {
+ public:
+  using PeerConnectionCallback = api::WebRtcMedium::PeerConnectionCallback;
+
+  WebRtcMedium(
+      network::mojom::P2PSocketManager* socket_manager,
+      network::mojom::MdnsResponder* mdns_responder,
+      sharing::mojom::IceConfigFetcher* ice_config_fetcher,
+      sharing::mojom::WebRtcSignalingMessenger* webrtc_signaling_messenger);
+  ~WebRtcMedium() override;
+
+  // api::WebRtcMedium:
+  void CreatePeerConnection(webrtc::PeerConnectionObserver* observer,
+                            PeerConnectionCallback callback) override;
+  std::unique_ptr<api::WebRtcSignalingMessenger> GetSignalingMessenger(
+      absl::string_view self_id) override;
+
+ private:
+  void OnIceServersFetched(
+      webrtc::PeerConnectionObserver* observer,
+      PeerConnectionCallback callback,
+      std::vector<sharing::mojom::IceServerPtr> ice_servers);
+
+  network::mojom::P2PSocketManager* p2p_socket_manager_;
+  network::mojom::MdnsResponder* mdns_responder_;
+  sharing::mojom::IceConfigFetcher* ice_config_fetcher_;
+  sharing::mojom::WebRtcSignalingMessenger* webrtc_signaling_messenger_;
+
+  std::unique_ptr<sharing::IpcPacketSocketFactory> socket_factory_;
+
+  base::WeakPtrFactory<WebRtcMedium> weak_ptr_factory_{this};
+};
+
+}  // namespace chrome
+}  // namespace nearby
+}  // namespace location
+
+#endif  // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_WEBRTC_H_
diff --git a/chrome/services/sharing/nearby/platform_v2/webrtc_test.cc b/chrome/services/sharing/nearby/platform_v2/webrtc_test.cc
new file mode 100644
index 0000000..921a86c0
--- /dev/null
+++ b/chrome/services/sharing/nearby/platform_v2/webrtc_test.cc
@@ -0,0 +1,257 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/sharing/nearby/platform_v2/webrtc.h"
+
+#include "base/test/task_environment.h"
+#include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace location {
+namespace nearby {
+namespace chrome {
+namespace {
+
+class MockPeerConnectionObserver : public webrtc::PeerConnectionObserver {
+ public:
+  MOCK_METHOD(void, OnRenegotiationNeeded, (), (override));
+  MOCK_METHOD(void,
+              OnIceCandidate,
+              (const webrtc::IceCandidateInterface*),
+              (override));
+  MOCK_METHOD(void,
+              OnDataChannel,
+              (rtc::scoped_refptr<webrtc::DataChannelInterface>),
+              (override));
+  MOCK_METHOD(void,
+              OnIceGatheringChange,
+              (webrtc::PeerConnectionInterface::IceGatheringState new_state),
+              (override));
+  MOCK_METHOD(void,
+              OnSignalingChange,
+              (webrtc::PeerConnectionInterface::SignalingState new_state),
+              (override));
+};
+
+class WebRtcMediumTest : public ::testing::Test {
+ public:
+  WebRtcMediumTest()
+      : socket_manager_(mojo_impl_.socket_manager_.BindNewPipeAndPassRemote(),
+                        task_environment_.GetMainThreadTaskRunner()),
+        mdns_responder_(mojo_impl_.mdns_responder_.BindNewPipeAndPassRemote(),
+                        task_environment_.GetMainThreadTaskRunner()),
+        ice_config_fetcher_(
+            mojo_impl_.ice_config_fetcher_.BindNewPipeAndPassRemote()),
+        messenger_(mojo_impl_.messenger_.BindNewPipeAndPassRemote()),
+        webrtc_medium_(socket_manager_.get(),
+                       mdns_responder_.get(),
+                       ice_config_fetcher_.get(),
+                       messenger_.get()) {}
+
+  ~WebRtcMediumTest() override {
+    // Let libjingle threads finish.
+    base::RunLoop().RunUntilIdle();
+  }
+
+  WebRtcMedium& GetMedium() { return webrtc_medium_; }
+
+  testing::NiceMock<sharing::MockWebRtcDependencies>&
+  GetMockWebRtcDependencies() {
+    return mojo_impl_;
+  }
+
+ private:
+  base::test::SingleThreadTaskEnvironment task_environment_;
+  testing::NiceMock<sharing::MockWebRtcDependencies> mojo_impl_;
+
+  mojo::Remote<network::mojom::P2PSocketManager> socket_manager_;
+  mojo::Remote<network::mojom::MdnsResponder> mdns_responder_;
+  mojo::Remote<sharing::mojom::IceConfigFetcher> ice_config_fetcher_;
+  mojo::Remote<sharing::mojom::WebRtcSignalingMessenger> messenger_;
+
+  WebRtcMedium webrtc_medium_;
+};
+
+TEST_F(WebRtcMediumTest, CreatePeerConnection) {
+  MockPeerConnectionObserver observer;
+  ON_CALL(GetMockWebRtcDependencies(), GetIceServers(testing::_))
+      .WillByDefault(testing::Invoke(
+          [](sharing::MockWebRtcDependencies::GetIceServersCallback callback) {
+            std::move(callback).Run({});
+          }));
+  EXPECT_CALL(GetMockWebRtcDependencies(), GetIceServers(testing::_));
+
+  base::RunLoop loop;
+  GetMedium().CreatePeerConnection(
+      &observer, [&](rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc) {
+        ASSERT_TRUE(pc);
+        pc->Close();
+        loop.Quit();
+      });
+  loop.Run();
+}
+
+TEST_F(WebRtcMediumTest, GetSignalingMessenger) {
+  std::unique_ptr<api::WebRtcSignalingMessenger> messenger =
+      GetMedium().GetSignalingMessenger("from");
+  EXPECT_TRUE(messenger);
+}
+
+TEST_F(WebRtcMediumTest, GetMessengerAndSendMessage) {
+  ByteArray message("message");
+  const std::string from = "from";
+  const std::string to = "to";
+
+  base::RunLoop loop;
+  EXPECT_CALL(GetMockWebRtcDependencies(),
+              SendMessage(testing::Eq(from), testing::Eq(to),
+                          testing::Eq(std::string(message)), testing::_))
+      .WillOnce(testing::WithArg<3>(testing::Invoke(
+          [&](sharing::MockWebRtcDependencies::SendMessageCallback callback) {
+            std::move(callback).Run(/*success=*/true);
+            loop.Quit();
+          })));
+
+  std::unique_ptr<api::WebRtcSignalingMessenger> messenger =
+      GetMedium().GetSignalingMessenger(from);
+  EXPECT_TRUE(messenger);
+
+  EXPECT_TRUE(messenger->SendMessage(to, message));
+  loop.Run();
+}
+
+TEST_F(WebRtcMediumTest, GetMessengerAndStartReceivingMessages) {
+  ByteArray message("message");
+  const std::string from = "from";
+
+  EXPECT_CALL(GetMockWebRtcDependencies(),
+              StartReceivingMessages(testing::Eq(from), testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&message](
+              const std::string& self_id,
+              mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
+                  listener,
+              sharing::MockWebRtcDependencies::StartReceivingMessagesCallback
+                  callback) {
+            std::move(callback).Run(/*success=*/true);
+
+            mojo::Remote<sharing::mojom::IncomingMessagesListener> remote(
+                std::move(listener));
+            remote->OnMessage(std::string(message));
+          }));
+
+  std::unique_ptr<api::WebRtcSignalingMessenger> messenger =
+      GetMedium().GetSignalingMessenger(from);
+  EXPECT_TRUE(messenger);
+
+  base::RunLoop loop;
+  EXPECT_TRUE(messenger->StartReceivingMessages([&](const ByteArray& msg) {
+    EXPECT_EQ(message, msg);
+    loop.Quit();
+  }));
+  loop.Run();
+}
+
+TEST_F(WebRtcMediumTest, GetMessenger_StartAndStopReceivingMessages) {
+  ByteArray message("message");
+  const std::string from = "from";
+
+  mojo::Remote<sharing::mojom::IncomingMessagesListener> remote;
+  EXPECT_CALL(GetMockWebRtcDependencies(),
+              StartReceivingMessages(testing::Eq(from), testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&](const std::string& self_id,
+              mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
+                  listener,
+              sharing::MockWebRtcDependencies::StartReceivingMessagesCallback
+                  callback) {
+            std::move(callback).Run(/*success=*/true);
+
+            remote.Bind(std::move(listener));
+            remote->OnMessage(std::string(message));
+          }));
+
+  std::unique_ptr<api::WebRtcSignalingMessenger> messenger =
+      GetMedium().GetSignalingMessenger(from);
+  EXPECT_TRUE(messenger);
+
+  base::RunLoop loop;
+  EXPECT_TRUE(messenger->StartReceivingMessages([&](const ByteArray& msg) {
+    EXPECT_EQ(message, msg);
+    loop.Quit();
+  }));
+  loop.Run();
+
+  EXPECT_TRUE(remote.is_connected());
+
+  messenger->StopReceivingMessages();
+
+  // Run mojo disconnect handlers.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(remote.is_connected());
+}
+
+TEST_F(WebRtcMediumTest, GetMessengerAndStartReceivingMessagesTwice) {
+  ByteArray message("message");
+  const std::string from = "from";
+
+  EXPECT_CALL(GetMockWebRtcDependencies(),
+              StartReceivingMessages(testing::Eq(from), testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&message](
+              const std::string& self_id,
+              mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
+                  listener,
+              sharing::MockWebRtcDependencies::StartReceivingMessagesCallback
+                  callback) {
+            std::move(callback).Run(/*success=*/true);
+
+            mojo::Remote<sharing::mojom::IncomingMessagesListener> remote(
+                std::move(listener));
+            remote->OnMessage(std::string(message));
+          }));
+
+  std::unique_ptr<api::WebRtcSignalingMessenger> messenger =
+      GetMedium().GetSignalingMessenger(from);
+  EXPECT_TRUE(messenger);
+
+  base::RunLoop loop;
+  EXPECT_TRUE(messenger->StartReceivingMessages([&](const ByteArray& msg) {
+    EXPECT_EQ(message, msg);
+    loop.Quit();
+  }));
+  loop.Run();
+
+  message = ByteArray("message_2");
+  EXPECT_CALL(GetMockWebRtcDependencies(),
+              StartReceivingMessages(testing::Eq(from), testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&message](
+              const std::string& self_id,
+              mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
+                  listener,
+              sharing::MockWebRtcDependencies::StartReceivingMessagesCallback
+                  callback) {
+            std::move(callback).Run(/*success=*/true);
+
+            mojo::Remote<sharing::mojom::IncomingMessagesListener> remote(
+                std::move(listener));
+            remote->OnMessage(std::string(message));
+          }));
+
+  base::RunLoop loop_2;
+  EXPECT_TRUE(messenger->StartReceivingMessages([&](const ByteArray& msg) {
+    EXPECT_EQ(message, msg);
+    loop_2.Quit();
+  }));
+  loop_2.Run();
+}
+
+}  // namespace
+}  // namespace chrome
+}  // namespace nearby
+}  // namespace location
diff --git a/chrome/services/sharing/nearby/test_support/BUILD.gn b/chrome/services/sharing/nearby/test_support/BUILD.gn
index 7252d46..45e3152 100644
--- a/chrome/services/sharing/nearby/test_support/BUILD.gn
+++ b/chrome/services/sharing/nearby/test_support/BUILD.gn
@@ -8,8 +8,8 @@
   sources = [
     "mock_bluetooth_adapter.cc",
     "mock_bluetooth_adapter.h",
-    "mock_webrtc_signaling_messenger.cc",
-    "mock_webrtc_signaling_messenger.h",
+    "mock_webrtc_dependencies.cc",
+    "mock_webrtc_dependencies.h",
   ]
 
   deps = [
diff --git a/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.cc b/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.cc
new file mode 100644
index 0000000..7ff30b7
--- /dev/null
+++ b/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.cc
@@ -0,0 +1,12 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
+
+namespace sharing {
+
+MockWebRtcDependencies::MockWebRtcDependencies() = default;
+MockWebRtcDependencies::~MockWebRtcDependencies() = default;
+
+}  // namespace sharing
diff --git a/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h b/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h
new file mode 100644
index 0000000..fad543a
--- /dev/null
+++ b/chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_DEPENDENCIES_H_
+#define CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_DEPENDENCIES_H_
+
+#include "chrome/services/sharing/public/mojom/webrtc.mojom.h"
+#include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "services/network/public/mojom/mdns_responder.mojom.h"
+#include "services/network/public/mojom/p2p.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace sharing {
+
+// Mimics browser process and network service implementations.
+class MockWebRtcDependencies : public network::mojom::P2PSocketManager,
+                               public network::mojom::MdnsResponder,
+                               public sharing::mojom::IceConfigFetcher,
+                               public sharing::mojom::WebRtcSignalingMessenger {
+ public:
+  MockWebRtcDependencies();
+  ~MockWebRtcDependencies() override;
+
+  // network::mojom::P2PSocketManager overrides:
+  MOCK_METHOD(void,
+              StartNetworkNotifications,
+              (mojo::PendingRemote<network::mojom::P2PNetworkNotificationClient>
+                   client),
+              (override));
+  MOCK_METHOD(
+      void,
+      GetHostAddress,
+      (const std::string& host_name,
+       bool enable_mdns,
+       network::mojom::P2PSocketManager::GetHostAddressCallback callback),
+      (override));
+  MOCK_METHOD(void,
+              CreateSocket,
+              (network::P2PSocketType type,
+               const net::IPEndPoint& local_address,
+               const network::P2PPortRange& port_range,
+               const network::P2PHostAndIPEndPoint& remote_address,
+               mojo::PendingRemote<network::mojom::P2PSocketClient> client,
+               mojo::PendingReceiver<network::mojom::P2PSocket> receiver),
+              (override));
+
+  // network::mojom::MdnsResponder overrides:
+  MOCK_METHOD(
+      void,
+      CreateNameForAddress,
+      (const net::IPAddress& address,
+       network::mojom::MdnsResponder::CreateNameForAddressCallback callback),
+      (override));
+  MOCK_METHOD(
+      void,
+      RemoveNameForAddress,
+      (const net::IPAddress& address,
+       network::mojom::MdnsResponder::RemoveNameForAddressCallback callback),
+      (override));
+
+  // sharing::mojom::IceConfigFetcher overrides:
+  MOCK_METHOD(void,
+              GetIceServers,
+              (GetIceServersCallback callback),
+              (override));
+
+  // sharing::mojom::WebRtcSignalingMessenger overrides:
+  MOCK_METHOD(void,
+              SendMessage,
+              (const std::string& self_id,
+               const std::string& peer_id,
+               const std::string& message,
+               SendMessageCallback callback),
+              (override));
+
+  MOCK_METHOD(void,
+              StartReceivingMessages,
+              (const std::string& self_id,
+               mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
+                   incoming_messages_listener,
+               StartReceivingMessagesCallback callback),
+              (override));
+  MOCK_METHOD(void, StopReceivingMessages, (), (override));
+
+  mojo::Receiver<network::mojom::P2PSocketManager> socket_manager_{this};
+  mojo::Receiver<network::mojom::MdnsResponder> mdns_responder_{this};
+  mojo::Receiver<sharing::mojom::IceConfigFetcher> ice_config_fetcher_{this};
+  mojo::Receiver<sharing::mojom::WebRtcSignalingMessenger> messenger_{this};
+};
+
+}  // namespace sharing
+
+#endif  // CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_DEPENDENCIES_H_
diff --git a/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.cc b/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.cc
deleted file mode 100644
index 58bb6d4..0000000
--- a/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.h"
-
-namespace sharing {
-
-MockWebRtcSignalingMessenger::MockWebRtcSignalingMessenger() = default;
-
-MockWebRtcSignalingMessenger::~MockWebRtcSignalingMessenger() = default;
-
-void MockWebRtcSignalingMessenger::SendMessage(const std::string& self_id,
-                                               const std::string& peer_id,
-                                               const std::string& message,
-                                               SendMessageCallback callback) {}
-
-void MockWebRtcSignalingMessenger::StartReceivingMessages(
-    const std::string& self_id,
-    mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
-        incoming_messages_listener,
-    StartReceivingMessagesCallback callback) {}
-
-void MockWebRtcSignalingMessenger::StopReceivingMessages() {}
-
-}  // namespace sharing
diff --git a/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.h b/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.h
deleted file mode 100644
index e092afd..0000000
--- a/chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_SIGNALING_MESSENGER_H_
-#define CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_SIGNALING_MESSENGER_H_
-
-#include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-
-namespace sharing {
-
-class MockWebRtcSignalingMessenger : public mojom::WebRtcSignalingMessenger {
- public:
-  MockWebRtcSignalingMessenger();
-  ~MockWebRtcSignalingMessenger() override;
-
-  // sharing::mojom::WebRtcSignalingMessenger:
-  void SendMessage(const std::string& self_id,
-                   const std::string& peer_id,
-                   const std::string& message,
-                   SendMessageCallback callback) override;
-  void StartReceivingMessages(
-      const std::string& self_id,
-      mojo::PendingRemote<sharing::mojom::IncomingMessagesListener>
-          incoming_messages_listener,
-      StartReceivingMessagesCallback callback) override;
-  void StopReceivingMessages() override;
-
-  mojo::Receiver<mojom::WebRtcSignalingMessenger> messenger{this};
-};
-
-}  // namespace sharing
-
-#endif  // CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_MOCK_WEBRTC_SIGNALING_MESSENGER_H_
diff --git a/chrome/services/sharing/nearby/webrtc/OWNERS b/chrome/services/sharing/nearby/webrtc/OWNERS
deleted file mode 100644
index 4ef4e54..0000000
--- a/chrome/services/sharing/nearby/webrtc/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=file://ipc/SECURITY_OWNERS
\ No newline at end of file
diff --git a/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.cc b/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.cc
deleted file mode 100644
index 01d2676..0000000
--- a/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/services/sharing/nearby/webrtc/incoming_messages_listener.h"
-
-namespace sharing {
-
-IncomingMessagesListener::IncomingMessagesListener(
-    base::RepeatingCallback<void(const std::string& message)> listener)
-    : listener_(listener) {}
-IncomingMessagesListener::~IncomingMessagesListener() = default;
-
-void IncomingMessagesListener::OnMessage(const std::string& message) {
-  listener_.Run(message);
-}
-
-}  // namespace sharing
diff --git a/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.h b/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.h
deleted file mode 100644
index ead2e7b2..0000000
--- a/chrome/services/sharing/nearby/webrtc/incoming_messages_listener.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_SERVICES_SHARING_NEARBY_WEBRTC_INCOMING_MESSAGES_LISTENER_H_
-#define CHROME_SERVICES_SHARING_NEARBY_WEBRTC_INCOMING_MESSAGES_LISTENER_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom.h"
-
-namespace sharing {
-
-class IncomingMessagesListener : public mojom::IncomingMessagesListener {
- public:
-  explicit IncomingMessagesListener(
-      base::RepeatingCallback<void(const std::string& message)> listener);
-  ~IncomingMessagesListener() override;
-
-  // mojom::IncomingMessagesListener:
-  void OnMessage(const std::string& message) override;
-
- private:
-  base::RepeatingCallback<void(const std::string& message)> listener_;
-};
-
-}  // namespace sharing
-
-#endif  // CHROME_SERVICES_SHARING_NEARBY_WEBRTC_INCOMING_MESSAGES_LISTENER_H_
\ No newline at end of file
diff --git a/chrome/services/sharing/public/mojom/nearby_connections.mojom b/chrome/services/sharing/public/mojom/nearby_connections.mojom
index 017aff5..0594427 100644
--- a/chrome/services/sharing/public/mojom/nearby_connections.mojom
+++ b/chrome/services/sharing/public/mojom/nearby_connections.mojom
@@ -6,7 +6,23 @@
 
 import "chrome/services/sharing/public/mojom/nearby_connections_types.mojom";
 import "chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom";
+import "chrome/services/sharing/public/mojom/webrtc.mojom";
 import "device/bluetooth/public/mojom/adapter.mojom";
+import "services/network/public/mojom/p2p.mojom";
+import "services/network/public/mojom/mdns_responder.mojom";
+
+// Collection of dependencies required by WebRTC medium.
+struct WebRtcDependencies {
+  // Used to allocate p2p sockets via Chromium's network service.
+  pending_remote<network.mojom.P2PSocketManager> socket_manager;
+  // Used to implement mDNS responder interface in WebRTC via MdnsResponder
+  // service in Chromium.
+  pending_remote<network.mojom.MdnsResponder> mdns_responder;
+  // Used to fetch STUN and TURN servers for establishing WebRTC connection.
+  pending_remote<sharing.mojom.IceConfigFetcher> ice_config_fetcher;
+  // Used to send and receive SDP messages for establishing WebRTC connection.
+  pending_remote<sharing.mojom.WebRtcSignalingMessenger> messenger;
+};
 
 // Main interface to control the NearbyConnections library. Implemented in a
 // sandboxed process. This interface is used by the browser process to connect
@@ -20,6 +36,5 @@
 struct NearbyConnectionsDependencies {
   pending_remote<bluetooth.mojom.Adapter>? bluetooth_adapter;
 
-  pending_remote<sharing.mojom.WebRtcSignalingMessenger>
-      webrtc_signaling_messenger;
+  WebRtcDependencies webrtc_dependencies;
 };
diff --git a/chrome/services/sharing/public/mojom/webrtc.mojom b/chrome/services/sharing/public/mojom/webrtc.mojom
index 63852e8..1124521d 100644
--- a/chrome/services/sharing/public/mojom/webrtc.mojom
+++ b/chrome/services/sharing/public/mojom/webrtc.mojom
@@ -35,6 +35,13 @@
   kError,
 };
 
+// Used to fetch ice servers for WebRtc communication. Implemented in browser
+// process.
+interface IceConfigFetcher {
+  // Returns a list of ice servers for WebRtc communication.
+  GetIceServers() => (array<IceServer> ice_servers);
+};
+
 // Signalling sender interface used to exchange offer / answer pairs and a list
 // of ICE candidates OOB. Implemented in the browser process.
 interface SignallingSender {
@@ -64,8 +71,8 @@
   OnMessageReceived(array<uint8> message);
 };
 
-// Sharing connection interface used to send messages via WebRTC. Implemented in
-// a sandboxed utility process.
+// Sharing connection interface used to send messages via WebRTC. Implemented
+// in a sandboxed utility process.
 interface SharingWebRtcConnection {
   // Sends a message to the remove via WebRTC and returns the result.
   SendMessage(array<uint8> message) => (SendMessageResult result);
diff --git a/chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom b/chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom
index 00e00b5..95780e0e 100644
--- a/chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom
+++ b/chrome/services/sharing/public/mojom/webrtc_signaling_messenger.mojom
@@ -12,15 +12,19 @@
 
 // Runs in browser process and is used by the nearby library to send and
 // receive messages.
+// TODO(crbug.com/1106387) : Update Nearby library to use async callbacks
+// instead of blocking calls.
 interface WebRtcSignalingMessenger {
   // Sends a signaling message |message| to |peer_id|.
+  [Sync]
   SendMessage(string self_id, string peer_id, string message)
     => (bool success);
 
   // Registers |listener| to start receiving messages from other devices.
+  [Sync]
   StartReceivingMessages(string self_id,
     pending_remote<IncomingMessagesListener> listener) => (bool success);
 
   // Unregisters listener and stops receiving messages from other devices.
   StopReceivingMessages();
-};
\ No newline at end of file
+};
diff --git a/chrome/services/sharing/sharing_impl_unittest.cc b/chrome/services/sharing/sharing_impl_unittest.cc
index 2ce37e3..4ce398c 100644
--- a/chrome/services/sharing/sharing_impl_unittest.cc
+++ b/chrome/services/sharing/sharing_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/test/task_environment.h"
 #include "chrome/services/sharing/nearby/nearby_connections.h"
 #include "chrome/services/sharing/nearby/test_support/mock_bluetooth_adapter.h"
-#include "chrome/services/sharing/nearby/test_support/mock_webrtc_signaling_messenger.h"
+#include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
 #include "chrome/services/sharing/public/mojom/nearby_decoder.mojom.h"
 #include "chrome/services/sharing/webrtc/test/mock_sharing_connection_host.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -53,13 +53,20 @@
 
   mojo::Remote<NearbyConnectionsMojom> CreateNearbyConnections(
       mojo::PendingRemote<bluetooth::mojom::Adapter> bluetooth_adapter,
+      mojo::PendingRemote<network::mojom::P2PSocketManager> socket_manager,
+      mojo::PendingRemote<network::mojom::MdnsResponder> mdns_responder,
+      mojo::PendingRemote<sharing::mojom::IceConfigFetcher> ice_config_fetcher,
       mojo::PendingRemote<sharing::mojom::WebRtcSignalingMessenger>
           webrtc_signaling_messenger) {
     mojo::Remote<NearbyConnectionsMojom> connections;
+    auto webrtc_dependencies =
+        location::nearby::connections::mojom::WebRtcDependencies::New(
+            std::move(socket_manager), std::move(mdns_responder),
+            std::move(ice_config_fetcher),
+            std::move(webrtc_signaling_messenger));
     auto dependencies =
         location::nearby::connections::mojom::NearbyConnectionsDependencies::
-            New(std::move(bluetooth_adapter),
-                std::move(webrtc_signaling_messenger));
+            New(std::move(bluetooth_adapter), std::move(webrtc_dependencies));
     base::RunLoop run_loop;
     service()->CreateNearbyConnections(
         std::move(dependencies),
@@ -122,28 +129,37 @@
 
 TEST_F(SharingImplTest, NearbyConnections_Create) {
   bluetooth::MockBluetoothAdapter bluetooth_adapter;
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
   mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
       bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
-      webrtc_signaling_messenger.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
 
   EXPECT_TRUE(connections.is_connected());
 }
 
 TEST_F(SharingImplTest, NearbyConnections_CreateMultiple) {
   bluetooth::MockBluetoothAdapter bluetooth_adapter_1;
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger_1;
+  sharing::MockWebRtcDependencies webrtc_dependencies_1;
   mojo::Remote<NearbyConnectionsMojom> connections_1 = CreateNearbyConnections(
       bluetooth_adapter_1.adapter.BindNewPipeAndPassRemote(),
-      webrtc_signaling_messenger_1.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies_1.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_1.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_1.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_1.messenger_.BindNewPipeAndPassRemote());
   EXPECT_TRUE(connections_1.is_connected());
 
   // Calling CreateNearbyConnections() again should disconnect the old instance.
   bluetooth::MockBluetoothAdapter bluetooth_adapter_2;
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger_2;
+  sharing::MockWebRtcDependencies webrtc_dependencies_2;
   mojo::Remote<NearbyConnectionsMojom> connections_2 = CreateNearbyConnections(
       bluetooth_adapter_2.adapter.BindNewPipeAndPassRemote(),
-      webrtc_signaling_messenger_2.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies_2.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_2.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_2.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies_2.messenger_.BindNewPipeAndPassRemote());
 
   // Run mojo disconnect handlers.
   base::RunLoop().RunUntilIdle();
@@ -154,10 +170,13 @@
 
 TEST_F(SharingImplTest, NearbyConnections_BluetoothDisconnects) {
   bluetooth::MockBluetoothAdapter bluetooth_adapter;
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
   mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
       bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
-      webrtc_signaling_messenger.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
   EXPECT_TRUE(connections.is_connected());
 
   // Disconnecting the |bluetooth_adapter| interface should also
@@ -172,15 +191,81 @@
 
 TEST_F(SharingImplTest, NearbyConnections_WebRtcSignalingMessengerDisconnects) {
   bluetooth::MockBluetoothAdapter bluetooth_adapter;
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
   mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
       bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
-      webrtc_signaling_messenger.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
   EXPECT_TRUE(connections.is_connected());
 
-  // Disconnecting the |webrtc_signaling_messenger| interface should also
+  // Disconnecting the |webrtc_dependencies.messenger_| interface should also
   // disconnect and destroy the |connections| interface.
-  webrtc_signaling_messenger.messenger.reset();
+  webrtc_dependencies.messenger_.reset();
+
+  // Run mojo disconnect handlers.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(connections.is_connected());
+}
+
+TEST_F(SharingImplTest, NearbyConnections_WebRtcMdnsResponderDisconnects) {
+  bluetooth::MockBluetoothAdapter bluetooth_adapter;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
+  mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
+      bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
+  EXPECT_TRUE(connections.is_connected());
+
+  // Disconnecting the |webrtc_dependencies.mdns_responder_| interface should
+  // also disconnect and destroy the |connections| interface.
+  webrtc_dependencies.mdns_responder_.reset();
+
+  // Run mojo disconnect handlers.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(connections.is_connected());
+}
+
+TEST_F(SharingImplTest, NearbyConnections_WebRtcP2PSocketManagerDisconnects) {
+  bluetooth::MockBluetoothAdapter bluetooth_adapter;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
+  mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
+      bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
+  EXPECT_TRUE(connections.is_connected());
+
+  // Disconnecting the |webrtc_dependencies.socket_manager_| interface should
+  // also disconnect and destroy the |connections| interface.
+  webrtc_dependencies.socket_manager_.reset();
+
+  // Run mojo disconnect handlers.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(connections.is_connected());
+}
+
+TEST_F(SharingImplTest, NearbyConnections_WebRtcIceConfigFetcherDisconnects) {
+  bluetooth::MockBluetoothAdapter bluetooth_adapter;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
+  mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
+      bluetooth_adapter.adapter.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
+  EXPECT_TRUE(connections.is_connected());
+
+  // Disconnecting the |webrtc_dependencies.ice_config_fetcher_| interface
+  // should also disconnect and destroy the |connections| interface.
+  webrtc_dependencies.ice_config_fetcher_.reset();
 
   // Run mojo disconnect handlers.
   base::RunLoop().RunUntilIdle();
@@ -189,10 +274,13 @@
 }
 
 TEST_F(SharingImplTest, NearbyConnections_NullBluetoothAdapter) {
-  sharing::MockWebRtcSignalingMessenger webrtc_signaling_messenger;
+  sharing::MockWebRtcDependencies webrtc_dependencies;
   mojo::Remote<NearbyConnectionsMojom> connections = CreateNearbyConnections(
       mojo::NullRemote(),
-      webrtc_signaling_messenger.messenger.BindNewPipeAndPassRemote());
+      webrtc_dependencies.socket_manager_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.mdns_responder_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.ice_config_fetcher_.BindNewPipeAndPassRemote(),
+      webrtc_dependencies.messenger_.BindNewPipeAndPassRemote());
   EXPECT_TRUE(connections.is_connected());
 }
 
diff --git a/chrome/services/sharing/webrtc/BUILD.gn b/chrome/services/sharing/webrtc/BUILD.gn
new file mode 100644
index 0000000..8186931
--- /dev/null
+++ b/chrome/services/sharing/webrtc/BUILD.gn
@@ -0,0 +1,55 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("webrtc") {
+  sources = [
+    "ipc_network_manager.cc",
+    "ipc_network_manager.h",
+    "ipc_packet_socket_factory.cc",
+    "ipc_packet_socket_factory.h",
+    "mdns_responder_adapter.cc",
+    "mdns_responder_adapter.h",
+    "p2p_async_address_resolver.cc",
+    "p2p_async_address_resolver.h",
+    "p2p_port_allocator.cc",
+    "p2p_port_allocator.h",
+    "p2p_socket_client.cc",
+    "p2p_socket_client.h",
+    "p2p_socket_client_delegate.h",
+    "sharing_webrtc_connection.cc",
+    "sharing_webrtc_connection.h",
+    "sharing_webrtc_timing_recorder.cc",
+    "sharing_webrtc_timing_recorder.h",
+  ]
+
+  deps = [
+    "//jingle:webrtc_glue",
+    "//third_party/webrtc_overrides:webrtc_component",
+  ]
+
+  public_deps = [
+    "//base",
+    "//chrome/services/sharing/public/cpp",
+    "//chrome/services/sharing/public/mojom",
+    "//mojo/public/cpp/bindings",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "sharing_webrtc_connection_integration_test.cc",
+    "sharing_webrtc_connection_unittest.cc",
+  ]
+
+  deps = [
+    ":webrtc",
+    "test",
+    "//base/test:test_support",
+    "//jingle:webrtc_glue",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/services/sharing/webrtc/test/BUILD.gn b/chrome/services/sharing/webrtc/test/BUILD.gn
new file mode 100644
index 0000000..2800105e
--- /dev/null
+++ b/chrome/services/sharing/webrtc/test/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test") {
+  testonly = true
+
+  sources = [
+    "mock_sharing_connection_host.cc",
+    "mock_sharing_connection_host.h",
+  ]
+
+  deps = [
+    "//base/test:test_support",
+    "//chrome/services/sharing/public/mojom",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index cfac0055..58d2b230 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4349,6 +4349,7 @@
       "//chrome/services/sharing/nearby/decoder:unit_tests",
       "//chrome/services/sharing/nearby/platform_v2:unit_tests",
       "//chrome/services/sharing/public/cpp:unit_tests",
+      "//chrome/services/sharing/webrtc:unit_tests",
       "//chrome/services/speech:unit_tests",
       "//components/chrome_cleaner/test:test_name_helper",
       "//components/enterprise",
diff --git a/chrome/test/chromedriver/chrome/adb_impl.cc b/chrome/test/chromedriver/chrome/adb_impl.cc
index 73c0aef..a51a2ed 100644
--- a/chrome/test/chromedriver/chrome/adb_impl.cc
+++ b/chrome/test/chromedriver/chrome/adb_impl.cc
@@ -13,7 +13,6 @@
 #include "base/json/string_escape.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -21,6 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/time/time.h"
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/constants/version.h"
@@ -84,7 +84,7 @@
 void ExecuteCommandOnIOThread(
     const std::string& command, scoped_refptr<ResponseBuffer> response_buffer,
     int port) {
-  CHECK(base::MessageLoopCurrentForIO::IsSet());
+  CHECK(base::CurrentIOThread::IsSet());
   AdbClientSocket::AdbQuery(port, command,
       base::Bind(&ResponseBuffer::OnResponse, response_buffer));
 }
@@ -94,7 +94,7 @@
                         const std::string& content,
                         scoped_refptr<ResponseBuffer> response_buffer,
                         int port) {
-  CHECK(base::MessageLoopCurrentForIO::IsSet());
+  CHECK(base::CurrentIOThread::IsSet());
   AdbClientSocket::SendFile(
       port, device_serial, filename, content,
       base::Bind(&ResponseBuffer::OnResponse, response_buffer));
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index 2b59dbc..4bd8b73 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -15,12 +15,12 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/test/chromedriver/capabilities.h"
diff --git a/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js
new file mode 100644
index 0000000..d523168
--- /dev/null
+++ b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_app.js';
+
+import {DiceWebSigninInterceptBrowserProxyImpl} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js';
+
+import {isVisible} from '../test_util.m.js';
+
+import {TestDiceWebSigninInterceptBrowserProxy} from './test_dice_web_signin_intercept_browser_proxy.js';
+
+suite('DiceWebSigninInterceptTest', function() {
+  /** @type {DiceWebSigninInterceptAppElement} */
+  let app;
+
+  /** @type {TestDiceWebSigninInterceptBrowserProxy} */
+  let browserProxy;
+
+  setup(function() {
+    browserProxy = new TestDiceWebSigninInterceptBrowserProxy();
+    DiceWebSigninInterceptBrowserProxyImpl.instance_ = browserProxy;
+    document.body.innerHTML = '';
+    app = document.createElement('dice-web-signin-intercept-app');
+    document.body.append(app);
+  });
+
+  test('ClickAccept', function() {
+    assertTrue(isVisible(app.$.acceptButton));
+    app.$.acceptButton.click();
+    return browserProxy.whenCalled('accept');
+  });
+
+  test('ClickCancel', function() {
+    assertTrue(isVisible(app.$.cancelButton));
+    app.$.cancelButton.click();
+    return browserProxy.whenCalled('cancel');
+  });
+});
diff --git a/chrome/test/data/webui/signin/signin_browsertest.js b/chrome/test/data/webui/signin/signin_browsertest.js
index 0ef2e8a..0e89203 100644
--- a/chrome/test/data/webui/signin/signin_browsertest.js
+++ b/chrome/test/data/webui/signin/signin_browsertest.js
@@ -66,3 +66,20 @@
 TEST_F('SigninReauthTest', 'Dialog', function() {
   mocha.run();
 });
+
+/**
+ * Test fixture for
+ * chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept.html.
+ * This has to be declared as a variable for TEST_F to find it correctly.
+ */
+// eslint-disable-next-line no-var
+var DiceWebSigninInterceptTest = class extends SigninBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://signin-dice-web-intercept/test_loader.html?module=signin/dice_web_signin_intercept_test.js';
+  }
+};
+
+TEST_F('DiceWebSigninInterceptTest', 'Bubble', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js
new file mode 100644
index 0000000..7ad9cdf
--- /dev/null
+++ b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
+
+/** @implements {DiceWebSigninInterceptBrowserProxy} */
+export class TestDiceWebSigninInterceptBrowserProxy extends TestBrowserProxy {
+  constructor() {
+    super(['accept', 'cancel']);
+  }
+
+  /** @override */
+  accept() {
+    this.methodCalled('accept');
+  }
+
+  /** @override */
+  cancel() {
+    this.methodCalled('cancel');
+  }
+}
diff --git a/chromecast/base/static_sequence/static_sequence.cc b/chromecast/base/static_sequence/static_sequence.cc
index 0d30ef8..88e491d6 100644
--- a/chromecast/base/static_sequence/static_sequence.cc
+++ b/chromecast/base/static_sequence/static_sequence.cc
@@ -22,7 +22,7 @@
 const scoped_refptr<base::SequencedTaskRunner>& StaticTaskRunnerHolder::Get() {
   if (!initialized_) {
     task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(traits_);
-    base::MessageLoopCurrent::Get().AddDestructionObserver(this);
+    base::CurrentThread::Get().AddDestructionObserver(this);
     initialized_ = true;
   }
   return task_runner_;
diff --git a/chromecast/base/static_sequence/static_sequence.h b/chromecast/base/static_sequence/static_sequence.h
index 2830943..56d1562 100644
--- a/chromecast/base/static_sequence/static_sequence.h
+++ b/chromecast/base/static_sequence/static_sequence.h
@@ -11,7 +11,7 @@
 #include "base/callback_forward.h"
 #include "base/location.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/task/task_traits.h"
 
 // Allows sequences to be defined at compile time so that objects can opt into
@@ -65,8 +65,7 @@
 // Provides a TaskRunner and can persist after the message loop is destroyed,
 // which is useful if e.g. a StaticTaskRunnerHolder outlives a
 // base::test::TaskEnvironment in tests. Only usable by StaticSequence.
-class StaticTaskRunnerHolder
-    : public base::MessageLoopCurrent::DestructionObserver {
+class StaticTaskRunnerHolder : public base::CurrentThread::DestructionObserver {
  public:
   ~StaticTaskRunnerHolder() override;
 
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 83ecd27..087048a 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -16,12 +16,12 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chromecast/external_mojo/public/cpp/external_mojo_broker.cc b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
index a2145d5e..c47d0272 100644
--- a/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
+++ b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
@@ -16,9 +16,9 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/optional.h"
+#include "base/task/current_thread.h"
 #include "base/token.h"
 #include "base/trace_event/trace_event.h"
 #include "chromecast/external_mojo/public/cpp/common.h"
@@ -358,7 +358,7 @@
         listen_handle_(std::move(listen_handle)),
         watch_controller_(FROM_HERE) {
     DCHECK(listen_handle_.is_valid());
-    base::MessageLoopCurrentForIO::Get().WatchFileDescriptor(
+    base::CurrentIOThread::Get().WatchFileDescriptor(
         listen_handle_.GetFD().get(), true /* persistent */,
         base::MessagePumpForIO::WATCH_READ, &watch_controller_, this);
   }
diff --git a/chromecast/media/cma/backend/alsa/alsa_volume_control.cc b/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
index 7546967d..b7965da 100644
--- a/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
+++ b/chromecast/media/cma/backend/alsa/alsa_volume_control.cc
@@ -11,8 +11,8 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_split.h"
+#include "base/task/current_thread.h"
 #include "chromecast/base/chromecast_switches.h"
 #include "media/base/media_switches.h"
 
@@ -365,7 +365,7 @@
   for (int i = 0; i < num_fds; ++i) {
     auto watcher =
         std::make_unique<base::MessagePumpForIO::FdWatchController>(FROM_HERE);
-    base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
         pfds[i].fd, true /* persistent */, base::MessagePumpForIO::WATCH_READ,
         watcher.get(), this);
     file_descriptor_watchers_.push_back(std::move(watcher));
diff --git a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
index 872aa7e..b212bd8 100644
--- a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
+++ b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -206,7 +206,7 @@
 
 void BalancedMediaTaskRunnerTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
-  if (base::MessageLoopCurrent::Get())
+  if (base::CurrentThread::Get())
     base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
diff --git a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
index c0fab0bd..2f19792 100644
--- a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
+++ b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
@@ -13,10 +13,10 @@
 
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -108,7 +108,7 @@
 
 void BufferingFrameProviderTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
-  if (base::MessageLoopCurrent::Get())
+  if (base::CurrentThread::Get())
     base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
diff --git a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
index c62d4cb..3efc1e5 100644
--- a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
+++ b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -102,7 +102,7 @@
 
 void DemuxerStreamAdapterTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
-  if (base::MessageLoopCurrent::Get())
+  if (base::CurrentThread::Get())
     base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
diff --git a/chromecast/tracing/tracing_service_main.cc b/chromecast/tracing/tracing_service_main.cc
index 9af57694..4b90500 100644
--- a/chromecast/tracing/tracing_service_main.cc
+++ b/chromecast/tracing/tracing_service_main.cc
@@ -15,7 +15,6 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/posix/eintr_wrapper.h"
@@ -23,6 +22,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -100,7 +100,7 @@
   ~TraceCopyTask() override {}
 
   void Start() {
-    base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
         out_fd_.get(), true /* persistent */,
         base::MessagePumpForIO::WATCH_WRITE, &out_watcher_, this);
   }
@@ -185,7 +185,7 @@
   ~TraceConnection() override {}
 
   void Init() {
-    base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
         connection_fd_.get(), true /* persistent */,
         base::MessagePumpForIO::WATCH_READ, &connection_watcher_, this);
   }
@@ -347,7 +347,7 @@
     if (!server_socket_.is_valid())
       return false;
 
-    base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
         server_socket_.get(), true /* persistent */,
         base::MessagePumpForIO::WATCH_READ, &server_socket_watcher_, this);
 
diff --git a/chromeos/attestation/BUILD.gn b/chromeos/attestation/BUILD.gn
index 6ae6f961..ab523a0 100644
--- a/chromeos/attestation/BUILD.gn
+++ b/chromeos/attestation/BUILD.gn
@@ -35,10 +35,13 @@
   deps = [
     "//base/test:test_support",
     "//chromeos/dbus/attestation:attestation_proto",
+    "//chromeos/dbus/constants:constants",
     "//components/account_id",
     "//testing/gmock",
   ]
   sources = [
+    "fake_attestation_flow.cc",
+    "fake_attestation_flow.h",
     "mock_attestation_flow.cc",
     "mock_attestation_flow.h",
   ]
diff --git a/chromeos/attestation/fake_attestation_flow.cc b/chromeos/attestation/fake_attestation_flow.cc
new file mode 100644
index 0000000..8eead403
--- /dev/null
+++ b/chromeos/attestation/fake_attestation_flow.cc
@@ -0,0 +1,49 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/attestation/fake_attestation_flow.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/dbus/constants/attestation_constants.h"
+#include "components/account_id/account_id.h"
+
+namespace chromeos {
+namespace attestation {
+
+namespace {
+
+constexpr char kFakeCert[] = "cert";
+
+}  // namespace
+
+// This constructor passes |nullptr|s to the base class
+// |AttestationFlow| because we don't use cryptohome client and server
+// proxy in |AttestationFlowIntegrated|.
+//
+// TOOD(b/158955123): Remove this transitional state along with the removal of
+// |AttestationFlow|.
+FakeAttestationFlow::FakeAttestationFlow()
+    : AttestationFlow(nullptr, nullptr, nullptr) {}
+
+FakeAttestationFlow::~FakeAttestationFlow() = default;
+
+void FakeAttestationFlow::GetCertificate(
+    AttestationCertificateProfile /*certificate_profile*/,
+    const AccountId& /*account_id*/,
+    const std::string& /*request_origin*/,
+    bool /*force_new_key*/,
+    const std::string& /*key_name*/,
+    CertificateCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback),
+                     AttestationStatus::ATTESTATION_SUCCESS, kFakeCert));
+}
+
+}  // namespace attestation
+}  // namespace chromeos
diff --git a/chromeos/attestation/fake_attestation_flow.h b/chromeos/attestation/fake_attestation_flow.h
new file mode 100644
index 0000000..467c833
--- /dev/null
+++ b/chromeos/attestation/fake_attestation_flow.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_ATTESTATION_FAKE_ATTESTATION_FLOW_H_
+#define CHROMEOS_ATTESTATION_FAKE_ATTESTATION_FLOW_H_
+
+#include <string>
+
+#include "chromeos/attestation/attestation_flow.h"
+
+class AccountId;
+
+namespace chromeos {
+namespace attestation {
+
+// This fake class always returns a fake certificate.
+class FakeAttestationFlow : public AttestationFlow {
+ public:
+  FakeAttestationFlow();
+  ~FakeAttestationFlow() override;
+
+  void GetCertificate(AttestationCertificateProfile certificate_profile,
+                      const AccountId& account_id,
+                      const std::string& request_origin,
+                      bool force_new_key,
+                      const std::string& key_name,
+                      CertificateCallback callback) override;
+};
+
+}  // namespace attestation
+}  // namespace chromeos
+
+#endif  // CHROMEOS_ATTESTATION_FAKE_ATTESTATION_FLOW_H_
diff --git a/chromeos/components/camera_app_ui/resources/BUILD.gn b/chromeos/components/camera_app_ui/resources/BUILD.gn
index 1edb57d..8dba78c 100644
--- a/chromeos/components/camera_app_ui/resources/BUILD.gn
+++ b/chromeos/components/camera_app_ui/resources/BUILD.gn
@@ -12,9 +12,7 @@
   # According to crbug.com/855747, we should list all the files we want to copy
   # rather than list only the folders to avoid potential building issue and ease
   # the difficulty to diagnose.
-  deps = [
-    "src/strings:camera_strings",
-  ]
+  deps = [ "src/strings:camera_strings" ]
 
   data_deps = [
     ":chrome_camera_app_base",
@@ -203,6 +201,7 @@
 copy("chrome_camera_app_sounds") {
   sources = [
     "src/sounds/record_end.ogg",
+    "src/sounds/record_pause.ogg",
     "src/sounds/record_start.ogg",
     "src/sounds/shutter.ogg",
     "src/sounds/tick_final.ogg",
diff --git a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
index c866160..7ef6a6c 100644
--- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
+++ b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
@@ -116,6 +116,7 @@
       <!-- TODO(crbug.com/980846): Add FFMpeg library here with comrpession enabled once video recording is ready to test in SWA -->
 
       <include name="IDR_CAMERA_RECORD_END_OGG" file="src/sounds/record_end.ogg" type="BINDATA" />
+      <include name="IDR_CAMERA_RECORD_PAUSE_OGG" file="src/sounds/record_pause.ogg" type="BINDATA" />
       <include name="IDR_CAMERA_RECORD_START_OGG" file="src/sounds/record_start.ogg" type="BINDATA" />
       <include name="IDR_CAMERA_SHUTTER_OGG" file="src/sounds/shutter.ogg" type="BINDATA" />
       <include name="IDR_CAMERA_TICK_FINAL_OGG" file="src/sounds/tick_final.ogg" type="BINDATA" />
diff --git a/chromeos/components/camera_app_ui/resources/src/css/main.css b/chromeos/components/camera_app_ui/resources/src/css/main.css
index 0c5f6fb94..b1b5135 100644
--- a/chromeos/components/camera_app_ui/resources/src/css/main.css
+++ b/chromeos/components/camera_app_ui/resources/src/css/main.css
@@ -434,7 +434,7 @@
   width: var(--size);
 }
 
-body:not(.recording-paused).video #pause-recordvideo .red-dot {
+body:not(.recording-ui-paused).video #pause-recordvideo .red-dot {
   --dot-size: 0px;
 }
 
@@ -469,15 +469,15 @@
   width: var(--bar-size);
 }
 
-body.video.recording.recording-paused #recordvideo {
+body.video.recording.recording-ui-paused #recordvideo {
   --size: 44px;
 }
 
-body.video.recording-paused #pause-recordvideo {
+body.video.recording-ui-paused #pause-recordvideo {
   --size: 60px;
 }
 
-body.video.recording-paused #pause-recordvideo .two-bars {
+body.video.recording-ui-paused #pause-recordvideo .two-bars {
   --bar-size: 0px;
 }
 
@@ -993,7 +993,7 @@
   pointer-events: none;
 }
 
-body.recording-paused #record-time {
+body.recording-ui-paused #record-time {
   background-color: black;
 }
 
@@ -1010,8 +1010,8 @@
   width: 6px;
 }
 
-body.recording-paused #record-time .icon,
-body:not(.recording-paused) #record-time [i18n-content=record_video_paused_msg] {
+body.recording-ui-paused #record-time .icon,
+body:not(.recording-ui-paused) #record-time [i18n-content=record_video_paused_msg] {
   display: none;
 }
 
diff --git a/chromeos/components/camera_app_ui/resources/src/js/state.js b/chromeos/components/camera_app_ui/resources/src/js/state.js
index aa38124..fbbc493 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/state.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/state.js
@@ -35,8 +35,12 @@
   PLAYING_RESULT_VIDEO: 'playing-result-video',
   PREVIEW_VERTICAL_DOCK: 'preview-vertical-dock',
   PRINT_PERFORMANCE_LOGS: 'print-performance-logs',
+  // Starts/Ends from start()/at stop() of MediaRecorder.
   RECORDING: 'recording',
+  // Binds with paused state of MediaRecorder.
   RECORDING_PAUSED: 'recording-paused',
+  // Controls appearance of paused/resumed UI.
+  RECORDING_UI_PAUSED: 'recording-ui-paused',
   REVIEW_PHOTO_RESULT: 'review-photo-result',
   REVIEW_RESULT: 'review-result',
   REVIEW_VIDEO_RESULT: 'review-video-result',
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js b/chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js
index af4c243..fe46766 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js
@@ -718,7 +718,10 @@
    * Toggles pause/resume state of video recording.
    * @return {!Promise} Promise resolved when recording is paused/resumed.
    */
-  togglePaused() {
+  async togglePaused() {
+    if (!state.get(state.State.RECORDING)) {
+      return;
+    }
     if (this.togglePaused_ !== null) {
       return this.togglePaused_;
     }
@@ -735,12 +738,18 @@
       this.togglePaused_ = null;
       waitable.signal();
     };
-    this.mediaRecorder_.addEventListener(toggledEvent, onToggled);
+    const playEffect = async () => {
+      state.set(state.State.RECORDING_UI_PAUSED, toBePaused);
+      await sound.play(toBePaused ? '#sound-rec-pause' : '#sound-rec-start');
+    };
 
+    this.mediaRecorder_.addEventListener(toggledEvent, onToggled);
     if (toBePaused) {
+      waitable.wait().then(playEffect);
       this.recordTime_.stop({pause: true});
       this.mediaRecorder_.pause();
     } else {
+      await playEffect();
       this.recordTime_.start({resume: true});
       this.mediaRecorder_.resume();
     }
@@ -841,6 +850,7 @@
       const onstop = (event) => {
         state.set(state.State.RECORDING, false);
         state.set(state.State.RECORDING_PAUSED, false);
+        state.set(state.State.RECORDING_UI_PAUSED, false);
 
         this.mediaRecorder_.removeEventListener(
             'dataavailable', ondataavailable);
@@ -858,6 +868,7 @@
       this.mediaRecorder_.start(100);
       state.set(state.State.RECORDING, true);
       state.set(state.State.RECORDING_PAUSED, false);
+      state.set(state.State.RECORDING_UI_PAUSED, false);
     });
   }
 }
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/record_pause.ogg b/chromeos/components/camera_app_ui/resources/src/sounds/record_pause.ogg
new file mode 100644
index 0000000..eb72241
--- /dev/null
+++ b/chromeos/components/camera_app_ui/resources/src/sounds/record_pause.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/views/main.html b/chromeos/components/camera_app_ui/resources/src/views/main.html
index 937d8388..2abf435 100644
--- a/chromeos/components/camera_app_ui/resources/src/views/main.html
+++ b/chromeos/components/camera_app_ui/resources/src/views/main.html
@@ -387,8 +387,10 @@
       data-timeout="1000">
     <audio id="sound-shutter" src="../sounds/shutter.ogg" data-timeout="350">
     <audio id="sound-rec-start" src="../sounds/record_start.ogg"
-      data-timeout="200">
+      data-timeout="300">
     <audio id="sound-rec-end" src="../sounds/record_end.ogg" data-timeout="450">
+    <audio id="sound-rec-pause" src="../sounds/record_pause.ogg"
+      data-timeout="500">
     <template id="resolution-item-template">
       <label class="menu-item circle resolution-option">
         <input class="icon" type="radio" tabindex="0">
diff --git a/chromeos/components/help_app_ui/help_app_ui.cc b/chromeos/components/help_app_ui/help_app_ui.cc
index 43ef8d95..01e06ab 100644
--- a/chromeos/components/help_app_ui/help_app_ui.cc
+++ b/chromeos/components/help_app_ui/help_app_ui.cc
@@ -53,7 +53,7 @@
   std::string csp =
       std::string("frame-src ") + kChromeUIHelpAppUntrustedURL + ";";
   host_source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::ChildSrc, csp);
+      network::mojom::CSPDirectiveName::FrameSrc, csp);
 
   content::WebUIDataSource* untrusted_source =
       CreateHelpAppUntrustedDataSource(delegate_.get());
diff --git a/chromeos/components/media_app_ui/media_app_ui.cc b/chromeos/components/media_app_ui/media_app_ui.cc
index 132bf96..36ef6f7 100644
--- a/chromeos/components/media_app_ui/media_app_ui.cc
+++ b/chromeos/components/media_app_ui/media_app_ui.cc
@@ -62,7 +62,7 @@
   // The guest is in an <iframe>. Add it to CSP.
   std::string csp = std::string("frame-src ") + kChromeUIMediaAppGuestURL + ";";
   host_source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::ChildSrc, csp);
+      network::mojom::CSPDirectiveName::FrameSrc, csp);
 
   // Register auto-granted permissions.
   auto* allowlist = WebUIAllowlist::GetOrCreate(browser_context);
diff --git a/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc b/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc
index a444489..b70d7b3 100644
--- a/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc
+++ b/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc
@@ -56,7 +56,7 @@
   std::string csp =
       std::string("frame-src ") + kChromeUIUntrustedSampleSystemWebAppURL + ";";
   trusted_source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::ChildSrc, csp);
+      network::mojom::CSPDirectiveName::FrameSrc, csp);
   auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
   content::WebUIDataSource::Add(browser_context, trusted_source.release());
   content::WebUIDataSource::Add(browser_context,
diff --git a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
index 5f6b5810..a35f2e6 100644
--- a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
+++ b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
@@ -71,7 +71,7 @@
   std::string csp =
       std::string("frame-src ") + kChromeUIUntrustedTelemetryExtensionURL + ";";
   trusted_source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::ChildSrc, csp);
+      network::mojom::CSPDirectiveName::FrameSrc, csp);
   auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
   content::WebUIDataSource::Add(browser_context, trusted_source.release());
   content::WebUIDataSource::Add(browser_context,
diff --git a/chromeos/components/web_applications/test/js_library_test.cc b/chromeos/components/web_applications/test/js_library_test.cc
index fc6626d..b123fb9 100644
--- a/chromeos/components/web_applications/test/js_library_test.cc
+++ b/chromeos/components/web_applications/test/js_library_test.cc
@@ -62,11 +62,10 @@
   auto* trusted_source = content::WebUIDataSource::Create(kSystemAppTestHost);
 
   // We need a CSP override to be able to embed a chrome-untrusted:// iframe.
-  // TODO(crbug.com/1105408): use FrameSrc instead of ChildSrc.
   std::string csp =
-      std::string("child-src ") + kUntrustedSystemAppTestURL + ";";
+      std::string("frame-src ") + kUntrustedSystemAppTestURL + ";";
   trusted_source->OverrideContentSecurityPolicy(
-      network::mojom::CSPDirectiveName::ChildSrc, csp);
+      network::mojom::CSPDirectiveName::FrameSrc, csp);
 
   SetRequestFilterForDataSource(*trusted_source);
   return trusted_source;
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index 9e496b1..6b62789 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-85-4181.3-1594639678-benchmark-85.0.4183.26-r1.orderfile.xz
+chromeos-chrome-orderfile-field-86-4181.3-1594638142-benchmark-86.0.4194.0-r1.orderfile.xz
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc
index b65a7c8..2d27841 100644
--- a/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -18,10 +18,10 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_run_loop_timeout.h"
@@ -175,7 +175,7 @@
     ASSERT_EQ(HANDLE_EINTR(listen(fd_.get(), 5)), 0);
 
     controller_.reset(new base::MessagePumpForUI::FdWatchController(FROM_HERE));
-    ASSERT_TRUE(base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+    ASSERT_TRUE(base::CurrentUIThread::Get()->WatchFileDescriptor(
         fd_.get(), true, base::MessagePumpForUI::WATCH_READ, controller_.get(),
         this));
   }
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 3696ebea..25070c3 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -88,6 +88,8 @@
     "data_model/autofill_profile.h",
     "data_model/autofill_profile_comparator.cc",
     "data_model/autofill_profile_comparator.h",
+    "data_model/autofill_structured_address_utils.cc",
+    "data_model/autofill_structured_address_utils.h",
     "data_model/contact_info.cc",
     "data_model/contact_info.h",
     "data_model/credit_card.cc",
@@ -566,6 +568,7 @@
     "data_model/autofill_data_model_unittest.cc",
     "data_model/autofill_profile_comparator_unittest.cc",
     "data_model/autofill_profile_unittest.cc",
+    "data_model/autofill_structured_address_utils_unittest.cc",
     "data_model/contact_info_unittest.cc",
     "data_model/credit_card_unittest.cc",
     "data_model/phone_number_unittest.cc",
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc b/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc
new file mode 100644
index 0000000..4b38a9f
--- /dev/null
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc
@@ -0,0 +1,146 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/check.h"
+#include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/strings/strcat.h"
+
+namespace autofill {
+namespace structured_address {
+
+Re2ExpressionCache::Re2ExpressionCache() = default;
+
+// static
+Re2ExpressionCache* Re2ExpressionCache::Instance() {
+  static base::NoDestructor<Re2ExpressionCache> g_re2regex_cache;
+  return g_re2regex_cache.get();
+}
+
+const RE2* Re2ExpressionCache::GetExpression(const std::string& pattern) {
+  // For thread safety, acquire a lock to prevent concurrent access.
+  base::AutoLock lock(lock_);
+
+  auto it = expression_map_.find(pattern);
+  if (it != expression_map_.end()) {
+    const RE2* expression = it->second.get();
+    return expression;
+  }
+
+  // Build the expression and verify it is correct.
+  auto expression_ptr = BuildExpressionFromPattern(pattern);
+
+  // Insert the expression into the map, check the success and return the
+  // pointer.
+  auto result = expression_map_.emplace(pattern, std::move(expression_ptr));
+  DCHECK(result.second);
+  return result.first->second.get();
+}
+
+std::unique_ptr<const RE2> BuildExpressionFromPattern(std::string pattern) {
+  RE2::Options opt;
+  opt.set_case_sensitive(false);
+
+  auto expression = std::make_unique<const RE2>(pattern, opt);
+
+  if (!expression->ok()) {
+    DEBUG_ALIAS_FOR_CSTR(pattern_copy, pattern.c_str(), 128);
+    base::debug::DumpWithoutCrashing();
+  }
+
+  return expression;
+}
+
+bool ParseValueByRegularExpression(
+    const std::string& value,
+    const std::string& pattern,
+    std::map<std::string, std::string>* result_map) {
+  DCHECK(result_map);
+
+  const RE2* expression =
+      Re2ExpressionCache::Instance()->GetExpression(pattern);
+
+  return ParseValueByRegularExpression(value, expression, result_map);
+}
+
+bool ParseValueByRegularExpression(
+    const std::string& value,
+    const RE2* expression,
+    std::map<std::string, std::string>* result_map) {
+  if (!expression || !expression->ok())
+    return false;
+
+  // Get the number of capturing groups in the expression.
+  // Note, the capturing group for the full match is not counted.
+  size_t number_of_capturing_groups = expression->NumberOfCapturingGroups() + 1;
+
+  // Create result vectors to get the matches for the capturing groups.
+  std::vector<std::string> results(number_of_capturing_groups);
+  std::vector<RE2::Arg> match_results(number_of_capturing_groups);
+  std::vector<RE2::Arg*> match_results_ptr(number_of_capturing_groups);
+
+  // Note, the capturing group for the full match is not counted by
+  // |NumberOfCapturingGroups|.
+  for (size_t i = 0; i < number_of_capturing_groups; i++) {
+    match_results[i] = &results[i];
+    match_results_ptr[i] = &match_results[i];
+  }
+
+  // One capturing group is not counted since it holds the full match.
+  if (!RE2::FullMatchN(value, *expression, match_results_ptr.data(),
+                       number_of_capturing_groups - 1))
+    return false;
+
+  // If successful, write the values into the results map.
+  // Note, the capturing group for the full match creates an off-by-one scenario
+  // in the indexing.
+  for (auto named_group : expression->NamedCapturingGroups())
+    (*result_map)[named_group.first] =
+        std::move(results.at(named_group.second - 1));
+
+  return true;
+}
+
+bool IsPartialMatch(const std::string& value, const std::string& pattern) {
+  const RE2* expression =
+      Re2ExpressionCache::Instance()->GetExpression(pattern);
+  if (!expression || !expression->ok())
+    return false;
+
+  return RE2::PartialMatch(value, *expression);
+}
+
+std::vector<std::string> GetAllPartialMatches(const std::string& value,
+                                              const std::string& pattern) {
+  const RE2* expression =
+      Re2ExpressionCache::Instance()->GetExpression(pattern);
+  if (!expression || !expression->ok())
+    return {};
+  re2::StringPiece input(value);
+  std::string match;
+  std::vector<std::string> matches;
+  while (re2::RE2::FindAndConsume(&input, *expression, &match)) {
+    matches.emplace_back(match);
+  }
+  return matches;
+}
+
+std::vector<std::string> ExtractAllPlaceholders(const std::string& value) {
+  return GetAllPartialMatches(value, "\\${([\\w]+)}");
+}
+
+std::string GetPlaceholderToken(const std::string& value) {
+  return base::StrCat({"${", value, "}"});
+}
+
+}  // namespace structured_address
+}  // namespace autofill
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_utils.h b/components/autofill/core/browser/data_model/autofill_structured_address_utils.h
new file mode 100644
index 0000000..fd6878da
--- /dev/null
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_utils.h
@@ -0,0 +1,92 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_STRUCTURED_ADDRESS_UTILS_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_STRUCTURED_ADDRESS_UTILS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
+#include "third_party/re2/src/re2/re2.h"
+
+namespace autofill {
+namespace structured_address {
+
+// A cache for compiled RE2 regular expressions.
+class Re2ExpressionCache {
+ public:
+  Re2ExpressionCache& operator=(const Re2ExpressionCache&) = delete;
+  Re2ExpressionCache(const Re2ExpressionCache&) = delete;
+  ~Re2ExpressionCache() = delete;
+
+  // Returns a singleton instance.
+  static Re2ExpressionCache* Instance();
+
+  // Returns a pointer to a constant compiled expression that matches |pattern|
+  // case-insensitively.
+  const RE2* GetExpression(const std::string& pattern);
+
+#ifdef UNIT_TEST
+  // Returns true if the compiled regular expression corresponding to |pattern|
+  // is cached.
+  bool IsExpressionCachedForTesting(const std::string& pattern) {
+    return expression_map_.count(pattern) > 0;
+  }
+#endif
+
+ private:
+  Re2ExpressionCache();
+
+  // Since the constructor is private, |base::NoDestructor| must be friend to be
+  // allowed to construct the cache.
+  friend class base::NoDestructor<Re2ExpressionCache>;
+
+  // Stores a compiled regular expression keyed by its corresponding |pattern|.
+  std::map<std::string, std::unique_ptr<const RE2>> expression_map_;
+
+  // A lock to prevent concurrent access to the map.
+  base::Lock lock_;
+};
+
+// Parses |value| with an regular expression defined by |pattern|.
+// Returns true on success meaning that the expressions is fully matched.
+// The matching results are written into the supplied |result_map|, keyed by the
+// name of the capture group with the captured substrings as the value.
+bool ParseValueByRegularExpression(
+    const std::string& value,
+    const std::string& pattern,
+    std::map<std::string, std::string>* result_map);
+
+// Same as above, but accepts a compiled regular expression instead of the
+// pattern.
+bool ParseValueByRegularExpression(
+    const std::string& value,
+    const RE2* expression,
+    std::map<std::string, std::string>* result_map);
+
+// Returns a compiled case insensitive regular expression for |pattern|.
+std::unique_ptr<const RE2> BuildExpressionFromPattern(std::string pattern);
+
+// Returns true if |value| can be matched with |pattern|.
+bool IsPartialMatch(const std::string& value, const std::string& pattern);
+
+// Returns a vector that contains all partial matches of |pattern| in |value|;
+std::vector<std::string> GetAllPartialMatches(const std::string& value,
+                                              const std::string& pattern);
+
+// Extracts all placeholders of the format ${PLACEHOLDER} in |value|.
+std::vector<std::string> ExtractAllPlaceholders(const std::string& value);
+
+// Returns |value| as a placeholder token: ${value}.
+std::string GetPlaceholderToken(const std::string& value);
+
+}  // namespace structured_address
+
+}  // namespace autofill
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_STRUCTURED_ADDRESS_UTILS_H_
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_utils_unittest.cc b/components/autofill/core/browser/data_model/autofill_structured_address_utils_unittest.cc
new file mode 100644
index 0000000..35667becc7
--- /dev/null
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_utils_unittest.cc
@@ -0,0 +1,198 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
+
+#include <stddef.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace structured_address {
+
+// Regular expression with named capture groups for parsing US-style names.
+char kFirstMiddleLastRe[] =
+    "^(?P<NAME_FULL>((?P<NAME_FIRST>\\w+)\\s)?"
+    "((?P<NAME_MIDDLE>(\\w+(?:\\s+\\w+)*))\\s)??"
+    "(?P<NAME_LAST>\\w+))$";
+
+// Test the successful parsing of a value by a regular expression.
+TEST(AutofillStructuredAddressUtils, TestParseValueByRegularExpression) {
+  std::string regex = kFirstMiddleLastRe;
+  std::string value = "first middle1 middle2 middle3 last";
+
+  std::map<std::string, std::string> result_map;
+
+  bool success = ParseValueByRegularExpression(value, regex, &result_map);
+
+  EXPECT_TRUE(success);
+  EXPECT_EQ(result_map["NAME_FULL"], value);
+  EXPECT_EQ(result_map["NAME_FIRST"], "first");
+  EXPECT_EQ(result_map["NAME_MIDDLE"], "middle1 middle2 middle3");
+  EXPECT_EQ(result_map["NAME_LAST"], "last");
+
+  // Parse a name with only one middle name.
+  value = "first middle1 last";
+  result_map.clear();
+  success = ParseValueByRegularExpression(value, regex, &result_map);
+
+  EXPECT_TRUE(success);
+  EXPECT_EQ(result_map["NAME_FULL"], value);
+  EXPECT_EQ(result_map["NAME_FIRST"], "first");
+  EXPECT_EQ(result_map["NAME_MIDDLE"], "middle1");
+  EXPECT_EQ(result_map["NAME_LAST"], "last");
+
+  // Parse a name without a middle name.
+  value = "first last";
+  result_map.clear();
+  success = ParseValueByRegularExpression(value, regex, &result_map);
+
+  // Verify the expectation.
+  EXPECT_TRUE(success);
+  EXPECT_EQ(result_map["NAME_FULL"], value);
+  EXPECT_EQ(result_map["NAME_FIRST"], "first");
+  EXPECT_EQ(result_map["NAME_MIDDLE"], "");
+  EXPECT_EQ(result_map["NAME_LAST"], "last");
+
+  // Parse a name without only a last name.
+  value = "last";
+  result_map.clear();
+  success = ParseValueByRegularExpression(value, regex, &result_map);
+
+  // Verify the expectations.
+  EXPECT_TRUE(success);
+  EXPECT_EQ(result_map["NAME_FULL"], value);
+  EXPECT_EQ(result_map["NAME_FIRST"], "");
+  EXPECT_EQ(result_map["NAME_MIDDLE"], "");
+  EXPECT_EQ(result_map["NAME_LAST"], "last");
+
+  // Parse an empty name that should not be successful.
+  value = "";
+  result_map.clear();
+  success = ParseValueByRegularExpression(value, regex, &result_map);
+
+  // Verify the expectations.
+  EXPECT_FALSE(success);
+  EXPECT_EQ(result_map.size(), 0u);
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestParseValueByRegularExpression_OnlyPartialMatch) {
+  std::string regex = "(!<GROUP>this)";
+  std::string value = "this is missing";
+
+  std::map<std::string, std::string> result_map;
+
+  EXPECT_FALSE(ParseValueByRegularExpression(value, regex, &result_map));
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestParseValueByRegularExpression_InvalidExpression) {
+  std::string regex = "(!<INVALID";
+  std::string value = "first middle1 middle2 middle3 last";
+
+  std::map<std::string, std::string> result_map;
+
+  EXPECT_FALSE(ParseValueByRegularExpression(value, regex, &result_map));
+  auto expression = BuildExpressionFromPattern(regex);
+  EXPECT_FALSE(
+      ParseValueByRegularExpression(value, expression.get(), &result_map));
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestParseValueByRegularExpression_UnintializedResultMap) {
+  std::string regex = "(exp)";
+  std::string value = "first middle1 middle2 middle3 last";
+
+  std::map<std::string, std::string>* result_map = nullptr;
+
+  ASSERT_DCHECK_DEATH(ParseValueByRegularExpression(value, regex, result_map));
+}
+
+// Test the matching of a value against a regular expression.
+TEST(AutofillStructuredAddressUtils, TestIsPartialMatch) {
+  EXPECT_TRUE(IsPartialMatch("123 sdf 123", "sdf"));
+  EXPECT_FALSE(IsPartialMatch("123 sdf 123", "^sdf$"));
+}
+
+// Test the matching of a value against an invalid regular expression.
+TEST(AutofillStructuredAddressUtils, TestIsPartialMatch_InvalidExpression) {
+  EXPECT_FALSE(IsPartialMatch("123 sdf 123", "(!<sdf"));
+}
+
+// Test the caching of regular expressions.
+TEST(AutofillStructuredAddressUtils, TestExpressionCaching) {
+  std::string pattern = "(?P<SOME_EXPRESSION>.)";
+  // Verify that the pattern is not cached yet.
+  EXPECT_FALSE(
+      Re2ExpressionCache::Instance()->IsExpressionCachedForTesting(pattern));
+
+  // Request the regular expression and verify that it is cached afterwards.
+  Re2ExpressionCache::Instance()->GetExpression(pattern);
+  EXPECT_TRUE(
+      Re2ExpressionCache::Instance()->IsExpressionCachedForTesting(pattern));
+}
+
+TEST(AutofillStructuredAddressUtils, TestGetAllPartialMatches) {
+  std::string input = "abaacaada";
+  std::string pattern = "(a.a)";
+
+  std::vector<std::string> expectation = {"aba", "aca", "ada"};
+  EXPECT_TRUE(IsPartialMatch(input, pattern));
+  EXPECT_EQ(GetAllPartialMatches(input, pattern), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils, TestGetAllPartialMatches_InvalidPattern) {
+  std::string input = "abaacaada";
+  std::string pattern = "(a.a";
+
+  std::vector<std::string> expectation = {};
+  EXPECT_FALSE(IsPartialMatch(input, pattern));
+  EXPECT_EQ(GetAllPartialMatches(input, pattern), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestExtractAllPlaceholders_Isolated_Placeholder) {
+  std::string input = "${HOLDER1}";
+  std::vector<std::string> expectation = {"HOLDER1"};
+  EXPECT_EQ(ExtractAllPlaceholders(input), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestExtractAllPlaceholders_Placeholder_In_Text) {
+  std::string input = "Some ${HOLDER1} Text";
+  std::vector<std::string> expectation = {"HOLDER1"};
+  EXPECT_EQ(ExtractAllPlaceholders(input), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestExtractAllPlaceholders_Multiple_Placeholders_In_Text) {
+  std::string input = "Some ${HOLDER1} Text ${HOLDER2}";
+  std::vector<std::string> expectation = {"HOLDER1", "HOLDER2"};
+  EXPECT_EQ(ExtractAllPlaceholders(input), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils, TestExtractAllPlaceholders_Broken_Syntax) {
+  std::string input = "Some ${HOLDER1} }} ";
+  std::vector<std::string> expectation = {"HOLDER1"};
+  EXPECT_EQ(ExtractAllPlaceholders(input), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils,
+     TestExtractAllPlaceholders_Nested_Placeholders) {
+  std::string input = "Some ${HOLDER${INANHOLDER}} }} ";
+  std::vector<std::string> expectation = {"INANHOLDER"};
+  EXPECT_EQ(ExtractAllPlaceholders(input), expectation);
+}
+
+TEST(AutofillStructuredAddressUtils, TestGetPlaceholderToken) {
+  EXPECT_EQ("${VAR}", GetPlaceholderToken("VAR"));
+}
+
+}  // namespace structured_address
+}  // namespace autofill
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 458879daf..b4b138f3 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -255,7 +255,7 @@
 
 // Enables the touch to fill feature for Android.
 const base::Feature kAutofillTouchToFill = {"TouchToFillAndroid",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAutofillUploadThrottling{"AutofillUploadThrottling",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/autofill/core/common/field_data_manager.cc b/components/autofill/core/common/field_data_manager.cc
index 76a92f4..df30b5b9 100644
--- a/components/autofill/core/common/field_data_manager.cc
+++ b/components/autofill/core/common/field_data_manager.cc
@@ -85,6 +85,27 @@
                               FieldPropertiesFlags::kAutofilledOnUserTrigger);
 }
 
+bool FieldDataManager::WasAutofilledOnPageLoad(FieldRendererId id) const {
+  return HasFieldData(id) && (GetFieldPropertiesMask(id) &
+                              FieldPropertiesFlags::kAutofilledOnPageLoad);
+}
+
+void FieldDataManager::UpdateFieldDataWithAutofilledValue(
+    FieldRendererId id,
+    const base::string16& value,
+    FieldPropertiesMask mask) {
+  UpdateFieldDataMapWithNullValue(id, mask);
+  autofilled_values_map_[id] = value;
+}
+
+base::Optional<base::string16> FieldDataManager::GetAutofilledValue(
+    FieldRendererId id) const {
+  if (autofilled_values_map_.count(id))
+    return base::Optional<base::string16>(autofilled_values_map_.at(id));
+  else
+    return base::nullopt;
+}
+
 FieldDataManager::~FieldDataManager() = default;
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/field_data_manager.h b/components/autofill/core/common/field_data_manager.h
index b9f8adcb..501eabc 100644
--- a/components/autofill/core/common/field_data_manager.h
+++ b/components/autofill/core/common/field_data_manager.h
@@ -52,12 +52,24 @@
     return field_value_and_properties_map_;
   }
 
+  bool WasAutofilledOnPageLoad(FieldRendererId id) const;
+
+  // Update data with autofilled value.
+  void UpdateFieldDataWithAutofilledValue(FieldRendererId id,
+                                          const base::string16& value,
+                                          FieldPropertiesMask mask);
+
+  base::Optional<base::string16> GetAutofilledValue(FieldRendererId id) const;
+
  private:
   friend class base::RefCounted<FieldDataManager>;
 
   ~FieldDataManager();
 
   FieldDataMap field_value_and_properties_map_;
+
+  // Stores values autofilled either on page load or on user trigger.
+  std::map<FieldRendererId, base::string16> autofilled_values_map_;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/field_data_manager_unittest.cc b/components/autofill/core/common/field_data_manager_unittest.cc
index cbc5b30d..9424986e 100644
--- a/components/autofill/core/common/field_data_manager_unittest.cc
+++ b/components/autofill/core/common/field_data_manager_unittest.cc
@@ -105,4 +105,20 @@
       field_data_manager->FindMachedValue(UTF8ToUTF16("second_element")));
 }
 
+TEST_F(FieldDataManagerTest, UpdateFieldDataMapWithAutofilledValue) {
+  const scoped_refptr<FieldDataManager> field_data_manager =
+      base::MakeRefCounted<FieldDataManager>();
+  const FieldRendererId id(control_elements_[0].unique_renderer_id);
+  field_data_manager->UpdateFieldDataWithAutofilledValue(
+      id, ASCIIToUTF16("autofilled"),
+      FieldPropertiesFlags::kAutofilledOnPageLoad);
+
+  EXPECT_TRUE(field_data_manager->HasFieldData(id));
+  EXPECT_EQ(base::string16(), field_data_manager->GetUserTypedValue(id));
+  EXPECT_EQ(UTF8ToUTF16("autofilled"),
+            field_data_manager->GetAutofilledValue(id));
+  EXPECT_EQ(FieldPropertiesFlags::kAutofilledOnPageLoad,
+            field_data_manager->GetFieldPropertiesMask(id));
+}
+
 }  // namespace autofill
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
index 2d4892a4..cd765ef 100644
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -149,10 +149,12 @@
   WAKE_LOCK_SCREEN,
   WAKE_LOCK_SYSTEM,
 
-  // Legacy SameSite cookie behavior. This disables SameSiteByDefaultCookies
-  // and CookiesWithoutSameSiteMustBeSecure, and forces the legacy behavior
-  // where cookies that don't specify SameSite are treated as SameSite=None and
-  // SameSite=None cookies are not required to be Secure.
+  // Legacy SameSite cookie behavior. This disables SameSiteByDefaultCookies,
+  // CookiesWithoutSameSiteMustBeSecure, and SchemefulSameSite, forcing the
+  // legacy behavior wherein cookies that don't specify SameSite are treated as
+  // SameSite=None, SameSite=None cookies are not required to be Secure, and
+  // schemeful same-site is not active.
+  //
   // This will also be used to revert to legacy behavior when future changes
   // in cookie handling are introduced.
   LEGACY_COOKIE_ACCESS,
diff --git a/components/crash/content/browser/crash_handler_host_linux.cc b/components/crash/content/browser/crash_handler_host_linux.cc
index 9db5e37..949a1d9 100644
--- a/components/crash/content/browser/crash_handler_host_linux.cc
+++ b/components/crash/content/browser/crash_handler_host_linux.cc
@@ -24,13 +24,13 @@
 #include "base/linux_util.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/threading/thread.h"
@@ -153,7 +153,7 @@
 }
 
 void CrashHandlerHostLinux::Init() {
-  base::MessageLoopCurrentForIO ml = base::MessageLoopCurrentForIO::Get();
+  base::CurrentIOThread ml = base::CurrentIOThread::Get();
   CHECK(ml->WatchFileDescriptor(browser_socket_, true /* persistent */,
                                 base::MessagePumpForIO::WATCH_READ,
                                 &fd_watch_controller_, this));
@@ -558,7 +558,7 @@
 }
 
 void CrashHandlerHost::Init() {
-  base::MessageLoopCurrentForIO ml = base::MessageLoopCurrentForIO::Get();
+  base::CurrentIOThread ml = base::CurrentIOThread::Get();
   CHECK(ml->WatchFileDescriptor(browser_socket_.get(), /* persistent= */ true,
                                 base::MessagePumpForIO::WATCH_READ,
                                 &fd_watch_controller_, this));
diff --git a/components/crash/content/browser/crash_handler_host_linux.h b/components/crash/content/browser/crash_handler_host_linux.h
index 4391eb97..b40c795c 100644
--- a/components/crash/content/browser/crash_handler_host_linux.h
+++ b/components/crash/content/browser/crash_handler_host_linux.h
@@ -14,11 +14,11 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/process/process_handle.h"
 #include "base/synchronization/atomic_flag.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 
 #if !defined(OS_ANDROID)
@@ -43,9 +43,8 @@
 // Processes signal that they need to be dumped by sending a datagram over a
 // UNIX domain socket. All processes of the same type share the client end of
 // this socket which is installed in their descriptor table before exec.
-class CrashHandlerHostLinux
-    : public base::MessagePumpForIO::FdWatcher,
-      public base::MessageLoopCurrent::DestructionObserver {
+class CrashHandlerHostLinux : public base::MessagePumpForIO::FdWatcher,
+                              public base::CurrentThread::DestructionObserver {
  public:
   CrashHandlerHostLinux(const std::string& process_type,
                         const base::FilePath& dumps_path,
@@ -66,7 +65,7 @@
   void OnFileCanWriteWithoutBlocking(int fd) override;
   void OnFileCanReadWithoutBlocking(int fd) override;
 
-  // MessageLoopCurrent::DestructionObserver impl:
+  // CurrentThread::DestructionObserver impl:
   void WillDestroyCurrentMessageLoop() override;
 
   // Whether we are shutting down or not.
@@ -125,7 +124,7 @@
 namespace crashpad {
 
 class CrashHandlerHost : public base::MessagePumpForIO::FdWatcher,
-                         public base::MessageLoopCurrent::DestructionObserver {
+                         public base::CurrentThread::DestructionObserver {
  public:
   // An interface for observers to be notified when a child process is crashing.
   class Observer {
@@ -165,7 +164,7 @@
   void OnFileCanWriteWithoutBlocking(int fd) override;
   void OnFileCanReadWithoutBlocking(int fd) override;
 
-  // MessageLoopCurrent::DestructionObserver impl:
+  // CurrentThread::DestructionObserver impl:
   void WillDestroyCurrentMessageLoop() override;
 
   base::Lock observers_lock_;
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc
index cec2b77..e9665780 100644
--- a/components/cronet/android/cronet_library_loader.cc
+++ b/components/cronet/android/cronet_library_loader.cc
@@ -18,9 +18,9 @@
 #include "base/check_op.h"
 #include "base/feature_list.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "build/build_config.h"
@@ -108,7 +108,7 @@
 
 void JNI_CronetLibraryLoader_CronetInitOnInitThread(JNIEnv* env) {
   // Initialize SingleThreadTaskExecutor for init thread.
-  DCHECK(!base::MessageLoopCurrent::IsSet());
+  DCHECK(!base::CurrentThread::IsSet());
   DCHECK(!g_init_task_executor);
   g_init_task_executor =
       new base::SingleThreadTaskExecutor(base::MessagePumpType::JAVA);
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.cc b/components/discardable_memory/service/discardable_shared_memory_manager.cc
index c39b4908..de1422c 100644
--- a/components/discardable_memory/service/discardable_shared_memory_manager.cc
+++ b/components/discardable_memory/service/discardable_shared_memory_manager.cc
@@ -15,13 +15,13 @@
 #include "base/macros.h"
 #include "base/memory/discardable_memory.h"
 #include "base/memory/shared_memory_tracker.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/numerics/safe_math.h"
 #include "base/process/memory.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_allocator_dump.h"
 #include "base/trace_event/memory_dump_manager.h"
@@ -234,7 +234,7 @@
       // Current thread might not have a task runner in tests.
       enforce_memory_policy_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       enforce_memory_policy_pending_(false),
-      mojo_thread_message_loop_(base::MessageLoopCurrent::GetNull()) {
+      mojo_thread_message_loop_(base::CurrentThread::GetNull()) {
   DCHECK(!g_instance)
       << "A DiscardableSharedMemoryManager already exists in this process.";
   g_instance = this;
@@ -254,9 +254,9 @@
   if (mojo_thread_message_loop_) {
     // TODO(etiennep): Get rid of mojo_thread_message_loop_ entirely.
     DCHECK(mojo_thread_task_runner_);
-    if (mojo_thread_message_loop_ == base::MessageLoopCurrent::Get()) {
+    if (mojo_thread_message_loop_ == base::CurrentThread::Get()) {
       mojo_thread_message_loop_->RemoveDestructionObserver(this);
-      mojo_thread_message_loop_ = base::MessageLoopCurrent::GetNull();
+      mojo_thread_message_loop_ = base::CurrentThread::GetNull();
       mojo_thread_task_runner_ = nullptr;
     } else {
       // If mojom::DiscardableSharedMemoryManager implementation is running in
@@ -288,10 +288,10 @@
 void DiscardableSharedMemoryManager::Bind(
     mojo::PendingReceiver<mojom::DiscardableSharedMemoryManager> receiver) {
   DCHECK(!mojo_thread_message_loop_ ||
-         mojo_thread_message_loop_ == base::MessageLoopCurrent::Get());
+         mojo_thread_message_loop_ == base::CurrentThread::Get());
   if (!mojo_thread_task_runner_) {
     DCHECK(!mojo_thread_message_loop_);
-    mojo_thread_message_loop_ = base::MessageLoopCurrent::Get();
+    mojo_thread_message_loop_ = base::CurrentThread::Get();
     mojo_thread_message_loop_->AddDestructionObserver(this);
     mojo_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
   }
@@ -641,7 +641,7 @@
   DCHECK(mojo_thread_task_runner_->RunsTasksInCurrentSequence());
   mojo_thread_weak_ptr_factory_.InvalidateWeakPtrs();
   mojo_thread_message_loop_->RemoveDestructionObserver(this);
-  mojo_thread_message_loop_ = base::MessageLoopCurrent::GetNull();
+  mojo_thread_message_loop_ = base::CurrentThread::GetNull();
   if (event)
     event->Signal();
 }
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.h b/components/discardable_memory/service/discardable_shared_memory_manager.h
index 99eff47c..eafa161c 100644
--- a/components/discardable_memory/service/discardable_shared_memory_manager.h
+++ b/components/discardable_memory/service/discardable_shared_memory_manager.h
@@ -21,10 +21,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/unsafe_shared_memory_region.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/process_handle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/thread_annotations.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_provider.h"
@@ -46,7 +46,7 @@
 class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager
     : public base::DiscardableMemoryAllocator,
       public base::trace_event::MemoryDumpProvider,
-      public base::MessageLoopCurrent::DestructionObserver {
+      public base::CurrentThread::DestructionObserver {
  public:
   DiscardableSharedMemoryManager();
   ~DiscardableSharedMemoryManager() override;
@@ -122,7 +122,7 @@
     return a->memory()->last_known_usage() > b->memory()->last_known_usage();
   }
 
-  // base::MessageLoopCurrent::DestructionObserver implementation:
+  // base::CurrentThread::DestructionObserver implementation:
   void WillDestroyCurrentMessageLoop() override;
 
   void AllocateLockedDiscardableSharedMemory(
@@ -175,7 +175,7 @@
   // when the thread is gone and remove this.
   // A prerequisite for this is allowing objects to be bound to the lifetime
   // of a sequence directly.
-  base::MessageLoopCurrent mojo_thread_message_loop_;
+  base::CurrentThread mojo_thread_message_loop_;
   scoped_refptr<base::SingleThreadTaskRunner> mojo_thread_task_runner_;
 
   base::WeakPtrFactory<DiscardableSharedMemoryManager> weak_ptr_factory_{this};
diff --git a/components/dom_distiller/core/distiller_unittest.cc b/components/dom_distiller/core/distiller_unittest.cc
index ce4a6438..f36336a 100644
--- a/components/dom_distiller/core/distiller_unittest.cc
+++ b/components/dom_distiller/core/distiller_unittest.cc
@@ -16,10 +16,10 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
@@ -252,7 +252,7 @@
   }
 
   void PostCallbackTask() {
-    ASSERT_TRUE(base::MessageLoopCurrent::Get());
+    ASSERT_TRUE(base::CurrentThread::Get());
     ASSERT_FALSE(callback_.is_null());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback_), responses_[url_]));
diff --git a/components/download/internal/common/download_file_unittest.cc b/components/download/internal/common/download_file_unittest.cc
index 2a7a29f..46d8883d 100644
--- a/components/download/internal/common/download_file_unittest.cc
+++ b/components/download/internal/common/download_file_unittest.cc
@@ -762,7 +762,7 @@
 // succeed.
 //
 // Note that there is only one queue of tasks to run, and that is in the tests'
-// base::MessageLoopCurrent::Get(). Each RunLoop processes that queue until it
+// base::CurrentThread::Get(). Each RunLoop processes that queue until it
 // sees a QuitClosure() targeted at itself, at which point it stops processing.
 TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
   ASSERT_TRUE(CreateDownloadFile(true));
diff --git a/components/enterprise/BUILD.gn b/components/enterprise/BUILD.gn
index 1d5e476..f21efe4 100644
--- a/components/enterprise/BUILD.gn
+++ b/components/enterprise/BUILD.gn
@@ -14,6 +14,8 @@
     "browser/reporting/policy_info.h",
     "browser/reporting/profile_report_generator.cc",
     "browser/reporting/profile_report_generator.h",
+    "browser/reporting/report_generator.cc",
+    "browser/reporting/report_generator.h",
     "browser/reporting/report_request_definition.h",
     "browser/reporting/report_request_queue_generator.cc",
     "browser/reporting/report_request_queue_generator.h",
diff --git a/chrome/browser/enterprise/reporting/report_generator.cc b/components/enterprise/browser/reporting/report_generator.cc
similarity index 89%
rename from chrome/browser/enterprise/reporting/report_generator.cc
rename to components/enterprise/browser/reporting/report_generator.cc
index 65053b4..840c0536 100644
--- a/chrome/browser/enterprise/reporting/report_generator.cc
+++ b/components/enterprise/browser/reporting/report_generator.cc
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/enterprise/reporting/report_generator.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 
 #include <utility>
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/enterprise/reporting/reporting_delegate_factory_desktop.h"
+#include "build/build_config.h"
+#include "components/enterprise/browser/reporting/browser_report_generator.h"
+#include "components/enterprise/browser/reporting/reporting_delegate_factory.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 
 #if defined(OS_WIN)
@@ -19,8 +21,7 @@
 
 namespace enterprise_reporting {
 
-ReportGenerator::ReportGenerator(
-    ReportingDelegateFactoryDesktop* delegate_factory)
+ReportGenerator::ReportGenerator(ReportingDelegateFactory* delegate_factory)
     : delegate_(delegate_factory->GetReportGeneratorDelegate()),
       report_request_queue_generator_(delegate_factory),
       browser_report_generator_(delegate_factory) {}
diff --git a/chrome/browser/enterprise/reporting/report_generator.h b/components/enterprise/browser/reporting/report_generator.h
similarity index 89%
rename from chrome/browser/enterprise/reporting/report_generator.h
rename to components/enterprise/browser/reporting/report_generator.h
index 75a6a0e9..22bfd0c0 100644
--- a/chrome/browser/enterprise/reporting/report_generator.h
+++ b/components/enterprise/browser/reporting/report_generator.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 CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_H_
-#define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_H_
+#ifndef COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_GENERATOR_H_
+#define COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_GENERATOR_H_
 
 #include <memory>
 #include <queue>
@@ -12,7 +12,6 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
 #include "components/enterprise/browser/reporting/browser_report_generator.h"
 #include "components/enterprise/browser/reporting/report_request_definition.h"
 #include "components/enterprise/browser/reporting/report_request_queue_generator.h"
@@ -20,7 +19,7 @@
 
 namespace enterprise_reporting {
 
-class ReportingDelegateFactoryDesktop;
+class ReportingDelegateFactory;
 
 class ReportGenerator {
  public:
@@ -41,7 +40,7 @@
     virtual void SetAndroidAppInfos(ReportRequest* basic_request) = 0;
   };
 
-  explicit ReportGenerator(ReportingDelegateFactoryDesktop* delegate_factory);
+  explicit ReportGenerator(ReportingDelegateFactory* delegate_factory);
   virtual ~ReportGenerator();
 
   // Asynchronously generates a queue of report requests, providing them to
@@ -91,4 +90,4 @@
 
 }  // namespace enterprise_reporting
 
-#endif  // CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_GENERATOR_H_
+#endif  // COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REPORT_GENERATOR_H_
diff --git a/components/enterprise/browser/reporting/reporting_delegate_factory.h b/components/enterprise/browser/reporting/reporting_delegate_factory.h
index 23489fd..d473ca15 100644
--- a/components/enterprise/browser/reporting/reporting_delegate_factory.h
+++ b/components/enterprise/browser/reporting/reporting_delegate_factory.h
@@ -9,6 +9,7 @@
 
 #include "components/enterprise/browser/reporting/browser_report_generator.h"
 #include "components/enterprise/browser/reporting/profile_report_generator.h"
+#include "components/enterprise/browser/reporting/report_generator.h"
 
 namespace enterprise_reporting {
 
@@ -25,6 +26,9 @@
 
   virtual std::unique_ptr<ProfileReportGenerator::Delegate>
   GetProfileReportGeneratorDelegate() = 0;
+
+  virtual std::unique_ptr<ReportGenerator::Delegate>
+  GetReportGeneratorDelegate() = 0;
 };
 
 }  // namespace enterprise_reporting
diff --git a/components/exo/server/wayland_server_controller.cc b/components/exo/server/wayland_server_controller.cc
index f4a44b2..b7e4591c 100644
--- a/components/exo/server/wayland_server_controller.cc
+++ b/components/exo/server/wayland_server_controller.cc
@@ -8,7 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "components/exo/display.h"
 #include "components/exo/file_helper.h"
 #include "components/exo/input_method_surface_manager.h"
diff --git a/components/exo/wayland/clients/test/wayland_client_test_helper.cc b/components/exo/wayland/clients/test/wayland_client_test_helper.cc
index 09574cf..3d65a7b 100644
--- a/components/exo/wayland/clients/test/wayland_client_test_helper.cc
+++ b/components/exo/wayland/clients/test/wayland_client_test_helper.cc
@@ -14,8 +14,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "components/exo/display.h"
 #include "components/exo/file_helper.h"
 #include "components/exo/input_method_surface_manager.h"
@@ -38,7 +38,7 @@
  public:
   explicit WaylandWatcher(exo::wayland::Server* server)
       : controller_(FROM_HERE), server_(server) {
-    base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+    base::CurrentUIThread::Get()->WatchFileDescriptor(
         server_->GetFileDescriptor(),
         /*persistent=*/true, base::MessagePumpLibevent::WATCH_READ,
         &controller_, this);
diff --git a/components/exo/wayland/wayland_watcher.cc b/components/exo/wayland/wayland_watcher.cc
index bc2d4b9..7ebbbc2 100644
--- a/components/exo/wayland/wayland_watcher.cc
+++ b/components/exo/wayland/wayland_watcher.cc
@@ -4,7 +4,7 @@
 
 #include "components/exo/wayland/wayland_watcher.h"
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "components/exo/wayland/server.h"
 
 namespace exo {
@@ -12,7 +12,7 @@
 
 WaylandWatcher::WaylandWatcher(wayland::Server* server)
     : controller_(FROM_HERE), server_(server) {
-  base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+  base::CurrentUIThread::Get()->WatchFileDescriptor(
       server_->GetFileDescriptor(),
       true,  // persistent
       base::MessagePumpForUI::WATCH_READ, &controller_, this);
diff --git a/components/gcm_driver/gcm_driver_desktop_unittest.cc b/components/gcm_driver/gcm_driver_desktop_unittest.cc
index a698e200..5344dc3 100644
--- a/components/gcm_driver/gcm_driver_desktop_unittest.cc
+++ b/components/gcm_driver/gcm_driver_desktop_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/components/gcm_driver/gcm_driver_unittest.cc b/components/gcm_driver/gcm_driver_unittest.cc
index 279a6da8..6773129 100644
--- a/components/gcm_driver/gcm_driver_unittest.cc
+++ b/components/gcm_driver/gcm_driver_unittest.cc
@@ -10,9 +10,9 @@
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/components/history/core/browser/expire_history_backend_unittest.cc b/components/history/core/browser/expire_history_backend_unittest.cc
index 945bd824..e413457 100644
--- a/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/components/history/core/browser/expire_history_backend_unittest.cc
@@ -16,12 +16,12 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "components/history/core/browser/favicon_database.h"
@@ -189,7 +189,7 @@
     top_sites_->ShutdownOnUIThread();
     top_sites_ = nullptr;
 
-    if (base::MessageLoopCurrent::Get())
+    if (base::CurrentThread::Get())
       base::RunLoop().RunUntilIdle();
 
     pref_service_.reset();
diff --git a/components/metrics/structured/recorder.cc b/components/metrics/structured/recorder.cc
index f8ebf39..aa719b4 100644
--- a/components/metrics/structured/recorder.cc
+++ b/components/metrics/structured/recorder.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "components/metrics/structured/event_base.h"
 #include "components/metrics/structured/histogram_util.h"
@@ -37,7 +37,7 @@
     return;
   }
 
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   for (auto& observer : observers_)
     observer.OnRecord(event);
 
@@ -51,7 +51,7 @@
 void Recorder::ProfileAdded(const base::FilePath& profile_path) {
   // All calls to the StructuredMetricsProvider (the observer) must be on the UI
   // sequence.
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   // TODO(crbug.com/1016655 ): investigate whether we can verify that
   // |profile_path| corresponds to a valid (non-guest, non-signin) profile.
   for (auto& observer : observers_)
diff --git a/components/metrics/structured/structured_metrics_provider.cc b/components/metrics/structured/structured_metrics_provider.cc
index 10fbd7d..2d858b9 100644
--- a/components/metrics/structured/structured_metrics_provider.cc
+++ b/components/metrics/structured/structured_metrics_provider.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/values.h"
 #include "components/metrics/structured/event_base.h"
 #include "components/metrics/structured/histogram_util.h"
@@ -108,7 +108,7 @@
 
 void StructuredMetricsProvider::OnProfileAdded(
     const base::FilePath& profile_path) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (initialized_)
     return;
 
@@ -136,14 +136,14 @@
 }
 
 void StructuredMetricsProvider::OnRecordingEnabled() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (!recording_enabled_)
     Recorder::GetInstance()->AddObserver(this);
   recording_enabled_ = true;
 }
 
 void StructuredMetricsProvider::OnRecordingDisabled() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (recording_enabled_)
     Recorder::GetInstance()->RemoveObserver(this);
   recording_enabled_ = false;
@@ -160,7 +160,7 @@
 
 void StructuredMetricsProvider::ProvideCurrentSessionData(
     ChromeUserMetricsExtension* uma_proto) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (!recording_enabled_ || !initialized_)
     return;
 
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
index 55ce75d0..1116a66 100644
--- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/check.h"
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 96b9c4b..f0a10b7 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -60,6 +60,9 @@
     "bulk_leak_check_service.h",
     "bulk_leak_check_service_interface.cc",
     "bulk_leak_check_service_interface.h",
+    "change_password_url_service.h",
+    "change_password_url_service_impl.cc",
+    "change_password_url_service_impl.h",
     "compromised_credentials_consumer.cc",
     "compromised_credentials_consumer.h",
     "compromised_credentials_observer.cc",
@@ -533,6 +536,7 @@
     "android_affiliation/facet_manager_unittest.cc",
     "browser_save_password_progress_logger_unittest.cc",
     "bulk_leak_check_service_unittest.cc",
+    "change_password_url_service_impl_unittest.cc",
     "compromised_credentials_observer_unittest.cc",
     "compromised_credentials_table_unittest.cc",
     "credential_cache_unittest.cc",
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_api.proto b/components/password_manager/core/browser/android_affiliation/affiliation_api.proto
index 353ab69b..9f563a6 100644
--- a/components/password_manager/core/browser/android_affiliation/affiliation_api.proto
+++ b/components/password_manager/core/browser/android_affiliation/affiliation_api.proto
@@ -8,39 +8,132 @@
 
 option optimize_for = LITE_RUNTIME;
 
-// A collection of facets affiliated with each other, i.e. an equivalence class.
+// Contains a list of affiliated facets.
+// Affiliated facets are allowed to share credentials among each other.
 message Affiliation {
+  // See the top level comment.
   repeated Facet facet = 1;
+
+  reserved 2;
 }
 
+// A website or Android app within the affiliation.
 message Facet {
-  // The URI of the facet.
+  // URL the uniquely identifies the website or Android app.
   optional string id = 1;
+
+  // Branding info for this Facet.
   optional BrandingInfo branding_info = 2;
+
+  // Top private domain of a facet. Exists only if facet ID refers to a website
+  // (starts with "http://" or "https://").
+  // See go/internet-domain-name for Top Private Domain definition.
+  // If no top private domain can be calculated (e.g. for IP addresses), then
+  // the domain in the facet ID is returned without changes.
+  // Examples (facet ID -> main_domain):
+  // http://www.facebook.com -> facebook.com
+  // https://google.com -> google.com
+  // http://192.168.0.1 -> 192.168.0.1
+  // http://somethinginvalid$%#^ -> somethinginvalid$%#^
+  // android://xyz@com.facebook -> field is not populated
+  optional string main_domain = 3;
 }
 
-message BrandingInfo {
+// Message representing set of facets that should be grouped together in the UI.
+message FacetGroup {
+  // Set of facets that can be grouped together in the UI.
+  // Do no use this for credential sharing - Affiliation.facet field is intended
+  // for that.
+  // Also, see the top level comment of Affiliation message.
+  repeated Facet facet = 1;
+
+  // Branding info (display name and the icon info) for the Group.
+  optional GroupBrandingInfo group_branding_info = 2;
+}
+
+// Branding info (display name and the icon info) for an affiliated group.
+message GroupBrandingInfo {
+  // Display name of the group.
   optional string name = 1;
+  // Eliding info for the name.
+  optional BrandingInfo.ElideInfo elide_info = 5;
+
+  // Icon URL of the group.
   optional string icon_url = 2;
+
+  // Width and height of the icon. These fields are populated only when we're
+  // able to find or detect them.
+  optional int32 icon_width = 3;
+  optional int32 icon_height = 4;
 }
 
-// Specifies what additional information to return with the response.
+// Branding info for a single facet.
+message BrandingInfo {
+  enum ElideInfo {
+    UNKNOWN_ELIDE = 0;
+    // Elide the name from the front if it doesn't fit.
+    // Example: "https://www.facebook.evildomain.com" -> "...ook.evildomain.com"
+    ELIDE_FROM_FRONT = 1;
+    // Elide the name from the back if it doesn't fit.
+    // Example: "Facebook - The awesome app" -> "Facebook - The awe..."
+    ELIDE_FROM_BACK = 2;
+  }
+
+  // Display name.
+  optional string name = 1;
+  // Eliding info for the name.
+  optional ElideInfo elide_info = 6;
+
+  // Icon URL.
+  optional string icon_url = 2;
+
+  // Width and height of the icon. These fields are populated only when we're
+  // able to find or detect them.
+  optional int32 icon_width = 4;
+  optional int32 icon_height = 5;
+}
+
+// Request mask for LookupAffiliationRequest.
 message LookupAffiliationMask {
-  // Whether or not to fill |branding_info| for returned Facets.
+  // If true, branding info for Android apps will be returned.
   optional bool branding_info = 1;
-  // The locale to use for |branding_info.name| for returned Facets.
+
+  // Preferred size of the icon returned in BrandingInfo or
+  // GroupBrandingInfo. Applies both to width and height of the image.
+  // This field can be set only if at least one of branding_info or
+  // affiliation_branding_info is set to true.
+  optional int32 preferred_icon_size = 4;
+
+  // If set, the display name for the specified locale will be returned.
   optional string locale = 2;
+
+  // If true, insecure affiliation (e.g. with HTTP websites) will be returned.
+  // Note that this does not affect the returned grouping information.
+  optional bool insecure_affiliation = 3;
+
+  // If true the information required for password grouping.
+  optional bool grouping_info = 6;
+
+  // If true, an instance of GroupBrandingInfo will be populated in the
+  // grouping response. Can be set only if grouping_info and branding_info is
+  // set to true.
+  optional bool group_branding_info = 5;
 }
 
-// Encapsulates a lookup request to the Affiliation API.
+// Request message for AffiliationService.Lookup.
 message LookupAffiliationRequest {
-  // The facet URIs to query.
+  // Facet IDs to query.
   repeated string facet = 1;
+
+  // Request mask.
   optional LookupAffiliationMask mask = 2;
 }
 
-// Encapsulates a lookup response from the the Affiliation API.
+// Response message for AffiliationService.Lookup.
 message LookupAffiliationResponse {
-  // For each queried facet, the corresponding equivalence class, if any.
+  // Affiliations containing the requested facets.
   repeated Affiliation affiliation = 1;
-}
\ No newline at end of file
+
+  // Information required for grouping facets in the UI.
+  repeated FacetGroup group = 2;
+}
diff --git a/components/password_manager/core/browser/change_password_url_service.h b/components/password_manager/core/browser/change_password_url_service.h
new file mode 100644
index 0000000..add254f
--- /dev/null
+++ b/components/password_manager/core/browser/change_password_url_service.h
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_H_
+
+#include "base/callback_forward.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+class GURL;
+
+namespace url {
+class Origin;
+}
+
+namespace password_manager {
+
+class ChangePasswordUrlService : public KeyedService {
+ public:
+  using UrlCallback = base::OnceCallback<void(GURL)>;
+  // Initializes the service.
+  virtual void Initialize() = 0;
+  // Returns the change password URL for `origin` via `callback`.
+  virtual void GetChangePasswordUrl(const url::Origin& origin,
+                                    UrlCallback callback) = 0;
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_H_
diff --git a/components/password_manager/core/browser/change_password_url_service_impl.cc b/components/password_manager/core/browser/change_password_url_service_impl.cc
new file mode 100644
index 0000000..af53473
--- /dev/null
+++ b/components/password_manager/core/browser/change_password_url_service_impl.cc
@@ -0,0 +1,57 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/change_password_url_service_impl.h"
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace password_manager {
+
+ChangePasswordUrlServiceImpl::ChangePasswordUrlServiceImpl(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+    : url_loader_factory_(std::move(url_loader_factory)) {}
+
+ChangePasswordUrlServiceImpl::~ChangePasswordUrlServiceImpl() = default;
+
+void ChangePasswordUrlServiceImpl::Initialize() {
+  if (started_fetching_) {
+    return;
+  }
+  started_fetching_ = true;
+  // TODO(crbug.com/1086141): make request to gstatic.
+  OnFetchComplete(std::make_unique<std::string>("{}"));
+}
+
+void ChangePasswordUrlServiceImpl::GetChangePasswordUrl(
+    const url::Origin& origin,
+    UrlCallback callback) {
+  // TODO(crbug.com/1086141): call callback if response available, otherwise
+  // save callback.
+  url_callbacks_.emplace_back(std::make_pair(origin, std::move(callback)));
+}
+
+void ChangePasswordUrlServiceImpl::OnFetchComplete(
+    std::unique_ptr<std::string> response_body) {
+  // TODO(crbug.com/1086141): handle response and convert JSON.
+  change_password_url_map_ = {};
+
+  for (auto& url_callback : std::exchange(url_callbacks_, {})) {
+    GURL url = ChangePasswordUrlFor(url_callback.first);
+    std::move(url_callback.second).Run(std::move(url));
+  }
+}
+
+GURL ChangePasswordUrlServiceImpl::ChangePasswordUrlFor(
+    const url::Origin& origin) {
+  // TODO(crbug.com/1086141): lookup url override from map.
+
+  // Fallback if no change-password url available or request failed
+  return origin.GetURL();
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/change_password_url_service_impl.h b/components/password_manager/core/browser/change_password_url_service_impl.h
new file mode 100644
index 0000000..a6d4d95
--- /dev/null
+++ b/components/password_manager/core/browser/change_password_url_service_impl.h
@@ -0,0 +1,64 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_IMPL_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/scoped_refptr.h"
+#include "components/password_manager/core/browser/change_password_url_service.h"
+
+class GURL;
+
+namespace url {
+class Origin;
+}
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+namespace password_manager {
+
+class ChangePasswordUrlServiceImpl
+    : public password_manager::ChangePasswordUrlService {
+ public:
+  explicit ChangePasswordUrlServiceImpl(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+  ~ChangePasswordUrlServiceImpl() override;
+
+  void Initialize() override;
+  // When the gstatic response arrives the callback is called with the override
+  // url for the given |url|. If no override is there the origin is returned.
+  void GetChangePasswordUrl(const url::Origin& origin,
+                            UrlCallback callback) override;
+
+ private:
+  // Callback for the the request to gstatic.
+  void OnFetchComplete(std::unique_ptr<std::string> response_body);
+  // Retrieves the url override from the |change_password_url_map| for a given
+  // origin. It uses eTLD+1 for the lookup but also checks if overrides for
+  // eTLD+1+N exist.
+  GURL ChangePasswordUrlFor(const url::Origin& origin);
+
+  // Stores if the request is already started to only fetch once.
+  bool started_fetching_ = false;
+  // Stores the JSON result for the url overrides.
+  base::flat_map<std::string, GURL> change_password_url_map_;
+  // Stores the callbacks that are waiting for the request to finish.
+  std::vector<std::pair<url::Origin, base::OnceCallback<void(GURL)>>>
+      url_callbacks_;
+  // SharedURLLoaderFactory for the gstatic request, argument in the
+  // constructor.
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+};
+
+}  // namespace password_manager
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CHANGE_PASSWORD_URL_SERVICE_IMPL_H_
diff --git a/components/password_manager/core/browser/change_password_url_service_impl_unittest.cc b/components/password_manager/core/browser/change_password_url_service_impl_unittest.cc
new file mode 100644
index 0000000..42b8bd5
--- /dev/null
+++ b/components/password_manager/core/browser/change_password_url_service_impl_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "components/password_manager/core/browser/change_password_url_service_impl.h"
+
+#include "base/logging.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+
+class ChangePasswordUrlServiceTest : public testing::Test {
+ private:
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_ =
+      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+          &test_url_loader_factory_);
+};
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc
index 98935fe..981e6bb7 100644
--- a/components/password_manager/core/browser/password_form_filling_unittest.cc
+++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -171,12 +171,19 @@
   LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
       &client_, &driver_, observed_form_, best_matches, federated_matches_,
       &saved_match_, metrics_recorder_.get());
+
+  // On Android Touch To Fill will prevent autofilling credentials on page load.
+#if defined(OS_ANDROID)
+  EXPECT_EQ(LikelyFormFilling::kFillOnAccountSelect, likely_form_filling);
+  EXPECT_TRUE(fill_data.wait_for_username);
+#else
   EXPECT_EQ(LikelyFormFilling::kFillOnPageLoad, likely_form_filling);
+  EXPECT_FALSE(fill_data.wait_for_username);
+#endif
 
   // Check that the message to the renderer (i.e. |fill_data|) is filled
   // correctly.
   EXPECT_EQ(observed_form_.url, fill_data.url);
-  EXPECT_FALSE(fill_data.wait_for_username);
   EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name);
   EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
   EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name);
@@ -240,10 +247,17 @@
     // In all cases where a current password exists, fill on load should be
     // permitted. Otherwise, the renderer will not fill anyway and return
     // kFillOnAccountSelect.
-    if (test_case.current_password_present)
-      EXPECT_EQ(LikelyFormFilling::kFillOnPageLoad, likely_form_filling);
-    else
+    if (test_case.current_password_present) {
+      // On Android Touch To Fill will prevent autofilling credentials on page
+      // load.
+#if defined(OS_ANDROID)
       EXPECT_EQ(LikelyFormFilling::kFillOnAccountSelect, likely_form_filling);
+#else
+      EXPECT_EQ(LikelyFormFilling::kFillOnPageLoad, likely_form_filling);
+#endif
+    } else {
+      EXPECT_EQ(LikelyFormFilling::kFillOnAccountSelect, likely_form_filling);
+    }
   }
 }
 
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 22709a19..e7c77f7 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -35,6 +35,7 @@
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "google_apis/gaia/core_account_id.h"
 
+using autofill::FieldDataManager;
 using autofill::FieldRendererId;
 using autofill::FormData;
 using autofill::FormFieldData;
@@ -566,6 +567,20 @@
     const base::WeakPtr<PasswordManagerDriver>& driver) {
   driver_ = driver;
 }
+
+void PasswordFormManager::UpdateObservedFormDataWithFieldDataManagerInfo(
+    const FieldDataManager* field_data_manager) {
+  for (FormFieldData& field : observed_form_.fields) {
+    FieldRendererId field_id = field.unique_renderer_id;
+    if (!field_data_manager->HasFieldData(field_id))
+      continue;
+    field.typed_value = field_data_manager->GetUserTypedValue(field_id);
+    field.properties_mask =
+        field_data_manager->GetFieldPropertiesMask(field_id);
+    field.value =
+        field_data_manager->GetAutofilledValue(field_id).value_or(field.value);
+  }
+}
 #endif  // defined(OS_IOS)
 
 std::unique_ptr<PasswordFormManager> PasswordFormManager::Clone() {
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 49baddb..8e841a5 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
@@ -205,6 +206,10 @@
                               const base::string16& field_value);
 
   void SetDriver(const base::WeakPtr<PasswordManagerDriver>& driver);
+
+  // Copies all known field data from FieldDataManager to |observed_form_|.
+  void UpdateObservedFormDataWithFieldDataManagerInfo(
+      const autofill::FieldDataManager* field_data_manager);
 #endif  // defined(OS_IOS)
 
   // Create a copy of |*this| which can be passed to the code handling
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 218c9b1..c8aac7a8 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -521,7 +521,14 @@
   task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_EQ(observed_form_.url, fill_data.url);
+
+  // On Android Touch To Fill will prevent autofilling credentials on page load.
+#if defined(OS_ANDROID)
+  EXPECT_TRUE(fill_data.wait_for_username);
+#else
   EXPECT_FALSE(fill_data.wait_for_username);
+#endif
+
   EXPECT_EQ(observed_form_.fields[1].name, fill_data.username_field.name);
   EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
   EXPECT_EQ(observed_form_.fields[2].name, fill_data.password_field.name);
@@ -2063,6 +2070,32 @@
             form_manager_->observed_form().fields[kPasswordFieldIndex].value);
 }
 
+TEST_P(PasswordFormManagerTest, iOSUsingFieldDataManagerData) {
+  CreateFormManager(observed_form_);
+
+  auto field_data_manager = base::MakeRefCounted<autofill::FieldDataManager>();
+  field_data_manager->UpdateFieldDataMap(
+      observed_form_.fields[1].unique_renderer_id,
+      base::UTF8ToUTF16("typed_username"), FieldPropertiesFlags::kUserTyped);
+  field_data_manager->UpdateFieldDataWithAutofilledValue(
+      observed_form_.fields[2].unique_renderer_id,
+      base::UTF8ToUTF16("autofilled_pw"),
+      FieldPropertiesFlags::kAutofilledOnPageLoad);
+
+  form_manager_->UpdateObservedFormDataWithFieldDataManagerInfo(
+      field_data_manager.get());
+
+  EXPECT_EQ(form_manager_->observed_form().fields[1].typed_value,
+            base::UTF8ToUTF16("typed_username"));
+  EXPECT_EQ(form_manager_->observed_form().fields[1].properties_mask,
+            FieldPropertiesFlags::kUserTyped);
+
+  EXPECT_EQ(form_manager_->observed_form().fields[2].value,
+            base::UTF8ToUTF16("autofilled_pw"));
+  EXPECT_EQ(form_manager_->observed_form().fields[2].properties_mask,
+            FieldPropertiesFlags::kAutofilledOnPageLoad);
+}
+
 #endif  // defined(OS_IOS)
 
 // Tests that username is taken during username first flow.
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 371d371..9fd2b8c 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -51,6 +51,7 @@
 #endif
 
 using autofill::ACCOUNT_CREATION_PASSWORD;
+using autofill::FieldDataManager;
 using autofill::FieldRendererId;
 using autofill::FormData;
 using autofill::FormRendererId;
@@ -740,25 +741,30 @@
     manager->PasswordNoLongerGenerated();
 }
 
-void PasswordManager::OnPasswordFormRemoved(PasswordManagerDriver* driver,
-                                            FormRendererId form_id) {
+void PasswordManager::OnPasswordFormRemoved(
+    PasswordManagerDriver* driver,
+    const FieldDataManager* field_data_manager,
+    FormRendererId form_id) {
   for (auto& manager : form_managers_) {
     if (driver && !manager->GetDriver())
       manager->SetDriver(driver->AsWeakPtr());
+    // Find a form with corresponding renderer id.
     if (manager->DoesManageAccordingToRendererId(form_id, driver)) {
-      if (manager->is_submitted())
-        OnLoginSuccessful();
-      else
-        return;
+      CheckForPotentialSubmission(manager.get(), field_data_manager, driver);
+      return;
     }
   }
 }
 
-void PasswordManager::OnIframeDetach(const std::string& frame_id) {
-  PasswordFormManager* submitted_manager = GetSubmittedManager();
-  if (submitted_manager &&
-      submitted_manager->observed_form().frame_id == frame_id) {
-    OnLoginSuccessful();
+void PasswordManager::OnIframeDetach(
+    const std::string& frame_id,
+    PasswordManagerDriver* driver,
+    const FieldDataManager* field_data_manager) {
+  for (auto& manager : form_managers_) {
+    // Find a form with corresponding frame id.
+    if (manager->observed_form().frame_id == frame_id) {
+      CheckForPotentialSubmission(manager.get(), field_data_manager, driver);
+    }
   }
 }
 #endif
@@ -1253,6 +1259,25 @@
   autofill_assistant_mode_ = AutofillAssistantMode::kNotRunning;
 }
 
+#if defined(OS_IOS)
+void PasswordManager::CheckForPotentialSubmission(
+    PasswordFormManager* form_manager,
+    const FieldDataManager* field_data_manager,
+    PasswordManagerDriver* driver) {
+  // If the manager is not submitted, it still can have autofilled data.
+  if (!form_manager->is_submitted()) {
+    form_manager->UpdateObservedFormDataWithFieldDataManagerInfo(
+        field_data_manager);
+    // Provisionally save form and set the manager to be submitted if valid
+    // data was recovered.
+    form_manager->ProvisionallySave(form_manager->observed_form(), driver,
+                                    nullptr);
+  }
+  if (form_manager->is_submitted())
+    OnLoginSuccessful();
+}
+#endif
+
 base::TimeDelta PasswordManager::GetTimeoutForDisablingPrompts() {
   return base::TimeDelta::FromSeconds(disable_prompts_timeout_in_seconds_);
 }
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h
index c9b336a..0991eff 100644
--- a/components/password_manager/core/browser/password_manager.h
+++ b/components/password_manager/core/browser/password_manager.h
@@ -110,9 +110,14 @@
                               autofill::FieldRendererId field_id,
                               const base::string16& field_value) override;
   void OnPasswordNoLongerGenerated(PasswordManagerDriver* driver) override;
-  void OnPasswordFormRemoved(PasswordManagerDriver* driver,
-                             autofill::FormRendererId form_id) override;
-  void OnIframeDetach(const std::string& frame_id) override;
+  void OnPasswordFormRemoved(
+      PasswordManagerDriver* driver,
+      const autofill::FieldDataManager* field_data_manager,
+      autofill::FormRendererId form_id) override;
+  void OnIframeDetach(
+      const std::string& frame_id,
+      PasswordManagerDriver* driver,
+      const autofill::FieldDataManager* field_data_manager) override;
 #endif
 
   // Notifies the renderer to start the generation flow or pops up additional UI
@@ -335,6 +340,17 @@
   // Resets |autofill_assistant_mode_| to the default.
   void ResetAutofillAssistantMode();
 
+#if defined(OS_IOS)
+  // Even though the formal submission might not happen, the manager
+  // could still be provisionally saved on user input or have autofilled data,
+  // in this case submission might be considered successful and a save prompt
+  // might be shown.
+  void CheckForPotentialSubmission(
+      PasswordFormManager* form_manager,
+      const autofill::FieldDataManager* field_data_manager,
+      PasswordManagerDriver* driver);
+#endif
+
   // PasswordFormManager transition schemes:
   // 1. HTML submission with navigation afterwads.
   // form "seen"
diff --git a/components/password_manager/core/browser/password_manager_interface.h b/components/password_manager/core/browser/password_manager_interface.h
index 46c0242..3621804 100644
--- a/components/password_manager/core/browser/password_manager_interface.h
+++ b/components/password_manager/core/browser/password_manager_interface.h
@@ -11,6 +11,7 @@
 
 #include "base/strings/string16.h"
 #include "build/build_config.h"
+#include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "components/password_manager/core/browser/form_submission_observer.h"
@@ -76,12 +77,17 @@
 
   // Call when a form is removed so that this class can decide if whether or not
   // the form was submitted.
-  virtual void OnPasswordFormRemoved(PasswordManagerDriver* driver,
-                                     autofill::FormRendererId form_id) = 0;
+  virtual void OnPasswordFormRemoved(
+      PasswordManagerDriver* driver,
+      const autofill::FieldDataManager* field_data_manager,
+      autofill::FormRendererId form_id) = 0;
 
   // Checks if there is a submitted PasswordFormManager for a form from the
   // detached frame.
-  virtual void OnIframeDetach(const std::string& frame_id) = 0;
+  virtual void OnIframeDetach(
+      const std::string& frame_id,
+      PasswordManagerDriver* driver,
+      const autofill::FieldDataManager* field_data_manager) = 0;
 #endif
 };
 
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 295f207..1115d6b 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -2259,7 +2259,12 @@
 
   EXPECT_EQ(android_form.username_value, form_data.username_field.value);
   EXPECT_EQ(android_form.password_value, form_data.password_field.value);
+  // On Android Touch To Fill will prevent autofilling credentials on page load.
+#if defined(OS_ANDROID)
+  EXPECT_TRUE(form_data.wait_for_username);
+#else
   EXPECT_FALSE(form_data.wait_for_username);
+#endif
   EXPECT_EQ(android_form.signon_realm, form_data.preferred_realm);
 
   EXPECT_CALL(client_, IsSavingAndFillingEnabled(observed_form.url))
diff --git a/components/password_manager/ios/password_form_helper.mm b/components/password_manager/ios/password_form_helper.mm
index 178b1e9..27781e0 100644
--- a/components/password_manager/ios/password_form_helper.mm
+++ b/components/password_manager/ios/password_form_helper.mm
@@ -31,6 +31,7 @@
 using autofill::FormRendererId;
 using autofill::FieldRendererId;
 using autofill::PasswordFormFillData;
+using base::SysNSStringToUTF16;
 using password_manager::FillData;
 using password_manager::GetPageURLAndCheckTrustLevel;
 using password_manager::SerializePasswordFormFillData;
@@ -189,6 +190,10 @@
                              forms.size(), 50);
   if (forms.size() != 1)
     return;
+
+  // Extract FieldDataManager data for observed fields.
+  [self extractKnownFieldData:forms[0]];
+
   [self.delegate formHelper:self
               didSubmitForm:forms[0]
                 inMainFrame:formInMainFrame];
@@ -254,15 +259,31 @@
     return;
   }
 
+  // Necessary copy so the values can be used inside a block.
+  FieldRendererId usernameID = formData.username_field.unique_renderer_id;
+  FieldRendererId passwordID = formData.password_field.unique_renderer_id;
+  base::string16 usernameValue = username;
+  base::string16 passwordValue = password;
+
   // Send JSON over to the web view.
+  __weak PasswordFormHelper* weakSelf = self;
   [self.jsPasswordManager
        fillPasswordForm:SerializePasswordFormFillData(formData)
                 inFrame:GetMainFrame(_webState)
            withUsername:base::SysUTF16ToNSString(username)
                password:base::SysUTF16ToNSString(password)
       completionHandler:^(NSString* result) {
+        BOOL success = [result isEqual:@"true"];
+        if (success) {
+          weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+              usernameID, usernameValue,
+              FieldPropertiesFlags::kAutofilledOnPageLoad);
+          weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+              passwordID, passwordValue,
+              FieldPropertiesFlags::kAutofilledOnPageLoad);
+        }
         if (completionHandler) {
-          completionHandler([result isEqual:@"true"]);
+          completionHandler(success);
         }
       }];
 }
@@ -341,12 +362,6 @@
     return;
   }
 
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      formData.username_field.unique_renderer_id,
-      FieldPropertiesFlags::kAutofilledOnPageLoad);
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      formData.password_field.unique_renderer_id,
-      FieldPropertiesFlags::kAutofilledOnPageLoad);
   [self fillPasswordForm:formData
             withUsername:formData.username_field.value
                 password:formData.password_field.value
@@ -358,43 +373,59 @@
     confirmPasswordIdentifier:(FieldRendererId)confirmPasswordIdentifier
             generatedPassword:(NSString*)generatedPassword
             completionHandler:(nullable void (^)(BOOL))completionHandler {
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      newPasswordIdentifier, FieldPropertiesFlags::kAutofilledOnUserTrigger);
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      confirmPasswordIdentifier,
-      FieldPropertiesFlags::kAutofilledOnUserTrigger);
-
   // Send JSON over to the web view.
-  [self.jsPasswordManager fillPasswordForm:formIdentifier
-                                   inFrame:GetMainFrame(_webState)
-                     newPasswordIdentifier:newPasswordIdentifier
-                 confirmPasswordIdentifier:confirmPasswordIdentifier
-                         generatedPassword:generatedPassword
-                         completionHandler:^(NSString* result) {
-                           if (completionHandler) {
-                             completionHandler([result isEqual:@"true"]);
-                           }
-                         }];
+  __weak PasswordFormHelper* weakSelf = self;
+  [self.jsPasswordManager
+               fillPasswordForm:formIdentifier
+                        inFrame:GetMainFrame(_webState)
+          newPasswordIdentifier:newPasswordIdentifier
+      confirmPasswordIdentifier:confirmPasswordIdentifier
+              generatedPassword:generatedPassword
+              completionHandler:^(NSString* result) {
+                BOOL success = [result isEqual:@"true"];
+                if (success) {
+                  weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+                      newPasswordIdentifier,
+                      SysNSStringToUTF16(generatedPassword),
+                      FieldPropertiesFlags::kAutofilledOnUserTrigger);
+                  weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+                      confirmPasswordIdentifier,
+                      SysNSStringToUTF16(generatedPassword),
+                      FieldPropertiesFlags::kAutofilledOnUserTrigger);
+                }
+                if (completionHandler) {
+                  completionHandler(success);
+                }
+              }];
 }
 
 - (void)fillPasswordFormWithFillData:(const password_manager::FillData&)fillData
                    completionHandler:
                        (nullable void (^)(BOOL))completionHandler {
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      fillData.username_element_id,
-      FieldPropertiesFlags::kAutofilledOnUserTrigger);
-  self.fieldDataManager->UpdateFieldDataMapWithNullValue(
-      fillData.password_element_id,
-      FieldPropertiesFlags::kAutofilledOnUserTrigger);
+  // Necessary copy so the values can be used inside a block.
+  FieldRendererId usernameID = fillData.username_element_id;
+  FieldRendererId passwordID = fillData.password_element_id;
+  base::string16 usernameValue = fillData.username_value;
+  base::string16 passwordValue = fillData.password_value;
 
+  __weak PasswordFormHelper* weakSelf = self;
   [self.jsPasswordManager
        fillPasswordForm:SerializeFillData(fillData)
                 inFrame:GetMainFrame(_webState)
-           withUsername:base::SysUTF16ToNSString(fillData.username_value)
-               password:base::SysUTF16ToNSString(fillData.password_value)
+           withUsername:base::SysUTF16ToNSString(usernameValue)
+               password:base::SysUTF16ToNSString(passwordValue)
       completionHandler:^(NSString* result) {
+        BOOL success = [result isEqual:@"true"];
+        if (success) {
+          weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+              usernameID, usernameValue,
+              FieldPropertiesFlags::kAutofilledOnUserTrigger);
+          weakSelf.fieldDataManager->UpdateFieldDataWithAutofilledValue(
+              passwordID, passwordValue,
+              FieldPropertiesFlags::kAutofilledOnUserTrigger);
+        }
         if (completionHandler) {
-          completionHandler([result isEqual:@"true"]);
+          completionHandler(success);
         }
       }];
 }
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
index 5aa99e4..fe33682 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -404,12 +404,6 @@
     ui::AXNodeData* static_text_node = nullptr;
     ui::AXNodeData* previous_on_line_node = nullptr;
     std::string static_text;
-    uint32_t current_link_index = 0;
-    uint32_t current_image_index = 0;
-    uint32_t current_highlight_index = 0;
-    uint32_t current_text_field_index = 0;
-    uint32_t current_button_index = 0;
-    uint32_t current_choice_field_index = 0;
     LineHelper line_helper(text_runs_);
     bool pdf_forms_enabled =
         base::FeatureList::IsEnabled(chrome_pdf::features::kAccessiblePDFForm);
@@ -425,49 +419,49 @@
 
       // If the |text_run_index| is less than or equal to the link's
       // text_run_index, then push the link node in the paragraph.
-      if (IsObjectInTextRun(links_, current_link_index, text_run_index)) {
+      if (IsObjectInTextRun(links_, current_link_index_, text_run_index)) {
         FinishStaticNode(&static_text_node, &static_text);
         const ppapi::PdfAccessibilityLinkInfo& link =
-            links_[current_link_index++];
+            links_[current_link_index_++];
         AddLinkToParaNode(link, para_node, &previous_on_line_node,
                           &text_run_index);
 
         if (link.text_run_count == 0)
           continue;
 
-      } else if (IsObjectInTextRun(images_, current_image_index,
+      } else if (IsObjectInTextRun(images_, current_image_index_,
                                    text_run_index)) {
         FinishStaticNode(&static_text_node, &static_text);
-        AddImageToParaNode(images_[current_image_index++], para_node,
+        AddImageToParaNode(images_[current_image_index_++], para_node,
                            &text_run_index);
         continue;
-      } else if (IsObjectInTextRun(highlights_, current_highlight_index,
+      } else if (IsObjectInTextRun(highlights_, current_highlight_index_,
                                    text_run_index) &&
                  base::FeatureList::IsEnabled(
                      chrome_pdf::features::kAccessiblePDFHighlight)) {
         FinishStaticNode(&static_text_node, &static_text);
-        AddHighlightToParaNode(highlights_[current_highlight_index++],
+        AddHighlightToParaNode(highlights_[current_highlight_index_++],
                                para_node, &previous_on_line_node,
                                &text_run_index);
-      } else if (IsObjectInTextRun(text_fields_, current_text_field_index,
+      } else if (IsObjectInTextRun(text_fields_, current_text_field_index_,
                                    text_run_index) &&
                  pdf_forms_enabled) {
         FinishStaticNode(&static_text_node, &static_text);
-        AddTextFieldToParaNode(text_fields_[current_text_field_index++],
+        AddTextFieldToParaNode(text_fields_[current_text_field_index_++],
                                para_node, &text_run_index);
         continue;
-      } else if (IsObjectInTextRun(buttons_, current_button_index,
+      } else if (IsObjectInTextRun(buttons_, current_button_index_,
                                    text_run_index) &&
                  pdf_forms_enabled) {
         FinishStaticNode(&static_text_node, &static_text);
-        AddButtonToParaNode(buttons_[current_button_index++], para_node,
+        AddButtonToParaNode(buttons_[current_button_index_++], para_node,
                             &text_run_index);
         continue;
-      } else if (IsObjectInTextRun(choice_fields_, current_choice_field_index,
+      } else if (IsObjectInTextRun(choice_fields_, current_choice_field_index_,
                                    text_run_index) &&
                  pdf_forms_enabled) {
         FinishStaticNode(&static_text_node, &static_text);
-        AddChoiceFieldToParaNode(choice_fields_[current_choice_field_index++],
+        AddChoiceFieldToParaNode(choice_fields_[current_choice_field_index_++],
                                  para_node, &text_run_index);
         continue;
       } else {
@@ -529,21 +523,7 @@
       }
     }
 
-    base::span<const ppapi::PdfAccessibilityLinkInfo> remaining_links =
-        base::make_span(links_).subspan(current_link_index);
-    base::span<const ppapi::PdfAccessibilityImageInfo> remaining_images =
-        base::make_span(images_).subspan(current_image_index);
-    base::span<const ppapi::PdfAccessibilityTextFieldInfo>
-        remaining_text_fields =
-            base::make_span(text_fields_).subspan(current_text_field_index);
-    base::span<const ppapi::PdfAccessibilityButtonInfo> remaining_buttons =
-        base::make_span(buttons_).subspan(current_button_index);
-    base::span<const ppapi::PdfAccessibilityChoiceFieldInfo>
-        remaining_choice_fields =
-            base::make_span(choice_fields_).subspan(current_text_field_index);
-    AddRemainingAnnotations(remaining_links, remaining_images,
-                            remaining_text_fields, remaining_buttons,
-                            remaining_choice_fields, para_node);
+    AddRemainingAnnotations(para_node);
   }
 
  private:
@@ -1056,17 +1036,14 @@
     --(*text_run_index);
   }
 
-  void AddRemainingAnnotations(
-      base::span<const ppapi::PdfAccessibilityLinkInfo> links,
-      base::span<const ppapi::PdfAccessibilityImageInfo> images,
-      base::span<const ppapi::PdfAccessibilityTextFieldInfo> text_fields,
-      base::span<const ppapi::PdfAccessibilityButtonInfo> buttons,
-      base::span<const ppapi::PdfAccessibilityChoiceFieldInfo> choice_fields,
-      ui::AXNodeData* para_node) {
+  void AddRemainingAnnotations(ui::AXNodeData* para_node) {
     // If we don't have additional links, images or form fields to insert in the
     // tree, then return.
-    if (links.empty() && images.empty() && text_fields.empty() &&
-        buttons.empty() && choice_fields.empty()) {
+    if (current_link_index_ >= links_.size() &&
+        current_image_index_ >= images_.size() &&
+        current_text_field_index_ >= text_fields_.size() &&
+        current_button_index_ >= buttons_.size() &&
+        current_choice_field_index_ >= choice_fields_.size()) {
       return;
     }
 
@@ -1078,13 +1055,13 @@
       page_node_->child_ids.push_back(para_node->id);
     }
     // Push all the links not anchored to any text run to the last paragraph.
-    for (const ppapi::PdfAccessibilityLinkInfo& link : links) {
-      ui::AXNodeData* link_node = CreateLinkNode(link);
+    for (size_t i = current_link_index_; i < links_.size(); i++) {
+      ui::AXNodeData* link_node = CreateLinkNode(links_[i]);
       para_node->child_ids.push_back(link_node->id);
     }
     // Push all the images not anchored to any text run to the last paragraph.
-    for (const ppapi::PdfAccessibilityImageInfo& image : images) {
-      ui::AXNodeData* image_node = CreateImageNode(image);
+    for (size_t i = current_image_index_; i < images_.size(); i++) {
+      ui::AXNodeData* image_node = CreateImageNode(images_[i]);
       para_node->child_ids.push_back(image_node->id);
     }
 
@@ -1092,24 +1069,24 @@
             chrome_pdf::features::kAccessiblePDFForm)) {
       // Push all the text fields not anchored to any text run to the last
       // paragraph.
-      for (const ppapi::PdfAccessibilityTextFieldInfo& text_field :
-           text_fields) {
-        ui::AXNodeData* text_field_node = CreateTextFieldNode(text_field);
+      for (size_t i = current_text_field_index_; i < text_fields_.size(); i++) {
+        ui::AXNodeData* text_field_node = CreateTextFieldNode(text_fields_[i]);
         para_node->child_ids.push_back(text_field_node->id);
       }
 
       // Push all the buttons not anchored to any text run to the last
       // paragraph.
-      for (const ppapi::PdfAccessibilityButtonInfo& button : buttons) {
-        ui::AXNodeData* button_node = CreateButtonNode(button);
+      for (size_t i = current_button_index_; i < buttons_.size(); i++) {
+        ui::AXNodeData* button_node = CreateButtonNode(buttons_[i]);
         para_node->child_ids.push_back(button_node->id);
       }
 
       // Push all the choice fields not anchored to any text run to the last
       // paragraph.
-      for (const ppapi::PdfAccessibilityChoiceFieldInfo& choice_field :
-           choice_fields) {
-        ui::AXNodeData* choice_field_node = CreateChoiceFieldNode(choice_field);
+      for (size_t i = current_choice_field_index_; i < choice_fields_.size();
+           i++) {
+        ui::AXNodeData* choice_field_node =
+            CreateChoiceFieldNode(choice_fields_[i]);
         para_node->child_ids.push_back(choice_field_node->id);
       }
     }
@@ -1119,11 +1096,17 @@
   const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs_;
   const std::vector<PP_PrivateAccessibilityCharInfo>& chars_;
   const std::vector<ppapi::PdfAccessibilityLinkInfo>& links_;
+  uint32_t current_link_index_ = 0;
   const std::vector<ppapi::PdfAccessibilityImageInfo>& images_;
+  uint32_t current_image_index_ = 0;
   const std::vector<ppapi::PdfAccessibilityHighlightInfo>& highlights_;
+  uint32_t current_highlight_index_ = 0;
   const std::vector<ppapi::PdfAccessibilityTextFieldInfo>& text_fields_;
+  uint32_t current_text_field_index_ = 0;
   const std::vector<ppapi::PdfAccessibilityButtonInfo>& buttons_;
+  uint32_t current_button_index_ = 0;
   const std::vector<ppapi::PdfAccessibilityChoiceFieldInfo>& choice_fields_;
+  uint32_t current_choice_field_index_ = 0;
   const gfx::RectF& page_bounds_;
   uint32_t page_index_;
   ui::AXNodeData* page_node_;
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn
index 83ee545..f68ceb80 100644
--- a/components/performance_manager/BUILD.gn
+++ b/components/performance_manager/BUILD.gn
@@ -140,15 +140,12 @@
     "worker_watcher.h",
   ]
 
-  deps = [ "//third_party/blink/public/common:headers" ]
-
   public_deps = [
     "//base",
     "//base/allocator:buildflags",
     "//components/performance_manager/public/mojom",
     "//content/public/browser",
     "//services/metrics/public/cpp:metrics_cpp",
-    "//third_party/blink/public/common",
     "//url",
   ]
 
diff --git a/components/performance_manager/DEPS b/components/performance_manager/DEPS
index c12714db..e278845 100644
--- a/components/performance_manager/DEPS
+++ b/components/performance_manager/DEPS
@@ -10,6 +10,5 @@
   "+services/service_manager/public/cpp",
   "+third_party/blink/public/mojom/favicon",
   "+third_party/blink/public/mojom/service_worker",
-  "+third_party/blink/public/mojom/tokens",
   "+third_party/leveldatabase",
 ]
diff --git a/components/performance_manager/worker_watcher.cc b/components/performance_manager/worker_watcher.cc
index 4819ae2f..1d05b728 100644
--- a/components/performance_manager/worker_watcher.cc
+++ b/components/performance_manager/worker_watcher.cc
@@ -145,19 +145,19 @@
 }
 
 void WorkerWatcher::OnWorkerCreated(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     int worker_process_id,
     content::GlobalFrameRoutingId ancestor_render_frame_host_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  // TODO(https://crbug.com/993029): Plumb through the URL, and make a
-  // strongly-typed WorkerToken instead of using DevToolsToken.
+  // TODO(https://crbug.com/993029): Plumb through the URL and the DevTools
+  // token.
   auto worker_node = PerformanceManagerImpl::CreateWorkerNode(
       browser_context_id_, WorkerNode::WorkerType::kDedicated,
       process_node_source_->GetProcessNode(worker_process_id),
-      dedicated_worker_token.value);
+      base::UnguessableToken::Create());
   auto insertion_result = dedicated_worker_nodes_.emplace(
-      dedicated_worker_token, std::move(worker_node));
+      dedicated_worker_id, std::move(worker_node));
   DCHECK(insertion_result.second);
 
   ConnectClient(insertion_result.first->second.get(),
@@ -165,11 +165,11 @@
 }
 
 void WorkerWatcher::OnBeforeWorkerDestroyed(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     content::GlobalFrameRoutingId ancestor_render_frame_host_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  auto it = dedicated_worker_nodes_.find(dedicated_worker_token);
+  auto it = dedicated_worker_nodes_.find(dedicated_worker_id);
   DCHECK(it != dedicated_worker_nodes_.end());
 
   auto worker_node = std::move(it->second);
@@ -186,11 +186,11 @@
 }
 
 void WorkerWatcher::OnFinalResponseURLDetermined(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    content::DedicatedWorkerId dedicated_worker_id,
     const GURL& url) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  SetFinalResponseURL(GetDedicatedWorkerNode(dedicated_worker_token), url);
+  SetFinalResponseURL(GetDedicatedWorkerNode(dedicated_worker_id), url);
 }
 
 void WorkerWatcher::OnWorkerCreated(
@@ -415,10 +415,10 @@
 }
 
 WorkerNodeImpl* WorkerWatcher::GetDedicatedWorkerNode(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token) {
+    content::DedicatedWorkerId dedicated_worker_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  auto it = dedicated_worker_nodes_.find(dedicated_worker_token);
+  auto it = dedicated_worker_nodes_.find(dedicated_worker_id);
   if (it == dedicated_worker_nodes_.end()) {
     NOTREACHED();
     return nullptr;
diff --git a/components/performance_manager/worker_watcher.h b/components/performance_manager/worker_watcher.h
index c4e505c..6c6ddb6 100644
--- a/components/performance_manager/worker_watcher.h
+++ b/components/performance_manager/worker_watcher.h
@@ -14,13 +14,13 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "base/sequence_checker.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/dedicated_worker_service.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/service_worker_context_observer.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "content/public/browser/shared_worker_service.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace performance_manager {
 
@@ -51,14 +51,14 @@
 
   // content::DedicatedWorkerService::Observer:
   void OnWorkerCreated(
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       int worker_process_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
   void OnBeforeWorkerDestroyed(
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       content::GlobalFrameRoutingId ancestor_render_frame_host_id) override;
   void OnFinalResponseURLDetermined(
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      content::DedicatedWorkerId dedicated_worker_id,
       const GURL& url) override;
 
   // content::SharedWorkerService::Observer:
@@ -104,7 +104,7 @@
 
   // Helper functions to retrieve an existing worker node.
   WorkerNodeImpl* GetDedicatedWorkerNode(
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token);
+      content::DedicatedWorkerId dedicated_worker_id);
   WorkerNodeImpl* GetSharedWorkerNode(content::SharedWorkerId shared_worker_id);
   WorkerNodeImpl* GetServiceWorkerNode(int64_t version_id);
 
@@ -135,8 +135,7 @@
   FrameNodeSource* const frame_node_source_;
 
   // Maps each dedicated worker ID to its worker node.
-  base::flat_map<blink::mojom::DedicatedWorkerToken,
-                 std::unique_ptr<WorkerNodeImpl>>
+  base::flat_map<content::DedicatedWorkerId, std::unique_ptr<WorkerNodeImpl>>
       dedicated_worker_nodes_;
 
   // Maps each shared worker ID to its worker node.
diff --git a/components/performance_manager/worker_watcher_unittest.cc b/components/performance_manager/worker_watcher_unittest.cc
index 2f32e404..53c8ad5 100644
--- a/components/performance_manager/worker_watcher_unittest.cc
+++ b/components/performance_manager/worker_watcher_unittest.cc
@@ -66,19 +66,21 @@
   void EnumerateDedicatedWorkers(Observer* observer) override;
 
   // Creates a new dedicated worker and returns its ID.
-  const blink::mojom::DedicatedWorkerToken& CreateDedicatedWorker(
+  content::DedicatedWorkerId CreateDedicatedWorker(
       int worker_process_id,
       content::GlobalFrameRoutingId client_render_frame_host_id);
 
   // Destroys an existing dedicated worker.
-  void DestroyDedicatedWorker(const blink::mojom::DedicatedWorkerToken& token);
+  void DestroyDedicatedWorker(content::DedicatedWorkerId dedicated_worker_id);
 
  private:
   base::ObserverList<Observer> observer_list_;
 
+  // Generates IDs for new dedicated workers.
+  content::DedicatedWorkerId::Generator dedicated_worker_id_generator_;
+
   // Maps each running worker to its client RenderFrameHost ID.
-  base::flat_map<blink::mojom::DedicatedWorkerToken,
-                 content::GlobalFrameRoutingId>
+  base::flat_map<content::DedicatedWorkerId, content::GlobalFrameRoutingId>
       dedicated_worker_client_frame_;
 
   DISALLOW_COPY_AND_ASSIGN(TestDedicatedWorkerService);
@@ -101,36 +103,36 @@
   ADD_FAILURE();
 }
 
-const blink::mojom::DedicatedWorkerToken&
-TestDedicatedWorkerService::CreateDedicatedWorker(
+content::DedicatedWorkerId TestDedicatedWorkerService::CreateDedicatedWorker(
     int worker_process_id,
     content::GlobalFrameRoutingId client_render_frame_host_id) {
-  // Create a new token for the worker and add it to the map, along with its
-  // client ID.
-  const blink::mojom::DedicatedWorkerToken token(
-      base::UnguessableToken::Create());
+  // Create a new DedicatedWorkerId for the worker and add it to the map, along
+  // with its client ID.
+  content::DedicatedWorkerId dedicated_worker_id =
+      dedicated_worker_id_generator_.GenerateNextId();
 
-  auto result = dedicated_worker_client_frame_.emplace(
-      token, client_render_frame_host_id);
-  DCHECK(result.second);  // Check inserted.
+  bool inserted = dedicated_worker_client_frame_
+                      .emplace(dedicated_worker_id, client_render_frame_host_id)
+                      .second;
+  DCHECK(inserted);
 
   // Notify observers.
   for (auto& observer : observer_list_) {
-    observer.OnWorkerCreated(token, worker_process_id,
+    observer.OnWorkerCreated(dedicated_worker_id, worker_process_id,
                              client_render_frame_host_id);
   }
 
-  return result.first->first;
+  return dedicated_worker_id;
 }
 
 void TestDedicatedWorkerService::DestroyDedicatedWorker(
-    const blink::mojom::DedicatedWorkerToken& token) {
-  auto it = dedicated_worker_client_frame_.find(token);
+    content::DedicatedWorkerId dedicated_worker_id) {
+  auto it = dedicated_worker_client_frame_.find(dedicated_worker_id);
   DCHECK(it != dedicated_worker_client_frame_.end());
 
   // Notify observers that the worker is being destroyed.
   for (auto& observer : observer_list_)
-    observer.OnBeforeWorkerDestroyed(token, it->second);
+    observer.OnBeforeWorkerDestroyed(dedicated_worker_id, it->second);
 
   // Remove the worker ID from the map.
   dedicated_worker_client_frame_.erase(it);
@@ -605,7 +607,7 @@
 
   // Retrieves an existing worker node.
   WorkerNodeImpl* GetDedicatedWorkerNode(
-      const blink::mojom::DedicatedWorkerToken& token);
+      content::DedicatedWorkerId dedicated_worker_id);
   WorkerNodeImpl* GetSharedWorkerNode(content::SharedWorkerId shared_worker_id);
   WorkerNodeImpl* GetServiceWorkerNode(int64_t version_id);
 
@@ -687,8 +689,8 @@
 }
 
 WorkerNodeImpl* WorkerWatcherTest::GetDedicatedWorkerNode(
-    const blink::mojom::DedicatedWorkerToken& token) {
-  return worker_watcher_->GetDedicatedWorkerNode(token);
+    content::DedicatedWorkerId dedicated_worker_id) {
+  return worker_watcher_->GetDedicatedWorkerNode(dedicated_worker_id);
 }
 
 WorkerNodeImpl* WorkerWatcherTest::GetSharedWorkerNode(
@@ -711,14 +713,14 @@
           process_node_source()->GetProcessNode(render_process_id));
 
   // Create the worker.
-  const blink::mojom::DedicatedWorkerToken token =
+  content::DedicatedWorkerId dedicated_worker_id =
       dedicated_worker_service()->CreateDedicatedWorker(render_process_id,
                                                         render_frame_host_id);
 
   // Check expectations on the graph.
   CallOnGraphAndWait(base::BindLambdaForTesting(
       [process_node = process_node_source()->GetProcessNode(render_process_id),
-       worker_node = GetDedicatedWorkerNode(token),
+       worker_node = GetDedicatedWorkerNode(dedicated_worker_id),
        client_frame_node = frame_node_source()->GetFrameNode(
            render_frame_host_id)](GraphImpl* graph) {
         EXPECT_TRUE(graph->NodeInGraph(worker_node));
@@ -729,7 +731,7 @@
       }));
 
   // Disconnect and clean up the worker.
-  dedicated_worker_service()->DestroyDedicatedWorker(token);
+  dedicated_worker_service()->DestroyDedicatedWorker(dedicated_worker_id);
 }
 
 // This test creates one shared worker with one client frame.
@@ -950,7 +952,7 @@
           process_node_source()->GetProcessNode(render_process_id));
 
   // Create a worker of each type.
-  const blink::mojom::DedicatedWorkerToken& token =
+  content::DedicatedWorkerId dedicated_worker_id =
       dedicated_worker_service()->CreateDedicatedWorker(render_process_id,
                                                         render_frame_host_id);
   content::SharedWorkerId shared_worker_id =
@@ -966,7 +968,7 @@
 
   // Check that everything is wired up correctly.
   CallOnGraphAndWait(base::BindLambdaForTesting(
-      [dedicated_worker_node = GetDedicatedWorkerNode(token),
+      [dedicated_worker_node = GetDedicatedWorkerNode(dedicated_worker_id),
        shared_worker_node = GetSharedWorkerNode(shared_worker_id),
        service_worker_node = GetServiceWorkerNode(service_worker_version_id),
        client_frame_node = frame_node_source()->GetFrameNode(
@@ -985,7 +987,7 @@
 
   // Check that the worker is no longer connected to the deleted frame.
   CallOnGraphAndWait(base::BindLambdaForTesting(
-      [dedicated_worker_node = GetDedicatedWorkerNode(token),
+      [dedicated_worker_node = GetDedicatedWorkerNode(dedicated_worker_id),
        shared_worker_node = GetSharedWorkerNode(shared_worker_id),
        service_worker_node =
            GetServiceWorkerNode(service_worker_version_id)](GraphImpl* graph) {
@@ -1004,7 +1006,7 @@
   shared_worker_service()->RemoveFrameClientFromWorker(shared_worker_id,
                                                        render_frame_host_id);
   shared_worker_service()->DestroySharedWorker(shared_worker_id);
-  dedicated_worker_service()->DestroyDedicatedWorker(token);
+  dedicated_worker_service()->DestroyDedicatedWorker(dedicated_worker_id);
 }
 
 }  // namespace performance_manager
diff --git a/components/policy/core/common/mock_configuration_policy_provider.cc b/components/policy/core/common/mock_configuration_policy_provider.cc
index 90a3596c..cd26c73 100644
--- a/components/policy/core/common/mock_configuration_policy_provider.cc
+++ b/components/policy/core/common/mock_configuration_policy_provider.cc
@@ -8,8 +8,8 @@
 #include <string>
 #include <utility>
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "components/policy/core/common/policy_bundle.h"
 
@@ -27,10 +27,10 @@
   bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
       .CopyFrom(policy);
   UpdatePolicy(std::move(bundle));
-  bool spin_run_loop = base::MessageLoopCurrent::IsSet();
+  bool spin_run_loop = base::CurrentThread::IsSet();
 #if defined(OS_IOS)
   // On iOS, the UI message loop does not support RunUntilIdle().
-  spin_run_loop &= !base::MessageLoopCurrentForUI::IsSet();
+  spin_run_loop &= !base::CurrentUIThread::IsSet();
 #endif  // defined(OS_IOS)
   if (spin_run_loop)
     base::RunLoop().RunUntilIdle();
@@ -43,7 +43,7 @@
   bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, extension_id))
       .CopyFrom(policy);
   UpdatePolicy(std::move(bundle));
-  if (base::MessageLoopCurrent::IsSet())
+  if (base::CurrentThread::IsSet())
     base::RunLoop().RunUntilIdle();
 }
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 57d30375..bb62bc0d 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -6172,9 +6172,9 @@
       'id': 623,
       'caption': '''Default legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> cookie behavior setting''',
       'tags': [],
-      'desc': '''Allows you to revert all cookies to legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior. Reverting to legacy behavior causes cookies that don't specify a <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> attribute to be treated as if they were "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>", and removes the requirement for "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>" cookies to carry the "<ph name="ATTRIBUTE_SECURE_NAME">Secure</ph>" attribute. See https://www.chromium.org/administrators/policy-list-3/cookie-legacy-samesite-policies for full description.
+      'desc': '''Allows you to revert all cookies to legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior. Reverting to legacy behavior causes cookies that don't specify a <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> attribute to be treated as if they were "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>", removes the requirement for "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>" cookies to carry the "<ph name="ATTRIBUTE_SECURE_NAME">Secure</ph>" attribute, and skips the scheme comparison when evaluating if two sites are same-site. See https://www.chromium.org/administrators/policy-list-3/cookie-legacy-samesite-policies for full description.
 
-          When this policy is not set, the default <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior for cookies that don't specify a <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> attribute will depend on the user's personal configuration for the <ph name="FEATURE_NAME_SAMESITE_BY_DEFAULT_COOKIES">SameSite-by-default</ph> feature, which may be set by a field trial or by enabling or disabling the flag <ph name="FLAG_NAME_SAMESITE_BY_DEFAULT_COOKIES">same-site-by-default-cookies</ph> flag.''',
+          When this policy is not set, the default <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior for cookies will depend on the user's personal configuration for the <ph name="FEATURE_NAME_SAMESITE_BY_DEFAULT_COOKIES">SameSite-by-default</ph> feature, the <ph name="FEATURE_NAME_SAMESITE_NONE_MUST_BE_SECURE">Cookies-without-SameSite-must-be-secure</ph> feature, and the <ph name="FEATURE_NAME_SCHEMEFUL_SAME_SITE">Schemeful Same-Site</ph> feature which may be set by a field trial or by enabling or disabling the <ph name="FLAG_NAME_SAMESITE_BY_DEFAULT_COOKIES">same-site-by-default-cookies</ph> flag, the <ph name="FLAG_NAME_SAMESITE_NONE_MUST_BE_SECURE">cookies-without-same-site-must-be-secure</ph> flag, or the <ph name="FLAG_NAME_SCHEMEFUL_SAME_SITE">schemeful-same-site</ph> flag, respectively.''',
     },
     {
       'name': 'LegacySameSiteCookieBehaviorEnabledForDomainList',
@@ -6197,7 +6197,7 @@
       'id': 624,
       'caption': '''Revert to legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior for cookies on these sites''',
       'tags': [],
-      'desc': '''Cookies set for domains matching these patterns will revert to legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior. Reverting to legacy behavior causes cookies that don't specify a <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> attribute to be treated as if they were "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>", and removes the requirement for "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>" cookies to carry the "<ph name="ATTRIBUTE_SECURE_NAME">Secure</ph>" attribute. See https://www.chromium.org/administrators/policy-list-3/cookie-legacy-samesite-policies for full description.
+      'desc': '''Cookies set for domains matching these patterns will revert to legacy <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> behavior. Reverting to legacy behavior causes cookies that don't specify a <ph name="ATTRIBUTE_SAMESITE_NAME">SameSite</ph> attribute to be treated as if they were "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>", removes the requirement for "<ph name="ATTRIBUTE_VALUE_SAMESITE_NONE">SameSite=None</ph>" cookies to carry the "<ph name="ATTRIBUTE_SECURE_NAME">Secure</ph>" attribute, and skips the scheme comparison when evaluating if two sites are same-site. See https://www.chromium.org/administrators/policy-list-3/cookie-legacy-samesite-policies for full description.
 
           For cookies on domains not covered by the patterns specified here, or for all cookies if this policy is not set, the global default value will be used either from the <ph name="LEGACY_SAMESITE_COOKIE_BEHAVIOR_ENABLED_POLICY_NAME">LegacySameSiteCookieBehaviorEnabled</ph> policy, if it is set, or the user's personal configuration otherwise.
 
diff --git a/components/services/app_service/app_service_impl.cc b/components/services/app_service/app_service_impl.cc
index ef0f6ef..e1f183d4 100644
--- a/components/services/app_service/app_service_impl.cc
+++ b/components/services/app_service/app_service_impl.cc
@@ -43,7 +43,8 @@
   kAdd = 0,
   kDeleteForFilter = 1,
   kDeleteForAppId = 2,
-  kMaxValue = kDeleteForAppId,
+  kUpgraded = 3,
+  kMaxValue = kUpgraded,
 };
 
 void Connect(apps::mojom::Publisher* publisher,
@@ -99,16 +100,20 @@
 
 AppServiceImpl::AppServiceImpl(PrefService* profile_prefs,
                                const base::FilePath& profile_dir,
-                               base::OnceClosure read_completed_for_testing)
+                               bool is_share_intents_supported,
+                               base::OnceClosure read_completed_for_testing,
+                               base::OnceClosure write_completed_for_testing)
     : pref_service_(profile_prefs),
       profile_dir_(profile_dir),
+      is_share_intents_supported_(is_share_intents_supported),
       should_write_preferred_apps_to_file_(false),
       writing_preferred_apps_(false),
       task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
           {base::ThreadPool(), base::MayBlock(),
            base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
-      read_completed_for_testing_(std::move(read_completed_for_testing)) {
+      read_completed_for_testing_(std::move(read_completed_for_testing)),
+      write_completed_for_testing_(std::move(write_completed_for_testing)) {
   DCHECK(pref_service_);
   InitializePreferredApps();
 }
@@ -388,11 +393,6 @@
   return preferred_apps_;
 }
 
-void AppServiceImpl::SetWriteCompletedCallbackForTesting(
-    base::OnceClosure testing_callback) {
-  write_completed_for_testing_ = std::move(testing_callback);
-}
-
 void AppServiceImpl::OnPublisherDisconnected(apps::mojom::AppType app_type) {
   publishers_.erase(app_type);
 }
@@ -462,6 +462,7 @@
 
 void AppServiceImpl::ReadCompleted(std::string preferred_apps_string) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  bool preferred_apps_upgraded = false;
   if (preferred_apps_string.empty()) {
     preferred_apps_.Init();
   } else {
@@ -479,9 +480,17 @@
     } else {
       auto preferred_apps =
           apps::ParseValueToPreferredApps(*preferred_apps_value);
+      if (is_share_intents_supported_) {
+        preferred_apps_upgraded = UpgradePreferredApps(preferred_apps);
+      }
       preferred_apps_.Init(preferred_apps);
     }
   }
+  if (preferred_apps_upgraded) {
+    LogPreferredAppUpdateAction(PreferredAppsUpdateAction::kUpgraded);
+    WriteToJSON(profile_dir_, preferred_apps_);
+  }
+
   for (auto& subscriber : subscribers_) {
     subscriber->InitializePreferredApps(preferred_apps_.GetValue());
   }
diff --git a/components/services/app_service/app_service_impl.h b/components/services/app_service/app_service_impl.h
index e0458cd..bc928eef 100644
--- a/components/services/app_service/app_service_impl.h
+++ b/components/services/app_service/app_service_impl.h
@@ -34,7 +34,9 @@
   AppServiceImpl(
       PrefService* profile_prefs,
       const base::FilePath& profile_dir,
-      base::OnceClosure read_completed_for_testing = base::OnceClosure());
+      bool is_share_intents_supported,
+      base::OnceClosure read_completed_for_testing = base::OnceClosure(),
+      base::OnceClosure write_completed_for_testing = base::OnceClosure());
   ~AppServiceImpl() override;
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
@@ -143,6 +145,13 @@
 
   base::FilePath profile_dir_;
 
+  // True if the kIntentHandlingSharing flag is on. This is used to see if
+  // we need to convert the stored preferred app to the new version that
+  // supports sharing.
+  // TODO(crbug.com/1092784): remove when the kIntentHandlingSharing flag is
+  // removed.
+  bool is_share_intents_supported_;
+
   // True if need to write preferred apps to file after the current write is
   // completed.
   bool should_write_preferred_apps_to_file_;
@@ -154,10 +163,10 @@
   // write operation will be operated in sequence.
   scoped_refptr<base::SequencedTaskRunner> const task_runner_;
 
-  base::OnceClosure write_completed_for_testing_;
-
   base::OnceClosure read_completed_for_testing_;
 
+  base::OnceClosure write_completed_for_testing_;
+
   base::WeakPtrFactory<AppServiceImpl> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(AppServiceImpl);
diff --git a/components/services/app_service/app_service_impl_unittest.cc b/components/services/app_service/app_service_impl_unittest.cc
index f41cc8f..2cd42ceb 100644
--- a/components/services/app_service/app_service_impl_unittest.cc
+++ b/components/services/app_service/app_service_impl_unittest.cc
@@ -173,7 +173,8 @@
 
   AppServiceImpl::RegisterProfilePrefs(pref_service_.registry());
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  AppServiceImpl impl(&pref_service_, temp_dir_.GetPath());
+  AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                      /*is_share_intents_supported=*/false);
 
   // Start with one subscriber.
   FakeSubscriber sub0(&impl);
@@ -268,7 +269,8 @@
   // Test Initialize.
   AppServiceImpl::RegisterProfilePrefs(pref_service_.registry());
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  AppServiceImpl impl(&pref_service_, temp_dir_.GetPath());
+  AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                      /*is_share_intents_supported=*/false);
   impl.GetPreferredAppsForTesting().Init();
 
   const char kAppId1[] = "abcdefg";
@@ -377,12 +379,13 @@
   auto intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url);
   {
     base::RunLoop run_loop_read;
+    base::RunLoop run_loop_write;
     AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
-                        run_loop_read.QuitClosure());
+                        /*is_share_intents_supported=*/false,
+                        run_loop_read.QuitClosure(),
+                        run_loop_write.QuitClosure());
     impl.FlushMojoCallsForTesting();
     run_loop_read.Run();
-    base::RunLoop run_loop_write;
-    impl.SetWriteCompletedCallbackForTesting(run_loop_write.QuitClosure());
     impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId1,
                          intent_filter->Clone(),
                          apps_util::CreateIntentFromUrl(filter_url),
@@ -394,6 +397,7 @@
   {
     base::RunLoop run_loop_read;
     AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                        /*is_share_intents_supported=*/false,
                         run_loop_read.QuitClosure());
     impl.FlushMojoCallsForTesting();
     run_loop_read.Run();
@@ -402,4 +406,90 @@
   }
 }
 
+TEST_F(AppServiceImplTest, PreferredAppsUpgrade) {
+  AppServiceImpl::RegisterProfilePrefs(pref_service_.registry());
+  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+  const char kAppId1[] = "abcdefg";
+  const char kAppId2[] = "gfedcba";
+  GURL filter_url1 = GURL("https://www.google.com/abc");
+  GURL filter_url2 = GURL("https://www.abc.com");
+  auto intent_filter1 = apps_util::CreateIntentFilterForUrlScope(filter_url1);
+  auto intent_filter1_with_action = apps_util::CreateIntentFilterForUrlScope(
+      filter_url1, /*with_action_view=*/true);
+  auto intent_filter2_with_action = apps_util::CreateIntentFilterForUrlScope(
+      filter_url2, /*with_action_view=*/true);
+  {
+    base::RunLoop run_loop_read;
+    base::RunLoop run_loop_write;
+    AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                        /*is_share_intents_supported=*/false,
+                        run_loop_read.QuitClosure(),
+                        run_loop_write.QuitClosure());
+    impl.FlushMojoCallsForTesting();
+    run_loop_read.Run();
+    impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId1,
+                         intent_filter1->Clone(),
+                         apps_util::CreateIntentFromUrl(filter_url1),
+                         /*from_publisher=*/false);
+    impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId2,
+                         intent_filter2_with_action->Clone(),
+                         apps_util::CreateIntentFromUrl(filter_url2),
+                         /*from_publisher=*/false);
+    run_loop_write.Run();
+    impl.FlushMojoCallsForTesting();
+
+    // If try to remove old intent filter with filter with action, it wouldn't
+    // work.
+    impl.RemovePreferredAppForFilter(apps::mojom::AppType::kUnknown, kAppId1,
+                                     intent_filter1_with_action->Clone());
+    task_environment_.RunUntilIdle();
+    EXPECT_EQ(kAppId1, impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(
+                           filter_url1));
+    EXPECT_EQ(kAppId2, impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(
+                           filter_url2));
+  }
+
+  // Create a new impl with sharing flag on to initialize preferred apps from
+  // the disk.
+  {
+    base::RunLoop run_loop_read;
+    base::RunLoop run_loop_write;
+    AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                        /*is_share_intents_supported=*/true,
+                        run_loop_read.QuitClosure(),
+                        run_loop_write.QuitClosure());
+    impl.FlushMojoCallsForTesting();
+    run_loop_read.Run();
+    EXPECT_EQ(kAppId1, impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(
+                           filter_url1));
+    EXPECT_EQ(kAppId2, impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(
+                           filter_url2));
+    run_loop_write.Run();
+    impl.FlushMojoCallsForTesting();
+  }
+
+  // Create another new impl to read from disk and see if the filter is upgraded
+  // by trying to delete the entry using new filter.
+  {
+    base::RunLoop run_loop_read;
+    AppServiceImpl impl(&pref_service_, temp_dir_.GetPath(),
+                        /*is_share_intents_supported=*/false,
+                        run_loop_read.QuitClosure());
+    impl.FlushMojoCallsForTesting();
+    run_loop_read.Run();
+    impl.RemovePreferredAppForFilter(apps::mojom::AppType::kUnknown, kAppId1,
+                                     intent_filter1_with_action->Clone());
+    impl.RemovePreferredAppForFilter(apps::mojom::AppType::kUnknown, kAppId2,
+                                     intent_filter2_with_action->Clone());
+    task_environment_.RunUntilIdle();
+    EXPECT_EQ(
+        base::nullopt,
+        impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(filter_url1));
+    EXPECT_EQ(
+        base::nullopt,
+        impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(filter_url2));
+  }
+}
+
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/intent_filter_util.cc b/components/services/app_service/public/cpp/intent_filter_util.cc
index b6b09753..84306c3 100644
--- a/components/services/app_service/public/cpp/intent_filter_util.cc
+++ b/components/services/app_service/public/cpp/intent_filter_util.cc
@@ -125,4 +125,22 @@
   return true;
 }
 
+bool FilterNeedsUpgrade(const apps::mojom::IntentFilterPtr& filter) {
+  for (const auto& condition : filter->conditions) {
+    if (condition->condition_type == apps::mojom::ConditionType::kAction) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void UpgradeFilter(apps::mojom::IntentFilterPtr& filter) {
+  std::vector<apps::mojom::ConditionValuePtr> condition_values;
+  condition_values.push_back(apps_util::MakeConditionValue(
+      apps_util::kIntentActionView, apps::mojom::PatternMatchType::kNone));
+  auto condition = apps_util::MakeCondition(apps::mojom::ConditionType::kAction,
+                                            std::move(condition_values));
+  filter->conditions.insert(filter->conditions.begin(), std::move(condition));
+}
+
 }  // namespace apps_util
diff --git a/components/services/app_service/public/cpp/intent_filter_util.h b/components/services/app_service/public/cpp/intent_filter_util.h
index 49befcb9..a16e9f8 100644
--- a/components/services/app_service/public/cpp/intent_filter_util.h
+++ b/components/services/app_service/public/cpp/intent_filter_util.h
@@ -76,6 +76,13 @@
 // intent with same match level.
 bool FiltersHaveOverlap(const apps::mojom::IntentFilterPtr& filter1,
                         const apps::mojom::IntentFilterPtr& filter2);
+
+// Check if the filter is the older version that doesn't contain action.
+bool FilterNeedsUpgrade(const apps::mojom::IntentFilterPtr& filter);
+
+// Upgrade the filter to contain action view.
+void UpgradeFilter(apps::mojom::IntentFilterPtr& filter);
+
 }  // namespace apps_util
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INTENT_FILTER_UTIL_H_
diff --git a/components/services/app_service/public/cpp/preferred_apps_converter.cc b/components/services/app_service/public/cpp/preferred_apps_converter.cc
index 641a60d..9334af87 100644
--- a/components/services/app_service/public/cpp/preferred_apps_converter.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_converter.cc
@@ -5,6 +5,7 @@
 #include <memory>
 #include <utility>
 
+#include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/preferred_apps_converter.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 
@@ -161,4 +162,15 @@
   return preferred_apps;
 }
 
+bool UpgradePreferredApps(PreferredAppsList::PreferredApps& preferred_apps) {
+  bool preferred_apps_upgraded = false;
+  for (auto& preferred_app : preferred_apps) {
+    if (apps_util::FilterNeedsUpgrade(preferred_app->intent_filter)) {
+      apps_util::UpgradeFilter(preferred_app->intent_filter);
+      preferred_apps_upgraded = true;
+    }
+  }
+  return preferred_apps_upgraded;
+}
+
 }  // namespace apps
diff --git a/components/services/app_service/public/cpp/preferred_apps_converter.h b/components/services/app_service/public/cpp/preferred_apps_converter.h
index 15c3bfae..b31e8a4 100644
--- a/components/services/app_service/public/cpp/preferred_apps_converter.h
+++ b/components/services/app_service/public/cpp/preferred_apps_converter.h
@@ -49,6 +49,10 @@
 PreferredAppsList::PreferredApps ParseValueToPreferredApps(
     const base::Value& preferred_apps_value);
 
+// Upgrade the preferred apps struct to contain action in the filters. Return
+// true if |preferred_apps| is upgraded.
+bool UpgradePreferredApps(PreferredAppsList::PreferredApps& preferred_apps);
+
 }  // namespace apps
 
 #endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PREFERRED_APPS_CONVERTER_H_
diff --git a/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc b/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
index a9d572ce..c62d00b 100644
--- a/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
+++ b/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
@@ -469,3 +469,24 @@
   parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
   EXPECT_TRUE(parsed_entry.empty());
 }
+
+TEST_F(PreferredAppsConverterTest, UpgradePreferredApp) {
+  // Create preferred app with old filter.
+  GURL filter_url = GURL("https://www.google.com/abc");
+  auto old_intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url);
+
+  apps::PreferredAppsList old_preferred_apps;
+  old_preferred_apps.Init();
+  old_preferred_apps.AddPreferredApp(kAppId1, old_intent_filter);
+
+  auto new_intent_filter = apps_util::CreateIntentFilterForUrlScope(
+      filter_url, /*with_action_view=*/true);
+
+  apps::PreferredAppsList new_preferred_apps;
+  new_preferred_apps.Init();
+  new_preferred_apps.AddPreferredApp(kAppId1, new_intent_filter);
+
+  auto old_preferred_apps_value = old_preferred_apps.GetValue();
+  EXPECT_TRUE(apps::UpgradePreferredApps(old_preferred_apps_value));
+  EXPECT_EQ(old_preferred_apps_value, new_preferred_apps.GetReference());
+}
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.cc b/components/spellcheck/renderer/spellcheck_provider_test.cc
index 8583bc5..4563f7e 100644
--- a/components/spellcheck/renderer/spellcheck_provider_test.cc
+++ b/components/spellcheck/renderer/spellcheck_provider_test.cc
@@ -6,8 +6,8 @@
 
 #include <memory>
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "components/spellcheck/common/spellcheck.mojom.h"
 #include "components/spellcheck/common/spellcheck_features.h"
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc
index c2df80a..a083cdc 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -246,6 +246,9 @@
   bookmark_tracker_->set_model_type_state(model_type_state);
   bookmark_tracker_->UpdateLastSyncTime();
   updates_handler.Process(updates, got_new_encryption_requirements);
+  if (bookmark_tracker_->ReuploadBookmarksOnLoadIfNeeded()) {
+    NudgeForCommitIfNeeded();
+  }
   // There are cases when we receive non-empty updates that don't result in
   // model changes (e.g. reflections). In that case, issue a write to persit the
   // progress marker in order to avoid downloading those updates again.
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 7b34f37..f5311950 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -19,6 +19,7 @@
 #include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
 #include "components/sync/base/unique_position.h"
+#include "components/sync/engine/commit_queue.h"
 #include "components/sync/model/data_type_activation_request.h"
 #include "components/sync_bookmarks/switches.h"
 #include "components/undo/bookmark_undo_service.h"
@@ -63,6 +64,7 @@
   data.parent_id = bookmark_info.parent_id;
   data.server_defined_unique_tag = bookmark_info.server_tag;
   data.unique_position = unique_position.ToProto();
+  data.originator_client_item_id = guid;
 
   sync_pb::BookmarkSpecifics* bookmark_specifics =
       data.specifics.mutable_bookmark();
@@ -149,6 +151,24 @@
   AssertState(processor, bookmarks);
 }
 
+class MockCommitQueue : public syncer::CommitQueue {
+ public:
+  MOCK_METHOD0(NudgeForCommit, void());
+};
+
+class ProxyCommitQueue : public syncer::CommitQueue {
+ public:
+  explicit ProxyCommitQueue(CommitQueue* commit_queue)
+      : commit_queue_(commit_queue) {
+    DCHECK(commit_queue_);
+  }
+
+  void NudgeForCommit() override { commit_queue_->NudgeForCommit(); }
+
+ private:
+  CommitQueue* commit_queue_ = nullptr;
+};
+
 class TestBookmarkClientWithFavicon : public bookmarks::TestBookmarkClient {
  public:
   // This method must be used to tell the bookmark_model about favicon.
@@ -192,17 +212,18 @@
 class BookmarkModelTypeProcessorTest : public testing::Test {
  public:
   BookmarkModelTypeProcessorTest()
-      : processor_(&bookmark_undo_service_),
+      : processor_(std::make_unique<BookmarkModelTypeProcessor>(
+            &bookmark_undo_service_)),
         bookmark_model_(bookmarks::TestBookmarkClient::CreateModelWithClient(
             std::make_unique<TestBookmarkClientWithFavicon>())) {
     // TODO(crbug.com/516866): This class assumes model is loaded and sync has
     // started before running tests. We should test other variations (i.e. model
     // isn't loaded yet and/or sync didn't start yet).
-    processor_.SetFaviconService(&favicon_service_);
+    processor_->SetFaviconService(&favicon_service_);
   }
 
   void SimulateModelReadyToSync() {
-    processor_.ModelReadyToSync(
+    processor_->ModelReadyToSync(
         /*metadata_str=*/std::string(), schedule_save_closure_.Get(),
         bookmark_model_.get());
   }
@@ -210,7 +231,19 @@
   void SimulateOnSyncStarting() {
     syncer::DataTypeActivationRequest request;
     request.cache_guid = kCacheGuid;
-    processor_.OnSyncStarting(request, base::DoNothing());
+    processor_->OnSyncStarting(request, base::DoNothing());
+  }
+
+  void SimulateConnectSync() {
+    processor_->ConnectSync(
+        std::make_unique<ProxyCommitQueue>(&mock_commit_queue_));
+  }
+
+  // Simulate browser restart.
+  void ResetModelTypeProcessor() {
+    processor_ =
+        std::make_unique<BookmarkModelTypeProcessor>(&bookmark_undo_service_);
+    processor_->SetFaviconService(&favicon_service_);
   }
 
   void DestroyBookmarkModel() { bookmark_model_.reset(); }
@@ -224,7 +257,8 @@
     return &bookmark_undo_service_;
   }
   favicon::FaviconService* favicon_service() { return &favicon_service_; }
-  BookmarkModelTypeProcessor* processor() { return &processor_; }
+  MockCommitQueue* mock_commit_queue() { return &mock_commit_queue_; }
+  BookmarkModelTypeProcessor* processor() { return processor_.get(); }
   base::MockCallback<base::RepeatingClosure>* schedule_save_closure() {
     return &schedule_save_closure_;
   }
@@ -242,7 +276,8 @@
   NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
   BookmarkUndoService bookmark_undo_service_;
   NiceMock<favicon::MockFaviconService> favicon_service_;
-  BookmarkModelTypeProcessor processor_;
+  NiceMock<MockCommitQueue> mock_commit_queue_;
+  std::unique_ptr<BookmarkModelTypeProcessor> processor_;
   std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
 };
 
@@ -540,6 +575,7 @@
        ShouldNotRecommitEntitiesWhenEncryptionIsUpToDate) {
   SimulateModelReadyToSync();
   SimulateOnSyncStarting();
+  SimulateConnectSync();
   // Initialize the process to make sure the tracker has been created.
   InitWithSyncedBookmarks({}, processor());
   const SyncedBookmarkTracker* tracker = processor()->GetTrackerForTest();
@@ -561,6 +597,7 @@
       /*response_version=*/0);
   response_data.encryption_key_name = kEncryptionKeyName;
 
+  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit()).Times(0);
   syncer::UpdateResponseDataList updates;
   updates.push_back(std::move(response_data));
   processor()->OnUpdateReceived(model_type_state, std::move(updates));
@@ -687,31 +724,49 @@
 
   SimulateModelReadyToSync();
   SimulateOnSyncStarting();
+  SimulateConnectSync();
   InitWithSyncedBookmarks(bookmarks, processor());
 
   sync_pb::BookmarkModelMetadata model_metadata =
       BuildBookmarkModelMetadataWithoutFullTitles();
-  // Ensure that bookmark is legacy.
-  model_metadata.clear_bookmarks_full_title_reuploaded();
   ASSERT_FALSE(processor()->GetTrackerForTest()->HasLocalChanges());
 
+  // Simulate browser restart, enable sync reupload and initialize the processor
+  // again.
+  ResetModelTypeProcessor();
+
   base::test::ScopedFeatureList features;
   features.InitAndEnableFeature(switches::kSyncReuploadBookmarkFullTitles);
-  BookmarkModelTypeProcessor new_processor(bookmark_undo_service());
 
   std::string metadata_str;
   model_metadata.SerializeToString(&metadata_str);
-  new_processor.ModelReadyToSync(metadata_str, base::DoNothing(),
-                                 bookmark_model());
+  processor()->ModelReadyToSync(metadata_str, base::DoNothing(),
+                                bookmark_model());
+  SimulateOnSyncStarting();
+  SimulateConnectSync();
+
+  ASSERT_THAT(processor()->GetTrackerForTest(), NotNull());
+  const SyncedBookmarkTracker::Entity* entity =
+      processor()->GetTrackerForTest()->GetEntityForSyncId(kNodeId);
+  ASSERT_THAT(entity, NotNull());
+
+  // Entity should be synced before until first update is received.
+  ASSERT_FALSE(entity->IsUnsynced());
+  ASSERT_FALSE(processor()
+                   ->GetTrackerForTest()
+                   ->BuildBookmarkModelMetadata()
+                   .bookmarks_full_title_reuploaded());
+
+  // Synchronize with the server and get any updates.
+  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit());
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
+                                syncer::UpdateResponseDataList());
 
   // Check that all entities are unsynced now and metadata is marked as
   // reuploaded.
-  const size_t entities_count =
-      processor()->GetTrackerForTest()->GetAllEntities().size();
-  EXPECT_EQ(1u, new_processor.GetTrackerForTest()
-                    ->GetEntitiesWithLocalChanges(entities_count)
-                    .size());
-  EXPECT_TRUE(new_processor.GetTrackerForTest()
+  EXPECT_TRUE(entity->IsUnsynced());
+  EXPECT_TRUE(processor()
+                  ->GetTrackerForTest()
                   ->BuildBookmarkModelMetadata()
                   .bookmarks_full_title_reuploaded());
 }
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index 0f52a56661..ffa81b8d 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -265,8 +265,6 @@
     return nullptr;
   }
 
-  tracker->ReuploadBookmarksOnLoadIfNeeded();
-
   return tracker;
 }
 
@@ -732,11 +730,11 @@
   return ordered_entities;
 }
 
-void SyncedBookmarkTracker::ReuploadBookmarksOnLoadIfNeeded() {
+bool SyncedBookmarkTracker::ReuploadBookmarksOnLoadIfNeeded() {
   if (bookmarks_full_title_reuploaded_ ||
       !base::FeatureList::IsEnabled(
           switches::kSyncReuploadBookmarkFullTitles)) {
-    return;
+    return false;
   }
   for (const auto& sync_id_and_entity : sync_id_to_entities_map_) {
     const SyncedBookmarkTracker::Entity* entity =
@@ -749,7 +747,8 @@
     }
     IncrementSequenceNumber(entity);
   }
-  bookmarks_full_title_reuploaded_ = true;
+  SetBookmarksFullTitleReuploaded();
+  return true;
 }
 
 void SyncedBookmarkTracker::TraverseAndAppend(
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.h b/components/sync_bookmarks/synced_bookmark_tracker.h
index 05d3f486..efd933a 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.h
+++ b/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -289,6 +289,15 @@
   void CheckAllNodesTracked(
       const bookmarks::BookmarkModel* bookmark_model) const;
 
+  // This method is used to mark all entities except permanent nodes as
+  // unsynced. This will cause reuploading of all bookmarks. The reupload
+  // will be initiated only when the |bookmarks_full_title_reuploaded| field in
+  // BookmarksMetadata is false. This field is used to prevent reuploading after
+  // each browser restart. Returns true if the reupload was initiated.
+  // TODO(crbug.com/1066962): remove this code when most of bookmarks are
+  // reuploaded.
+  bool ReuploadBookmarksOnLoadIfNeeded();
+
  private:
   // Enumeration of possible reasons why persisted metadata are considered
   // corrupted and don't match the bookmark model. Used in UMA metrics. Do not
@@ -334,16 +343,6 @@
   std::vector<const Entity*> ReorderUnsyncedEntitiesExceptDeletions(
       const std::vector<const Entity*>& entities) const;
 
-  // This method is used to mark all entities except permanent nodes as
-  // unsynced. This will cause reuploading of all bookmarks. This reupload
-  // should be initiated only when the |bookmarks_full_title_reuploaded| field
-  // in BookmarksMetadata is false. This field is used to prevent reuploading
-  // after each browser restart. It is set to true in
-  // BuildBookmarkModelMetadata.
-  // TODO(crbug.com/1066962): remove this code when most of bookmarks are
-  // reuploaded.
-  void ReuploadBookmarksOnLoadIfNeeded();
-
   // Recursive method that starting from |node| appends all corresponding
   // entities with updates in top-down order to |ordered_entities|.
   void TraverseAndAppend(const bookmarks::BookmarkNode* node,
diff --git a/components/wifi/wifi_test.cc b/components/wifi/wifi_test.cc
index f184eb03..66b2761c5 100644
--- a/components/wifi/wifi_test.cc
+++ b/components/wifi/wifi_test.cc
@@ -14,7 +14,6 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
@@ -22,6 +21,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -54,7 +54,7 @@
   void Finish(Result result) {
     DCHECK_NE(RESULT_PENDING, result);
     result_ = result;
-    if (base::MessageLoopCurrent::Get())
+    if (base::CurrentThread::Get())
       base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
diff --git a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
index ceca7d9..e4fb424 100644
--- a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
+++ b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -166,6 +166,7 @@
   AddATKEventListener("ATK:AtkText:text-remove");
   AddATKEventListener("ATK:AtkText:text-selection-changed");
   AddATKEventListener("ATK:AtkText:text-caret-moved");
+  AddATKEventListener("ATK:AtkText:text-attributes-changed");
   AddATKEventListener("ATK:AtkSelection:selection-changed");
 }
 
@@ -326,6 +327,7 @@
     "object:row-reordered",
     "object:selection-changed",
     "object:state-changed",
+    "object:text-attributes-changed",
     "object:text-caret-moved",
     "object:text-changed",
     "object:text-selection-changed",
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index 65c9a1193..ce8fb53 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -445,18 +445,20 @@
   *start_offset = FindStartOfStyle(offset, ax::mojom::MoveDirection::kBackward);
   *end_offset = FindStartOfStyle(offset, ax::mojom::MoveDirection::kForward);
 
-  const ui::TextAttributeList& attributes =
-      offset_to_text_attributes().find(*start_offset)->second;
-
   std::ostringstream attributes_stream;
-  for (const ui::TextAttribute& attribute : attributes) {
-    // Don't expose the default language value of "en-US".
-    // TODO(nektar): Determine if it's possible to check against the interface
-    // language.
-    if (attribute.first == "language" && attribute.second == "en-US")
-      continue;
+  auto iter = offset_to_text_attributes().find(*start_offset);
+  if (iter != offset_to_text_attributes().end()) {
+    const ui::TextAttributeList& attributes = iter->second;
 
-    attributes_stream << attribute.first << ":" << attribute.second << ";";
+    for (const ui::TextAttribute& attribute : attributes) {
+      // Don't expose the default language value of "en-US".
+      // TODO(nektar): Determine if it's possible to check against the interface
+      // language.
+      if (attribute.first == "language" && attribute.second == "en-US")
+        continue;
+
+      attributes_stream << attribute.first << ":" << attribute.second << ";";
+    }
   }
   base::string16 attributes_str = base::UTF8ToUTF16(attributes_stream.str());
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 495b8f8bb..f759f67 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -282,6 +282,7 @@
     case ui::AXEventGenerator::Event::SORT_CHANGED:
     case ui::AXEventGenerator::Event::STATE_CHANGED:
     case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+    case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index e4ee1b2..5faaae2 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -78,6 +78,11 @@
     g_signal_emit_by_name(obj, "load_complete");
 }
 
+void BrowserAccessibilityManagerAuraLinux::FireEnabledChangedEvent(
+    BrowserAccessibility* node) {
+  ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnEnabledChanged();
+}
+
 void BrowserAccessibilityManagerAuraLinux::FireExpandedEvent(
     BrowserAccessibility* node,
     bool is_expanded) {
@@ -120,6 +125,11 @@
   ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnSortDirectionChanged();
 }
 
+void BrowserAccessibilityManagerAuraLinux::FireTextAttributesChangedEvent(
+    BrowserAccessibility* node) {
+  ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnTextAttributesChanged();
+}
+
 void BrowserAccessibilityManagerAuraLinux::FireSubtreeCreatedEvent(
     BrowserAccessibility* node) {
   // Sending events during a load would create a lot of spam, don't do that.
@@ -155,6 +165,9 @@
     case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
       FireEvent(node, ax::mojom::Event::kDocumentTitleChanged);
       break;
+    case ui::AXEventGenerator::Event::ENABLED_CHANGED:
+      FireEnabledChangedEvent(node);
+      break;
     case ui::AXEventGenerator::Event::EXPANDED:
       FireExpandedEvent(node, true);
       break;
@@ -190,7 +203,55 @@
     case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
       FireEvent(node, ax::mojom::Event::kInvalidStatusChanged);
       break;
-    default:
+    case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
+      FireTextAttributesChangedEvent(node);
+      break;
+    case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
+    case ui::AXEventGenerator::Event::ALERT:
+    case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
+    case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
+    case ui::AXEventGenerator::Event::BUSY_CHANGED:
+    case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
+    case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
+    case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
+    case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
+    case ui::AXEventGenerator::Event::FOCUS_CHANGED:
+    case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
+    case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+    case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+    case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
+    case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+    case ui::AXEventGenerator::Event::IGNORED_CHANGED:
+    case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
+    case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
+    case ui::AXEventGenerator::Event::LABELED_BY_CHANGED:
+    case ui::AXEventGenerator::Event::LANGUAGE_CHANGED:
+    case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
+    case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+    case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
+    case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
+    case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
+    case ui::AXEventGenerator::Event::READONLY_CHANGED:
+    case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::REQUIRED_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::ROLE_CHANGED:
+    case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
+    case ui::AXEventGenerator::Event::SCROLL_HORIZONTAL_POSITION_CHANGED:
+    case ui::AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED:
+    case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
+    case ui::AXEventGenerator::Event::STATE_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
+    case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
       // Need to implement.
       break;
   }
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index d86cba0..834f2db 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -35,11 +35,13 @@
                           BrowserAccessibility* node) override;
 
   void FireSelectedEvent(BrowserAccessibility* node);
+  void FireEnabledChangedEvent(BrowserAccessibility* node);
   void FireExpandedEvent(BrowserAccessibility* node, bool is_expanded);
   void FireLoadingEvent(BrowserAccessibility* node, bool is_loading);
   void FireNameChangedEvent(BrowserAccessibility* node);
   void FireDescriptionChangedEvent(BrowserAccessibility* node);
   void FireSortDirectionChangedEvent(BrowserAccessibility* node);
+  void FireTextAttributesChangedEvent(BrowserAccessibility* node);
   void FireSubtreeCreatedEvent(BrowserAccessibility* node);
   void OnFindInPageResult(int request_id,
                           int match_index,
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 04bbb885..aaf53dd 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -451,6 +451,7 @@
     case ui::AXEventGenerator::Event::SORT_CHANGED:
     case ui::AXEventGenerator::Event::STATE_CHANGED:
     case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+    case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index 443c5f2..aa5bc73 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -350,6 +350,10 @@
         FireUiaAccessibilityEvent(UIA_MenuOpenedEventId, node);
       }
       break;
+    case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
+      FireWinAccessibilityEvent(IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, node);
+      FireUiaTextContainerEvent(UIA_Text_TextChangedEventId, node);
+      break;
     case ui::AXEventGenerator::Event::VALUE_CHANGED:
       FireWinAccessibilityEvent(EVENT_OBJECT_VALUECHANGE, node);
       if (node->GetData().IsRangeValueSupported()) {
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 1ed75c2..c07cb45 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -765,6 +765,11 @@
 }
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+                       AccessibilityEventsStyleChanged) {
+  RunEventTest(FILE_PATH_LITERAL("style-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
                        AccessibilityEventsTabindexAddedOnPlainDiv) {
   RunEventTest(FILE_PATH_LITERAL("tabindex-added-on-plain-div.html"));
 }
diff --git a/content/browser/android/synchronous_compositor_host.cc b/content/browser/android/synchronous_compositor_host.cc
index 7afaf4e..7691419 100644
--- a/content/browser/android/synchronous_compositor_host.cc
+++ b/content/browser/android/synchronous_compositor_host.cc
@@ -464,9 +464,6 @@
 
 void SynchronousCompositorHost::UpdatePresentedFrameToken(
     uint32_t frame_token) {
-  if (!viz::FrameTokenGT(frame_token, last_frame_token_))
-    return;
-  last_frame_token_ = frame_token;
   rwhva_->FrameTokenChangedForSynchronousCompositor(frame_token,
                                                     root_scroll_offset_);
 }
diff --git a/content/browser/android/synchronous_compositor_host.h b/content/browser/android/synchronous_compositor_host.h
index e3b50b3d..aeb7236e 100644
--- a/content/browser/android/synchronous_compositor_host.h
+++ b/content/browser/android/synchronous_compositor_host.h
@@ -180,9 +180,6 @@
   float min_page_scale_factor_ = 0.f;
   float max_page_scale_factor_ = 0.f;
 
-  // From viz display.
-  uint32_t last_frame_token_ = 0u;
-
   scoped_refptr<SynchronousCompositorSyncCallBridge> bridge_;
 
   // Indicates whether and for what reason a request for begin frames has been
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index afec55c8..50536c8 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -21,7 +21,6 @@
 #include "base/logging.h"
 #include "base/memory/memory_pressure_monitor.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
@@ -39,6 +38,7 @@
 #include "base/strings/string_split.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/system/system_monitor.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool/initialization_util.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
@@ -673,7 +673,7 @@
   // PostMainMessageLoopStart() below.
 
   TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart");
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   InitializeMainThread();
 }
 
@@ -1168,7 +1168,7 @@
 
   // Register the main thread. The main thread's task runner should already have
   // been initialized in MainMessageLoopStart() (or before if
-  // MessageLoopCurrent::Get() was externally provided).
+  // CurrentThread::Get() was externally provided).
   DCHECK(base::ThreadTaskRunnerHandle::IsSet());
   main_thread_.reset(new BrowserThreadImpl(
       BrowserThread::UI, base::ThreadTaskRunnerHandle::Get()));
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 1371b1e..01fac18fe 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -13,9 +13,9 @@
 #include "base/check_op.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/sequence_checker.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/task_executor.h"
 #include "base/threading/platform_thread.h"
@@ -121,7 +121,7 @@
     //
     // In unit tests, usage of the  FileDescriptorWatcher API is already allowed
     // if the UI thread is running a MessageLoopForIO.
-    if (!base::MessageLoopCurrentForIO::IsSet()) {
+    if (!base::CurrentIOThread::IsSet()) {
       file_descriptor_watcher_.emplace(GetIOThreadTaskRunner({}));
     }
     base::FileDescriptorWatcher::AssertAllowed();
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc
index 40775af..fb15a7e1 100644
--- a/content/browser/browser_thread_unittest.cc
+++ b/content/browser/browser_thread_unittest.cc
@@ -10,12 +10,12 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
@@ -160,7 +160,7 @@
 };
 
 class UIThreadDestructionObserver
-    : public base::MessageLoopCurrent::DestructionObserver {
+    : public base::CurrentThread::DestructionObserver {
  public:
   explicit UIThreadDestructionObserver(bool* did_shutdown,
                                        base::OnceClosure callback)
@@ -173,10 +173,10 @@
 
  private:
   static void Watch(UIThreadDestructionObserver* observer) {
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(observer);
+    base::CurrentThread::Get()->AddDestructionObserver(observer);
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     // Ensure that even during MessageLoop teardown the BrowserThread ID is
     // correctly associated with this thread and the BrowserThreadTaskRunner
@@ -184,7 +184,7 @@
     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
     EXPECT_TRUE(ui_task_runner_->BelongsToCurrentThread());
 
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
     *did_shutdown_ = true;
     callback_task_runner_->PostTask(FROM_HERE, std::move(callback_));
   }
diff --git a/content/browser/frame_host/popup_menu_helper_mac.mm b/content/browser/frame_host/popup_menu_helper_mac.mm
index 66c8b3bd..c761d7d 100644
--- a/content/browser/frame_host/popup_menu_helper_mac.mm
+++ b/content/browser/frame_host/popup_menu_helper_mac.mm
@@ -6,8 +6,8 @@
 
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/scoped_sending_event.h"
-#include "base/message_loop/message_loop_current.h"
 #import "base/message_loop/message_pump_mac.h"
+#include "base/task/current_thread.h"
 #import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
@@ -81,7 +81,7 @@
 
   {
     // Make sure events can be pumped while the menu is up.
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedNestableTaskAllower allow;
 
     // One of the events that could be pumped is |window.close()|.
     // User-initiated event-tracking loops protect against this by
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index d062c8d..471b74d 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -8551,11 +8551,6 @@
                                                  discard_duplicates);
 }
 
-void RenderFrameHostImpl::AddInspectorIssue(
-    blink::mojom::InspectorIssueInfoPtr info) {
-  GetAssociatedLocalFrame()->AddInspectorIssue(std::move(info));
-}
-
 void RenderFrameHostImpl::LogCannotCommitUrlCrashKeys(
     const GURL& url,
     bool is_same_document_navigation,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 1f83d41..ec67a697 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -301,7 +301,6 @@
   gfx::NativeView GetNativeView() override;
   void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,
                            const std::string& message) override;
-  void AddInspectorIssue(blink::mojom::InspectorIssueInfoPtr info);
   void ExecuteJavaScript(const base::string16& javascript,
                          JavaScriptResultCallback callback) override;
   void ExecuteJavaScriptInIsolatedWorld(const base::string16& javascript,
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index ec711b4..d6f0f9b 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -5,6 +5,7 @@
 #include "content/browser/media/media_web_contents_observer.h"
 
 #include <memory>
+#include <tuple>
 
 #include "build/build_config.h"
 #include "content/browser/media/audible_metrics.h"
@@ -29,17 +30,6 @@
   return metrics;
 }
 
-// Returns true if |player_id| exists in |player_map|.
-bool MediaPlayerEntryExists(
-    const MediaPlayerId& player_id,
-    const MediaWebContentsObserver::ActiveMediaPlayerMap& player_map) {
-  const auto& players = player_map.find(player_id.render_frame_host);
-  if (players == player_map.end())
-    return false;
-
-  return players->second.find(player_id.delegate_id) != players->second.end();
-}
-
 #if defined(OS_ANDROID)
 static void SuspendAllMediaPlayersInRenderFrame(
     RenderFrameHost* render_frame_host) {
@@ -50,16 +40,91 @@
 
 }  // anonymous namespace
 
+// Maintains state for a single player.  Issues WebContents and power-related
+// notifications appropriate for state changes.
+class MediaWebContentsObserver::PlayerInfo {
+ public:
+  PlayerInfo(const MediaPlayerId& id, MediaWebContentsObserver* observer)
+      : id_(id), observer_(observer) {}
+
+  ~PlayerInfo() {
+    if (is_playing_) {
+      NotifyPlayerStopped(WebContentsObserver::MediaStoppedReason::kUnspecified,
+                          MediaPowerExperimentManager::NotificationMode::kSkip);
+    }
+  }
+
+  PlayerInfo(const PlayerInfo&) = delete;
+  PlayerInfo& operator=(const PlayerInfo&) = delete;
+
+  void set_has_audio(bool has_audio) { has_audio_ = has_audio; }
+
+  bool has_video() const { return has_video_; }
+  void set_has_video(bool has_video) { has_video_ = has_video; }
+
+  bool is_playing() const { return is_playing_; }
+
+  void SetIsPlaying() {
+    DCHECK(!is_playing_);
+    is_playing_ = true;
+
+    NotifyPlayerStarted();
+  }
+
+  void SetIsStopped(bool reached_end_of_stream) {
+    DCHECK(is_playing_);
+    is_playing_ = false;
+
+    NotifyPlayerStopped(
+        reached_end_of_stream
+            ? WebContentsObserver::MediaStoppedReason::kReachedEndOfStream
+            : WebContentsObserver::MediaStoppedReason::kUnspecified,
+        MediaPowerExperimentManager::NotificationMode::kNotify);
+  }
+
+ private:
+  void NotifyPlayerStarted() {
+    observer_->web_contents_impl()->MediaStartedPlaying(
+        WebContentsObserver::MediaPlayerInfo(has_video_, has_audio_), id_);
+
+    if (observer_->power_experiment_manager_) {
+      // Bind the callback to a WeakPtr for the frame, so that we won't try to
+      // notify the frame after it's been destroyed.
+      observer_->power_experiment_manager_->PlayerStarted(
+          id_, base::BindRepeating(
+                   &MediaWebContentsObserver::OnExperimentStateChanged,
+                   observer_->GetWeakPtrForFrame(id_.render_frame_host), id_));
+    }
+  }
+
+  void NotifyPlayerStopped(
+      WebContentsObserver::MediaStoppedReason stopped_reason,
+      MediaPowerExperimentManager::NotificationMode notification_mode) {
+    observer_->web_contents_impl()->MediaStoppedPlaying(
+        WebContentsObserver::MediaPlayerInfo(has_video_, has_audio_), id_,
+        stopped_reason);
+
+    if (observer_->power_experiment_manager_) {
+      observer_->power_experiment_manager_->PlayerStopped(id_,
+                                                          notification_mode);
+    }
+  }
+
+  const MediaPlayerId id_;
+  MediaWebContentsObserver* const observer_;
+
+  bool has_audio_ = false;
+  bool has_video_ = false;
+  bool is_playing_ = false;
+};
+
 MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
     : WebContentsObserver(web_contents),
       audible_metrics_(GetAudibleMetrics()),
       session_controllers_manager_(this),
       power_experiment_manager_(MediaPowerExperimentManager::Instance()) {}
 
-MediaWebContentsObserver::~MediaWebContentsObserver() {
-  // Remove all players so that the experiment manager is notified.
-  RemoveAllPlayers();
-}
+MediaWebContentsObserver::~MediaWebContentsObserver() = default;
 
 void MediaWebContentsObserver::WebContentsDestroyed() {
   AudioStreamMonitor* audio_stream_monitor =
@@ -70,12 +135,17 @@
                           !web_contents()->IsAudioMuted());
 
   // Remove all players so that the experiment manager is notified.
-  RemoveAllPlayers();
+  player_info_map_.clear();
 }
 
 void MediaWebContentsObserver::RenderFrameDeleted(
     RenderFrameHost* render_frame_host) {
-  ClearWakeLocks(render_frame_host);
+  base::EraseIf(
+      player_info_map_,
+      [render_frame_host](const PlayerInfoMap::value_type& id_and_player_info) {
+        return render_frame_host == id_and_player_info.first.render_frame_host;
+      });
+
   session_controllers_manager_.RenderFrameDeleted(render_frame_host);
 
   if (fullscreen_player_ &&
@@ -107,7 +177,10 @@
     return false;
 
   // Check that the player is active.
-  return MediaPlayerEntryExists(*fullscreen_player_, active_video_players_);
+  if (const PlayerInfo* player_info = GetPlayerInfo(*fullscreen_player_))
+    return player_info->is_playing() && player_info->has_video();
+
+  return false;
 }
 
 bool MediaWebContentsObserver::IsPictureInPictureAllowedForFullscreenVideo()
@@ -174,10 +247,16 @@
 
 bool MediaWebContentsObserver::IsPlayerActive(
     const MediaPlayerId& player_id) const {
-  if (MediaPlayerEntryExists(player_id, active_video_players_))
-    return true;
+  if (const PlayerInfo* player_info = GetPlayerInfo(player_id))
+    return player_info->is_playing();
 
-  return MediaPlayerEntryExists(player_id, active_audio_players_);
+  return false;
+}
+
+MediaWebContentsObserver::PlayerInfo* MediaWebContentsObserver::GetPlayerInfo(
+    const MediaPlayerId& id) const {
+  const auto it = player_info_map_.find(id);
+  return it != player_info_map_.end() ? it->second.get() : nullptr;
 }
 
 void MediaWebContentsObserver::OnMediaDestroyed(
@@ -191,20 +270,11 @@
                                              int delegate_id,
                                              bool reached_end_of_stream) {
   const MediaPlayerId player_id(render_frame_host, delegate_id);
-  const bool removed_audio =
-      RemoveMediaPlayerEntry(player_id, &active_audio_players_);
-  const bool removed_video =
-      RemoveMediaPlayerEntry(player_id, &active_video_players_);
+  PlayerInfo* player_info = GetPlayerInfo(player_id);
+  if (!player_info || !player_info->is_playing())
+    return;
 
-  if (removed_audio || removed_video) {
-    // Notify observers the player has been "paused".
-    web_contents_impl()->MediaStoppedPlaying(
-        WebContentsObserver::MediaPlayerInfo(removed_video, removed_audio),
-        player_id,
-        reached_end_of_stream
-            ? WebContentsObserver::MediaStoppedReason::kReachedEndOfStream
-            : WebContentsObserver::MediaStoppedReason::kUnspecified);
-  }
+  player_info->SetIsStopped(reached_end_of_stream);
 
   if (reached_end_of_stream)
     session_controllers_manager_.OnEnd(player_id);
@@ -218,21 +288,32 @@
     bool has_video,
     bool has_audio,
     media::MediaContentType media_content_type) {
-  const MediaPlayerId id(render_frame_host, delegate_id);
-  if (has_audio)
-    AddMediaPlayerEntry(id, &active_audio_players_);
+  const MediaPlayerId player_id(render_frame_host, delegate_id);
 
-  if (has_video)
-    AddMediaPlayerEntry(id, &active_video_players_);
+  // TODO(wdzierzanowski): OnMediaPlaying() should only ever be called for a
+  // player that has started playing (crbug.com/1091203).  For now, we must
+  // handle updating the metadata here as well.
+  PlayerInfo* player_info = GetPlayerInfo(player_id);
+  if (!player_info) {
+    PlayerInfoMap::iterator it;
+    std::tie(it, std::ignore) = player_info_map_.emplace(
+        player_id, std::make_unique<PlayerInfo>(player_id, this));
+    player_info = it->second.get();
+  }
+
+  player_info->set_has_audio(has_audio);
+  player_info->set_has_video(has_video);
 
   if (!session_controllers_manager_.RequestPlay(
-          id, has_audio, media_content_type, has_video)) {
+          player_id, has_audio, media_content_type, has_video)) {
+    // Return early to avoid spamming WebContents with playing/stopped
+    // notifications.  If RequestPlay() fails, media session will send a pause
+    // signal right away.
     return;
   }
 
-  // Notify observers of the new player.
-  web_contents_impl()->MediaStartedPlaying(
-      WebContentsObserver::MediaPlayerInfo(has_video, has_audio), id);
+  if (!player_info->is_playing())
+    player_info->SetIsPlaying();
 }
 
 void MediaWebContentsObserver::OnMediaEffectivelyFullscreenChanged(
@@ -282,31 +363,6 @@
       MediaPlayerId(render_frame_host, delegate_id), available);
 }
 
-void MediaWebContentsObserver::ClearWakeLocks(
-    RenderFrameHost* render_frame_host) {
-  std::set<MediaPlayerId> video_players;
-  RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_,
-                              &video_players);
-  std::set<MediaPlayerId> audio_players;
-  RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_,
-                              &audio_players);
-
-  std::set<MediaPlayerId> removed_players;
-  std::set_union(video_players.begin(), video_players.end(),
-                 audio_players.begin(), audio_players.end(),
-                 std::inserter(removed_players, removed_players.end()));
-
-  // Notify all observers the player has been "paused".
-  for (const auto& id : removed_players) {
-    auto it = video_players.find(id);
-    bool was_video = (it != video_players.end());
-    bool was_audio = (audio_players.find(id) != audio_players.end());
-    web_contents_impl()->MediaStoppedPlaying(
-        WebContentsObserver::MediaPlayerInfo(was_video, was_audio), id,
-        WebContentsObserver::MediaStoppedReason::kUnspecified);
-  }
-}
-
 device::mojom::WakeLock* MediaWebContentsObserver::GetAudioWakeLock() {
   // Here is a lazy binding, and will not reconnect after connection error.
   if (!audio_wake_lock_) {
@@ -350,66 +406,6 @@
   session_controllers_manager_.OnMediaPositionStateChanged(id, position);
 }
 
-void MediaWebContentsObserver::AddMediaPlayerEntry(
-    const MediaPlayerId& id,
-    ActiveMediaPlayerMap* player_map) {
-  (*player_map)[id.render_frame_host].insert(id.delegate_id);
-  if (power_experiment_manager_) {
-    // Bind the callback to a WeakPtr for the frame, so that we won't try to
-    // notify the frame after it's been destroyed.
-    power_experiment_manager_->PlayerStarted(
-        id,
-        base::BindRepeating(&MediaWebContentsObserver::OnExperimentStateChanged,
-                            GetWeakPtrForFrame(id.render_frame_host), id));
-  }
-}
-
-bool MediaWebContentsObserver::RemoveMediaPlayerEntry(
-    const MediaPlayerId& id,
-    ActiveMediaPlayerMap* player_map) {
-  // If the power experiment is running, then notify it.
-  if (power_experiment_manager_)
-    power_experiment_manager_->PlayerStopped(id);
-
-  auto it = player_map->find(id.render_frame_host);
-  if (it == player_map->end())
-    return false;
-
-  // Remove the player.
-  bool did_remove = it->second.erase(id.delegate_id) == 1;
-  if (!did_remove)
-    return false;
-
-  // If there are no players left, remove the map entry.
-  if (it->second.empty())
-    player_map->erase(it);
-
-  return true;
-}
-
-void MediaWebContentsObserver::RemoveAllMediaPlayerEntries(
-    RenderFrameHost* render_frame_host,
-    ActiveMediaPlayerMap* player_map,
-    std::set<MediaPlayerId>* removed_players) {
-  auto it = player_map->find(render_frame_host);
-  if (it == player_map->end())
-    return;
-
-  for (int delegate_id : it->second) {
-    MediaPlayerId id(render_frame_host, delegate_id);
-    removed_players->insert(id);
-
-    // Since the player is being destroyed, don't bother to notify it if it's
-    // no longer the active experiment.
-    if (power_experiment_manager_) {
-      power_experiment_manager_->PlayerStopped(
-          id, MediaPowerExperimentManager::NotificationMode::kSkip);
-    }
-  }
-
-  player_map->erase(it);
-}
-
 WebContentsImpl* MediaWebContentsObserver::web_contents_impl() const {
   return static_cast<WebContentsImpl*>(web_contents());
 }
@@ -428,26 +424,6 @@
           id.render_frame_host->GetRoutingID(), id.delegate_id, is_starting));
 }
 
-void MediaWebContentsObserver::RemoveAllPlayers(
-    ActiveMediaPlayerMap* player_map) {
-  if (power_experiment_manager_) {
-    for (auto& iter : *player_map) {
-      for (auto delegate_id : iter.second) {
-        MediaPlayerId id(iter.first, delegate_id);
-        power_experiment_manager_->PlayerStopped(
-            id, MediaPowerExperimentManager::NotificationMode::kSkip);
-      }
-    }
-  }
-
-  player_map->clear();
-}
-
-void MediaWebContentsObserver::RemoveAllPlayers() {
-  RemoveAllPlayers(&active_audio_players_);
-  RemoveAllPlayers(&active_video_players_);
-}
-
 base::WeakPtr<MediaWebContentsObserver>
 MediaWebContentsObserver::GetWeakPtrForFrame(
     RenderFrameHost* render_frame_host) {
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index f2a6d09..de74774 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -9,9 +9,10 @@
 
 #include <map>
 #include <memory>
-#include <set>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "build/build_config.h"
 #include "content/browser/media/media_power_experiment_manager.h"
 #include "content/browser/media/session/media_session_controllers_manager.h"
@@ -54,9 +55,6 @@
   explicit MediaWebContentsObserver(WebContents* web_contents);
   ~MediaWebContentsObserver() override;
 
-  using PlayerSet = std::set<int>;
-  using ActiveMediaPlayerMap = std::map<RenderFrameHost*, PlayerSet>;
-
   // Called by WebContentsImpl when the audible state may have changed.
   void MaybeUpdateAudibleState();
 
@@ -113,6 +111,16 @@
   }
 
  private:
+  class PlayerInfo;
+  friend class PlayerInfo;
+
+  using PlayerInfoMap =
+      base::flat_map<MediaPlayerId, std::unique_ptr<PlayerInfo>>;
+
+  // Returns the PlayerInfo associated with |id|, or nullptr if no such
+  // PlayerInfo exists.
+  PlayerInfo* GetPlayerInfo(const MediaPlayerId& id) const;
+
   void OnMediaDestroyed(RenderFrameHost* render_frame_host, int delegate_id);
   void OnMediaPaused(RenderFrameHost* render_frame_host,
                      int delegate_id,
@@ -140,9 +148,6 @@
                                              int delegate_id,
                                              bool available);
 
-  // Clear |render_frame_host|'s tracking entry for its WakeLocks.
-  void ClearWakeLocks(RenderFrameHost* render_frame_host);
-
   device::mojom::WakeLock* GetAudioWakeLock();
 
   // WakeLock related methods for audio and video.
@@ -150,18 +155,6 @@
   void CancelAudioLock();
   void UpdateVideoLock();
 
-  // Helper methods for adding or removing player entries in |player_map|.
-  void AddMediaPlayerEntry(const MediaPlayerId& id,
-                           ActiveMediaPlayerMap* player_map);
-  // Returns true if an entry is actually removed.
-  bool RemoveMediaPlayerEntry(const MediaPlayerId& id,
-                              ActiveMediaPlayerMap* player_map);
-  // Removes all entries from |player_map| for |render_frame_host|. Removed
-  // entries are added to |removed_players|.
-  void RemoveAllMediaPlayerEntries(RenderFrameHost* render_frame_host,
-                                   ActiveMediaPlayerMap* player_map,
-                                   std::set<MediaPlayerId>* removed_players);
-
   // Convenience method that casts web_contents() to a WebContentsImpl*.
   WebContentsImpl* web_contents_impl() const;
 
@@ -169,12 +162,6 @@
   // active players list, which is fine.
   void OnExperimentStateChanged(MediaPlayerId id, bool is_starting);
 
-  // Remove all players from |player_map|.
-  void RemoveAllPlayers(ActiveMediaPlayerMap* player_map);
-
-  // Remove all players.
-  void RemoveAllPlayers();
-
   // Return a weak pointer to |this| that's local to |render_frame_host|, in the
   // sense that we can cancel all of the ptrs to one frame without cancelling
   // pointers for any of the others.
@@ -185,8 +172,7 @@
   AudibleMetrics* audible_metrics_;
 
   // Tracking variables and associated wake locks for media playback.
-  ActiveMediaPlayerMap active_audio_players_;
-  ActiveMediaPlayerMap active_video_players_;
+  PlayerInfoMap player_info_map_;
   mojo::Remote<device::mojom::WakeLock> audio_wake_lock_;
   base::Optional<MediaPlayerId> fullscreen_player_;
   base::Optional<bool> picture_in_picture_allowed_in_fullscreen_;
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc
index 3723d4a..5d81a819 100644
--- a/content/browser/network_service_client.cc
+++ b/content/browser/network_service_client.cc
@@ -37,7 +37,7 @@
 #endif
 
 #if defined(OS_MACOSX)
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #endif
 
 namespace content {
@@ -65,7 +65,7 @@
 {
 
 #if defined(OS_MACOSX)
-  if (base::MessageLoopCurrentForUI::IsSet())  // Not set in some unit tests.
+  if (base::CurrentUIThread::IsSet())  // Not set in some unit tests.
     net::CertDatabase::GetInstance()->StartListeningForKeychainEvents();
 #endif
 
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 0929cab..20f1eb7d 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1942,7 +1942,7 @@
 
   // We want to be notified of IO message loop destruction to delete the thread
   // and the device managers.
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  base::CurrentThread::Get()->AddDestructionObserver(this);
 
   video_capture_manager_ =
       new VideoCaptureManager(std::move(video_capture_provider),
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 4468b5c9..f01af6b 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -37,10 +37,10 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/power_monitor/power_observer.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
 #include "content/browser/media/media_devices_util.h"
@@ -78,7 +78,7 @@
 // using callbacks.
 class CONTENT_EXPORT MediaStreamManager
     : public MediaStreamProviderListener,
-      public base::MessageLoopCurrent::DestructionObserver,
+      public base::CurrentThread::DestructionObserver,
       public base::PowerObserver {
  public:
   // Callback to deliver the result of a media access request.
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 53722c3..25f9f21 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -376,7 +376,7 @@
   }
 
   // media_stream_manager_ needs to outlive task_environment_ because it is a
-  // MessageLoopCurrent::DestructionObserver. audio_manager_ needs to outlive
+  // CurrentThread::DestructionObserver. audio_manager_ needs to outlive
   // task_environment_ because it uses the underlying message loop.
   std::unique_ptr<MediaStreamManager> media_stream_manager_;
   std::unique_ptr<MockMediaObserver> media_observer_;
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc
index 7094b06e..8ed9b49 100644
--- a/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -303,7 +303,7 @@
   }
 
   // |media_stream_manager_| needs to outlive |task_environment_| because it is
-  // a MessageLoopCurrent::DestructionObserver.
+  // a CurrentThread::DestructionObserver.
   std::unique_ptr<MediaStreamManager> media_stream_manager_;
   const content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<media::AudioManager> audio_manager_;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 32fb705..fbb357d 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -22,13 +22,13 @@
 #include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_tick_clock.h"
@@ -3042,7 +3042,7 @@
 }
 
 void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   if (!pending_surface_browser_snapshots_.empty()) {
     GetView()->CopyFromSurface(
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 3a7abe75..5acdd6e 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1104,6 +1104,10 @@
 void RenderWidgetHostViewAndroid::FrameTokenChangedForSynchronousCompositor(
     uint32_t frame_token,
     const gfx::ScrollOffset& root_scroll_offset) {
+  if (!viz::FrameTokenGT(frame_token, sync_compositor_last_frame_token_))
+    return;
+  sync_compositor_last_frame_token_ = frame_token;
+
   if (host() && frame_token) {
     if (!using_viz_for_webview_) {
       // For viz it's reported through FrameSinkManager.
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index ede0fee..1affef2 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -502,6 +502,8 @@
   const bool using_browser_compositor_;
   const bool using_viz_for_webview_;
   std::unique_ptr<SynchronousCompositorHost> sync_compositor_;
+  uint32_t sync_compositor_last_frame_token_ = 0u;
+
 
   SynchronousCompositorClient* synchronous_compositor_client_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 5a1a9b4a..521ae2d 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -8,10 +8,10 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/browser/gpu/compositor_util.h"
diff --git a/content/browser/scheduler/responsiveness/message_loop_observer.cc b/content/browser/scheduler/responsiveness/message_loop_observer.cc
index df04ccc..5589e35 100644
--- a/content/browser/scheduler/responsiveness/message_loop_observer.cc
+++ b/content/browser/scheduler/responsiveness/message_loop_observer.cc
@@ -4,7 +4,7 @@
 
 #include "content/browser/scheduler/responsiveness/message_loop_observer.h"
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 
 namespace content {
 namespace responsiveness {
@@ -14,13 +14,13 @@
     DidProcessTaskCallback did_process_task_callback)
     : will_process_task_callback_(std::move(will_process_task_callback)),
       did_process_task_callback_(std::move(did_process_task_callback)) {
-  base::MessageLoopCurrent::Get()->SetAddQueueTimeToTasks(true);
-  base::MessageLoopCurrent::Get()->AddTaskObserver(this);
+  base::CurrentThread::Get()->SetAddQueueTimeToTasks(true);
+  base::CurrentThread::Get()->AddTaskObserver(this);
 }
 
 MessageLoopObserver::~MessageLoopObserver() {
-  base::MessageLoopCurrent::Get()->RemoveTaskObserver(this);
-  base::MessageLoopCurrent::Get()->SetAddQueueTimeToTasks(false);
+  base::CurrentThread::Get()->RemoveTaskObserver(this);
+  base::CurrentThread::Get()->SetAddQueueTimeToTasks(false);
 }
 
 void MessageLoopObserver::WillProcessTask(const base::PendingTask& pending_task,
diff --git a/content/browser/scheduler/responsiveness/native_event_observer.cc b/content/browser/scheduler/responsiveness/native_event_observer.cc
index ff9f906a..68771d3 100644
--- a/content/browser/scheduler/responsiveness/native_event_observer.cc
+++ b/content/browser/scheduler/responsiveness/native_event_observer.cc
@@ -21,7 +21,7 @@
 #endif
 
 #if defined(OS_WIN)
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #endif
 
 namespace content {
@@ -65,10 +65,10 @@
 
 #if defined(OS_WIN)
 void NativeEventObserver::RegisterObserver() {
-  base::MessageLoopCurrentForUI::Get()->AddMessagePumpObserver(this);
+  base::CurrentUIThread::Get()->AddMessagePumpObserver(this);
 }
 void NativeEventObserver::DeregisterObserver() {
-  base::MessageLoopCurrentForUI::Get()->RemoveMessagePumpObserver(this);
+  base::CurrentUIThread::Get()->RemoveMessagePumpObserver(this);
 }
 void NativeEventObserver::WillDispatchMSG(const MSG& msg) {
   will_run_event_callback_.Run(&msg);
diff --git a/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc b/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc
index 86883be..49c62f2 100644
--- a/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc
+++ b/content/browser/screenlock_monitor/screenlock_monitor_unittest.cc
@@ -5,8 +5,8 @@
 #include "content/browser/screenlock_monitor/screenlock_monitor.h"
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "content/browser/screenlock_monitor/screenlock_monitor_source.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,7 +16,7 @@
 class ScreenlockMonitorTestSource : public ScreenlockMonitorSource {
  public:
   ScreenlockMonitorTestSource() {
-    DCHECK(base::MessageLoopCurrent::Get())
+    DCHECK(base::CurrentThread::Get())
         << "ScreenlocMonitorTestSource requires a MessageLoop.";
   }
   ~ScreenlockMonitorTestSource() override = default;
diff --git a/content/browser/service_worker/service_worker_container_host_unittest.cc b/content/browser/service_worker/service_worker_container_host_unittest.cc
index a74b620..962d219 100644
--- a/content/browser/service_worker/service_worker_container_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_container_host_unittest.cc
@@ -41,7 +41,6 @@
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 #include "url/url_util.h"
 
 namespace content {
@@ -103,10 +102,6 @@
   std::vector<AllowServiceWorkerCallLog> logs_;
 };
 
-blink::mojom::DedicatedWorkerToken CreateDedicatedWorkerToken() {
-  return blink::mojom::DedicatedWorkerToken(base::UnguessableToken::Create());
-}
-
 }  // namespace
 
 class ServiceWorkerContainerHostTest : public testing::Test {
@@ -1033,7 +1028,7 @@
   ASSERT_TRUE(
       base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
   TestReservedClientsAreNotExposed(
-      ServiceWorkerClientInfo(CreateDedicatedWorkerToken()),
+      ServiceWorkerClientInfo(DedicatedWorkerId()),
       GURL("https://www.example.com/dedicated_worker.js"));
 }
 
@@ -1104,7 +1099,7 @@
   ASSERT_TRUE(
       base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
   TestClientPhaseTransition(
-      ServiceWorkerClientInfo(CreateDedicatedWorkerToken()),
+      ServiceWorkerClientInfo(DedicatedWorkerId()),
       GURL("https://www.example.com/dedicated_worker.js"));
 }
 
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index b18fb74..76a2658 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -25,6 +25,7 @@
 #include "content/browser/service_worker/service_worker_registry.h"
 #include "content/browser/service_worker/service_worker_storage.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/shared_worker_id.h"
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 646f0e40..f3dcbc4 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -1462,12 +1462,6 @@
   scoped_refptr<ServiceWorkerRegistration> new_registration =
       RunRegisterJob(script_url, options);
 
-  // Update check succeeds but no update is found.
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                     blink::ServiceWorkerStatusCode::kOk, 1);
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                     false, 1);
-
   // Ensure that the registration object is not copied.
   EXPECT_EQ(old_registration, new_registration);
   EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kNone,
@@ -1502,12 +1496,6 @@
   first_version->StartUpdate();
   base::RunLoop().RunUntilIdle();
 
-  // Update check succeeds but no update is found.
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                     blink::ServiceWorkerStatusCode::kOk, 1);
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                     false, 1);
-
   // Verify results.
   ASSERT_TRUE(registration->active_version());
   EXPECT_EQ(first_version.get(), registration->active_version());
@@ -1543,12 +1531,6 @@
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(kToday, registration->last_update_check());
     EXPECT_FALSE(update_helper_->update_found_);
-
-    // Update check succeeds but no update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       false, 1);
   }
 
   // Run an update where the script did not change and the network was
@@ -1568,11 +1550,6 @@
     registration->RemoveListener(update_helper_);
     registration = update_helper_->SetupInitialRegistration(kNewVersionOrigin);
     ASSERT_TRUE(registration.get());
-    // Update check succeeds but no update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       false, 1);
   }
 
   registration->AddListener(update_helper_);
@@ -1588,11 +1565,6 @@
     registration->active_version()->StartUpdate();
     base::RunLoop().RunUntilIdle();
     EXPECT_LT(kYesterday, registration->last_update_check());
-    // Update check succeeds and update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       true, 1);
   }
 
   // Run an update to a worker that loads successfully but fails to start up
@@ -1614,12 +1586,6 @@
     registration->active_version()->StartUpdate();
     base::RunLoop().RunUntilIdle();
     EXPECT_LT(kYesterday, registration->last_update_check());
-    // Update check succeeds and update is found even when starting a worker
-    // fails.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       true, 1);
   }
 }
 
@@ -1645,11 +1611,6 @@
       registration->active_version();
   first_version->StartUpdate();
   base::RunLoop().RunUntilIdle();
-  // Update check succeeds and update is found.
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                     blink::ServiceWorkerStatusCode::kOk, 1);
-  histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                     true, 1);
 
   // The worker is updated after RequestTermination() is called from the
   // renderer. Until then, the active version stays active.
@@ -2084,12 +2045,6 @@
     base::RunLoop().RunUntilIdle();
     EXPECT_LT(kYesterday, registration->last_update_check());
     EXPECT_FALSE(update_helper_->update_found_);
-
-    // Update check succeeds but no update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       false, 1);
   }
 
   // Run an update where the COEP value and the script changed.
@@ -2103,11 +2058,6 @@
     base::RunLoop().RunUntilIdle();
     EXPECT_LT(kYesterday, registration->last_update_check());
     EXPECT_TRUE(update_helper_->update_found_);
-    // Update check succeeds and update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       true, 1);
     ASSERT_NE(nullptr, registration->waiting_version());
     EXPECT_EQ(CrossOriginEmbedderPolicyRequireCorp(),
               registration->waiting_version()->cross_origin_embedder_policy());
@@ -2125,11 +2075,6 @@
     base::RunLoop().RunUntilIdle();
     EXPECT_LT(kYesterday, registration->last_update_check());
     EXPECT_TRUE(update_helper_->update_found_);
-    // Update check succeeds and update is found.
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.Result",
-                                       blink::ServiceWorkerStatusCode::kOk, 1);
-    histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound",
-                                       true, 1);
     ASSERT_NE(nullptr, registration->waiting_version());
     EXPECT_EQ(CrossOriginEmbedderPolicyNone(),
               registration->waiting_version()->cross_origin_embedder_policy());
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
index 954b405..701b8f9 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
+++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
@@ -85,7 +85,7 @@
     bool are_ancestors_secure,
     int frame_tree_node_id,
     int process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost>
         host_receiver,
@@ -131,7 +131,7 @@
 
       ServiceWorkerClientInfo client_info =
           resource_type == blink::mojom::ResourceType::kWorker
-              ? ServiceWorkerClientInfo(dedicated_worker_token)
+              ? ServiceWorkerClientInfo(dedicated_worker_id)
               : ServiceWorkerClientInfo(shared_worker_id);
 
       container_host = context_core->CreateContainerHostForWorker(
@@ -213,7 +213,7 @@
                                  : blink::mojom::ResourceType::kSubFrame,
       request_info.begin_params->skip_service_worker,
       request_info.are_ancestors_secure, request_info.frame_tree_node_id,
-      ChildProcessHost::kInvalidUniqueID, blink::mojom::DedicatedWorkerToken(),
+      ChildProcessHost::kInvalidUniqueID, DedicatedWorkerId(),
       SharedWorkerId()));
 }
 
@@ -221,7 +221,7 @@
 ServiceWorkerMainResourceLoaderInterceptor::CreateForWorker(
     const network::ResourceRequest& resource_request,
     int process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -240,8 +240,8 @@
   return base::WrapUnique(new ServiceWorkerMainResourceLoaderInterceptor(
       std::move(navigation_handle), resource_type,
       resource_request.skip_service_worker, /*are_ancestors_secure=*/false,
-      FrameTreeNode::kFrameTreeNodeInvalidId, process_id,
-      dedicated_worker_token, shared_worker_id));
+      FrameTreeNode::kFrameTreeNodeInvalidId, process_id, dedicated_worker_id,
+      shared_worker_id));
 }
 
 ServiceWorkerMainResourceLoaderInterceptor::
@@ -296,7 +296,7 @@
       base::BindOnce(&MaybeCreateLoaderOnCoreThread, GetWeakPtr(),
                      handle_->core(), resource_type_, skip_service_worker_,
                      are_ancestors_secure_, frame_tree_node_id_, process_id_,
-                     dedicated_worker_token_, shared_worker_id_,
+                     dedicated_worker_id_, shared_worker_id_,
                      std::move(host_receiver), std::move(client_remote),
                      tentative_resource_request, browser_context,
                      std::move(loader_callback), std::move(fallback_callback),
@@ -366,7 +366,7 @@
         bool are_ancestors_secure,
         int frame_tree_node_id,
         int process_id,
-        const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+        DedicatedWorkerId dedicated_worker_id,
         SharedWorkerId shared_worker_id)
     : handle_(std::move(handle)),
       resource_type_(resource_type),
@@ -374,7 +374,7 @@
       are_ancestors_secure_(are_ancestors_secure),
       frame_tree_node_id_(frame_tree_node_id),
       process_id_(process_id),
-      dedicated_worker_token_(dedicated_worker_token),
+      dedicated_worker_id_(dedicated_worker_id),
       shared_worker_id_(shared_worker_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(handle_);
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
index 869e2a7a..692ce5a5 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
+++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
@@ -14,13 +14,13 @@
 #include "content/browser/navigation_subresource_loader_params.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "content/public/common/child_process_host.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace content {
 
@@ -49,7 +49,7 @@
   static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorker(
       const network::ResourceRequest& resource_request,
       int process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id,
       base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle);
 
@@ -90,7 +90,7 @@
       bool are_ancestors_secure,
       int frame_tree_node_id,
       int process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id);
 
   // Returns true if a ServiceWorkerMainResourceLoaderInterceptor should be
@@ -126,7 +126,7 @@
 
   // For web workers:
   const int process_id_;
-  const blink::mojom::DedicatedWorkerToken dedicated_worker_token_;
+  const DedicatedWorkerId dedicated_worker_id_;
   const SharedWorkerId shared_worker_id_;
 
   base::Optional<SubresourceLoaderParams> subresource_loader_params_;
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc
index 511fa76..93c515d 100644
--- a/content/browser/service_worker/service_worker_metrics.cc
+++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -578,17 +578,6 @@
   }
 }
 
-void ServiceWorkerMetrics::RecordByteForByteUpdateCheckStatus(
-    blink::ServiceWorkerStatusCode status,
-    bool has_found_update) {
-  DCHECK(blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled());
-  UMA_HISTOGRAM_ENUMERATION("ServiceWorker.UpdateCheck.Result", status);
-  if (status == blink::ServiceWorkerStatusCode::kOk) {
-    UMA_HISTOGRAM_BOOLEAN("ServiceWorker.UpdateCheck.UpdateFound",
-                          has_found_update);
-  }
-}
-
 void ServiceWorkerMetrics::RecordGetAllOriginsInfoTime(base::TimeDelta time) {
   base::UmaHistogramMediumTimes("ServiceWorker.GetAllOriginsInfoTime", time);
 }
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h
index 22eb3f2..7fef822c 100644
--- a/content/browser/service_worker/service_worker_metrics.h
+++ b/content/browser/service_worker/service_worker_metrics.h
@@ -257,14 +257,6 @@
       blink::ServiceWorkerStatusCode status,
       base::TimeDelta duration);
 
-  // Records the result of byte-for-byte update checking.
-  // |has_found_update| should be true when the update checking finds update of
-  // the script. It's recorded only when |status| is kOk.
-  // This is used only when ServiceWorkerImportedScriptUpdateCheck is enabled.
-  static void RecordByteForByteUpdateCheckStatus(
-      blink::ServiceWorkerStatusCode status,
-      bool has_found_update);
-
   static void RecordGetAllOriginsInfoTime(base::TimeDelta time);
 
  private:
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index c7586d5..3c03fb5 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -377,8 +377,6 @@
   // Update check failed.
   if (result == ServiceWorkerSingleScriptUpdateChecker::Result::kFailed) {
     DCHECK(failure_info);
-    ServiceWorkerMetrics::RecordByteForByteUpdateCheckStatus(
-        failure_info->status, /*has_found_update=*/false);
     ResolvePromise(failure_info->status, failure_info->error_message, nullptr);
     // This terminates the current job (|this|).
     Complete(failure_info->status, failure_info->error_message);
@@ -390,8 +388,6 @@
 
   // Update check succeeded.
   if (result == ServiceWorkerSingleScriptUpdateChecker::Result::kIdentical) {
-    ServiceWorkerMetrics::RecordByteForByteUpdateCheckStatus(
-        blink::ServiceWorkerStatusCode::kOk, /*has_found_update=*/false);
     ResolvePromise(blink::ServiceWorkerStatusCode::kOk, std::string(),
                    registration());
     // This terminates the current job (|this|).
@@ -400,8 +396,6 @@
     return;
   }
 
-  ServiceWorkerMetrics::RecordByteForByteUpdateCheckStatus(
-      blink::ServiceWorkerStatusCode::kOk, /*has_found_update=*/true);
   CreateNewVersionForUpdate();
 }
 
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index b332c568..cc6dabc4 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -16,9 +16,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
 #include "components/viz/common/features.h"
@@ -1061,7 +1061,7 @@
   int result_op = 0;
   {
     gfx::NativeView content_native_view = GetContentNativeView();
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedNestableTaskAllower allow;
     result_op = aura::client::GetDragDropClient(root_window)
                     ->StartDragAndDrop(
                         std::move(data), root_window, content_native_view,
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index 88aa049..aceb5e2 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -10,8 +10,8 @@
 
 #import "base/mac/mac_util.h"
 #import "base/mac/scoped_sending_event.h"
-#include "base/message_loop/message_loop_current.h"
 #import "base/message_loop/message_pump_mac.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "components/remote_cocoa/browser/ns_view_ids.h"
@@ -152,7 +152,7 @@
 
   // The drag invokes a nested event loop, arrange to continue
   // processing events.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  base::CurrentThread::ScopedNestableTaskAllower allow;
   NSDragOperation mask = static_cast<NSDragOperation>(allowed_operations) &
                          ~NSDragOperationGeneric;
   [drag_dest_ setDragStartTrackersForProcess:source_rwh->GetProcess()->GetID()];
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
index 4b2bbb3..796ef06f 100644
--- a/content/browser/webui/url_data_manager_backend.cc
+++ b/content/browser/webui/url_data_manager_backend.cc
@@ -164,6 +164,7 @@
     const network::mojom::CSPDirectiveName kAllDirectives[] = {
         network::mojom::CSPDirectiveName::ChildSrc,
         network::mojom::CSPDirectiveName::DefaultSrc,
+        network::mojom::CSPDirectiveName::FrameSrc,
         network::mojom::CSPDirectiveName::ImgSrc,
         network::mojom::CSPDirectiveName::MediaSrc,
         network::mojom::CSPDirectiveName::ObjectSrc,
diff --git a/content/browser/webui/web_ui_data_source_unittest.cc b/content/browser/webui/web_ui_data_source_unittest.cc
index 7ec7409..e20ea8ba 100644
--- a/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/content/browser/webui/web_ui_data_source_unittest.cc
@@ -280,6 +280,8 @@
   EXPECT_EQ("", url_data_source->GetContentSecurityPolicy(
                     network::mojom::CSPDirectiveName::DefaultSrc));
   EXPECT_EQ("", url_data_source->GetContentSecurityPolicy(
+                    network::mojom::CSPDirectiveName::FrameSrc));
+  EXPECT_EQ("", url_data_source->GetContentSecurityPolicy(
                     network::mojom::CSPDirectiveName::ImgSrc));
   EXPECT_EQ("", url_data_source->GetContentSecurityPolicy(
                     network::mojom::CSPDirectiveName::MediaSrc));
@@ -308,6 +310,12 @@
                 network::mojom::CSPDirectiveName::DefaultSrc));
 
   source()->OverrideContentSecurityPolicy(
+      network::mojom::CSPDirectiveName::FrameSrc, "frame-src 'self';");
+  EXPECT_EQ("frame-src 'self';",
+            url_data_source->GetContentSecurityPolicy(
+                network::mojom::CSPDirectiveName::FrameSrc));
+
+  source()->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ImgSrc, "img-src 'self' blob:;");
   EXPECT_EQ("img-src 'self' blob:;",
             url_data_source->GetContentSecurityPolicy(
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index d7c9d44..c3e7a72e 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -37,7 +37,7 @@
 
 DedicatedWorkerHost::DedicatedWorkerHost(
     DedicatedWorkerServiceImpl* service,
-    const blink::mojom::DedicatedWorkerToken& token,
+    DedicatedWorkerId id,
     RenderProcessHost* worker_process_host,
     base::Optional<GlobalFrameRoutingId> creator_render_frame_host_id,
     GlobalFrameRoutingId ancestor_render_frame_host_id,
@@ -46,7 +46,7 @@
     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
         coep_reporter)
     : service_(service),
-      token_(token),
+      id_(id),
       worker_process_host_(worker_process_host),
       scoped_process_host_observer_(this),
       creator_render_frame_host_id_(creator_render_frame_host_id),
@@ -58,19 +58,18 @@
       cross_origin_embedder_policy_(cross_origin_embedder_policy),
       coep_reporter_(std::move(coep_reporter)) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!token_.value.is_empty());
   DCHECK(worker_process_host_);
   DCHECK(worker_process_host_->IsInitializedAndNotDead());
   DCHECK(coep_reporter_);
 
   scoped_process_host_observer_.Add(worker_process_host_);
 
-  service_->NotifyWorkerCreated(token_, worker_process_host_->GetID(),
+  service_->NotifyWorkerCreated(id_, worker_process_host_->GetID(),
                                 ancestor_render_frame_host_id_);
 }
 
 DedicatedWorkerHost::~DedicatedWorkerHost() {
-  service_->NotifyBeforeWorkerDestroyed(token_, ancestor_render_frame_host_id_);
+  service_->NotifyBeforeWorkerDestroyed(id_, ancestor_render_frame_host_id_);
 }
 
 void DedicatedWorkerHost::BindBrowserInterfaceBrokerReceiver(
@@ -190,7 +189,7 @@
       storage_partition_impl->GetServiceWorkerContext(), base::DoNothing());
 
   WorkerScriptFetchInitiator::Start(
-      worker_process_host_->GetID(), token_, SharedWorkerId(), script_url,
+      worker_process_host_->GetID(), id_, SharedWorkerId(), script_url,
       creator_render_frame_host,
       nearest_ancestor_render_frame_host->ComputeSiteForCookies(),
       creator_origin_,
@@ -229,7 +228,7 @@
 
   // TODO(https://crbug.com/986188): Check if the main script's final response
   // URL is committable.
-  service_->NotifyWorkerFinalResponseURLDetermined(token_, final_response_url);
+  service_->NotifyWorkerFinalResponseURLDetermined(id_, final_response_url);
 
   // TODO(cammie): Change this approach when we support shared workers
   // creating dedicated workers, as there might be no ancestor frame.
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h
index e55dfa4..a093a91 100644
--- a/content/browser/worker_host/dedicated_worker_host.h
+++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -11,6 +11,7 @@
 #include "base/scoped_observer.h"
 #include "build/build_config.h"
 #include "content/browser/browser_interface_broker_impl.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
@@ -22,7 +23,6 @@
 #include "third_party/blink/public/mojom/idle/idle_manager.mojom-forward.h"
 #include "third_party/blink/public/mojom/loader/content_security_notifier.mojom.h"
 #include "third_party/blink/public/mojom/sms/sms_receiver.mojom-forward.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 #include "third_party/blink/public/mojom/usb/web_usb_service.mojom-forward.h"
 #include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-forward.h"
 #include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-forward.h"
@@ -50,7 +50,7 @@
  public:
   DedicatedWorkerHost(
       DedicatedWorkerServiceImpl* service,
-      const blink::mojom::DedicatedWorkerToken& token,
+      DedicatedWorkerId id,
       RenderProcessHost* worker_process_host,
       base::Optional<GlobalFrameRoutingId> creator_render_frame_host_id,
       GlobalFrameRoutingId ancestor_render_frame_host_id,
@@ -63,9 +63,8 @@
   void BindBrowserInterfaceBrokerReceiver(
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver);
 
-  const blink::mojom::DedicatedWorkerToken& GetToken() const { return token_; }
-  RenderProcessHost* GetProcessHost() const { return worker_process_host_; }
-  const url::Origin& GetWorkerOrigin() const { return worker_origin_; }
+  RenderProcessHost* GetProcessHost() { return worker_process_host_; }
+  const url::Origin& GetWorkerOrigin() { return worker_origin_; }
 
   void CreateContentSecurityNotifier(
       mojo::PendingReceiver<blink::mojom::ContentSecurityNotifier> receiver);
@@ -157,8 +156,8 @@
 
   DedicatedWorkerServiceImpl* const service_;
 
-  // The renderer generated ID of this worker, unique across all processes.
-  const blink::mojom::DedicatedWorkerToken token_;
+  // An internal ID that is unique within a storage partition.
+  const DedicatedWorkerId id_;
 
   // The RenderProcessHost that hosts this worker.
   RenderProcessHost* const worker_process_host_;
diff --git a/content/browser/worker_host/dedicated_worker_host_factory_impl.cc b/content/browser/worker_host/dedicated_worker_host_factory_impl.cc
index 48d5f4a..4094b51 100644
--- a/content/browser/worker_host/dedicated_worker_host_factory_impl.cc
+++ b/content/browser/worker_host/dedicated_worker_host_factory_impl.cc
@@ -17,24 +17,6 @@
 
 namespace content {
 
-namespace {
-
-// Gets the DedicatedWorkerServiceImpl, returning nullptr if not possible.
-DedicatedWorkerServiceImpl* GetDedicatedWorkerServiceImplForRenderProcessHost(
-    RenderProcessHost* worker_process_host) {
-  if (!worker_process_host || !worker_process_host->IsInitializedAndNotDead()) {
-    // Abort if the worker's process host is gone. This means that the calling
-    // frame or worker is also either destroyed or in the process of being
-    // destroyed.
-    return nullptr;
-  }
-  auto* storage_partition = static_cast<StoragePartitionImpl*>(
-      worker_process_host->GetStoragePartition());
-  return storage_partition->GetDedicatedWorkerService();
-}
-
-}  // namespace
-
 DedicatedWorkerHostFactoryImpl::DedicatedWorkerHostFactoryImpl(
     int worker_process_id,
     base::Optional<GlobalFrameRoutingId> creator_render_frame_host_id,
@@ -55,7 +37,6 @@
 DedicatedWorkerHostFactoryImpl::~DedicatedWorkerHostFactoryImpl() = default;
 
 void DedicatedWorkerHostFactoryImpl::CreateWorkerHost(
-    blink::mojom::DedicatedWorkerTokenPtr token,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> broker_receiver,
     base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)>
         callback) {
@@ -65,34 +46,36 @@
     return;
   }
 
-  // Get the dedicated worker service.
-  auto* worker_process_host = RenderProcessHost::FromID(worker_process_id_);
-  auto* service =
-      GetDedicatedWorkerServiceImplForRenderProcessHost(worker_process_host);
-  if (!service)
-    return;
+  std::move(callback).Run(cross_origin_embedder_policy_);
 
-  if (service->HasToken(*token)) {
-    mojo::ReportBadMessage("DWH_INVALID_WORKER_TOKEN");
+  auto* worker_process_host = RenderProcessHost::FromID(worker_process_id_);
+  if (!worker_process_host || !worker_process_host->IsInitializedAndNotDead()) {
+    // Abort if the worker's process host is gone. This means that the calling
+    // frame or worker is also either destroyed or in the process of being
+    // destroyed.
     return;
   }
 
-  std::move(callback).Run(cross_origin_embedder_policy_);
+  auto* storage_partition = static_cast<StoragePartitionImpl*>(
+      worker_process_host->GetStoragePartition());
+
+  // Get the dedicated worker service.
+  DedicatedWorkerServiceImpl* service =
+      storage_partition->GetDedicatedWorkerService();
 
   mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
       coep_reporter;
   coep_reporter_->Clone(coep_reporter.InitWithNewPipeAndPassReceiver());
 
   auto* host = new DedicatedWorkerHost(
-      service, *token, worker_process_host, creator_render_frame_host_id_,
-      ancestor_render_frame_host_id_, creator_origin_,
-      cross_origin_embedder_policy_, std::move(coep_reporter));
+      service, service->GenerateNextDedicatedWorkerId(), worker_process_host,
+      creator_render_frame_host_id_, ancestor_render_frame_host_id_,
+      creator_origin_, cross_origin_embedder_policy_, std::move(coep_reporter));
   host->BindBrowserInterfaceBrokerReceiver(std::move(broker_receiver));
 }
 
 // PlzDedicatedWorker:
 void DedicatedWorkerHostFactoryImpl::CreateWorkerHostAndStartScriptLoad(
-    blink::mojom::DedicatedWorkerTokenPtr token,
     const GURL& script_url,
     network::mojom::CredentialsMode credentials_mode,
     blink::mojom::FetchClientSettingsObjectPtr
@@ -106,29 +89,32 @@
     return;
   }
 
-  // Get the dedicated worker service.
-  auto* worker_process_host = RenderProcessHost::FromID(worker_process_id_);
-  auto* service =
-      GetDedicatedWorkerServiceImplForRenderProcessHost(worker_process_host);
-  if (!service)
-    return;
+  // TODO(https://crbug.com/1058759): Compare |creator_origin_| to
+  // |script_url|, and report as bad message if that fails.
 
-  if (service->HasToken(*token)) {
-    mojo::ReportBadMessage("DWH_INVALID_WORKER_TOKEN");
+  auto* worker_process_host = RenderProcessHost::FromID(worker_process_id_);
+  if (!worker_process_host || !worker_process_host->IsInitializedAndNotDead()) {
+    // Abort if the worker's process host is gone. This means that the calling
+    // frame or worker is also either destroyed or in the process of being
+    // destroyed.
     return;
   }
 
-  // TODO(https://crbug.com/1058759): Compare |creator_origin_| to
-  // |script_url|, and report as bad message if that fails.
+  auto* storage_partition = static_cast<StoragePartitionImpl*>(
+      worker_process_host->GetStoragePartition());
+
+  // Get the dedicated worker service.
+  DedicatedWorkerServiceImpl* service =
+      storage_partition->GetDedicatedWorkerService();
 
   mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
       coep_reporter;
   coep_reporter_->Clone(coep_reporter.InitWithNewPipeAndPassReceiver());
 
   auto* host = new DedicatedWorkerHost(
-      service, *token, worker_process_host, creator_render_frame_host_id_,
-      ancestor_render_frame_host_id_, creator_origin_,
-      cross_origin_embedder_policy_, std::move(coep_reporter));
+      service, service->GenerateNextDedicatedWorkerId(), worker_process_host,
+      creator_render_frame_host_id_, ancestor_render_frame_host_id_,
+      creator_origin_, cross_origin_embedder_policy_, std::move(coep_reporter));
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker;
   host->BindBrowserInterfaceBrokerReceiver(
       broker.InitWithNewPipeAndPassReceiver());
diff --git a/content/browser/worker_host/dedicated_worker_host_factory_impl.h b/content/browser/worker_host/dedicated_worker_host_factory_impl.h
index 4d0f285d..f1583c18 100644
--- a/content/browser/worker_host/dedicated_worker_host_factory_impl.h
+++ b/content/browser/worker_host/dedicated_worker_host_factory_impl.h
@@ -34,7 +34,6 @@
 
   // blink::mojom::DedicatedWorkerHostFactory:
   void CreateWorkerHost(
-      blink::mojom::DedicatedWorkerTokenPtr token,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           broker_receiver,
       base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)>
@@ -42,7 +41,6 @@
 
   // PlzDedicatedWorker:
   void CreateWorkerHostAndStartScriptLoad(
-      blink::mojom::DedicatedWorkerTokenPtr token,
       const GURL& script_url,
       network::mojom::CredentialsMode credentials_mode,
       blink::mojom::FetchClientSettingsObjectPtr
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.cc b/content/browser/worker_host/dedicated_worker_service_impl.cc
index 65bc1ca7..b2d4c48 100644
--- a/content/browser/worker_host/dedicated_worker_service_impl.cc
+++ b/content/browser/worker_host/dedicated_worker_service_impl.cc
@@ -37,63 +37,63 @@
 
 void DedicatedWorkerServiceImpl::EnumerateDedicatedWorkers(Observer* observer) {
   for (const auto& kv : dedicated_worker_infos_) {
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token = kv.first;
+    DedicatedWorkerId dedicated_worker_id = kv.first;
     const DedicatedWorkerInfo& dedicated_worker_info = kv.second;
 
     observer->OnWorkerCreated(
-        dedicated_worker_token, dedicated_worker_info.worker_process_id,
+        dedicated_worker_id, dedicated_worker_info.worker_process_id,
         dedicated_worker_info.ancestor_render_frame_host_id);
     if (dedicated_worker_info.final_response_url) {
       observer->OnFinalResponseURLDetermined(
-          dedicated_worker_token, *dedicated_worker_info.final_response_url);
+          dedicated_worker_id, *dedicated_worker_info.final_response_url);
     }
   }
 }
 
+DedicatedWorkerId DedicatedWorkerServiceImpl::GenerateNextDedicatedWorkerId() {
+  return dedicated_worker_id_generator_.GenerateNextId();
+}
+
 void DedicatedWorkerServiceImpl::NotifyWorkerCreated(
-    const blink::mojom::DedicatedWorkerToken& worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     int worker_process_id,
     GlobalFrameRoutingId ancestor_render_frame_host_id) {
-  bool inserted = dedicated_worker_infos_
-                      .emplace(worker_token, DedicatedWorkerInfo(
-                                                 worker_process_id,
-                                                 ancestor_render_frame_host_id))
-                      .second;
+  bool inserted =
+      dedicated_worker_infos_
+          .emplace(dedicated_worker_id,
+                   DedicatedWorkerInfo(worker_process_id,
+                                       ancestor_render_frame_host_id))
+          .second;
   DCHECK(inserted);
 
   for (Observer& observer : observers_) {
-    observer.OnWorkerCreated(worker_token, worker_process_id,
+    observer.OnWorkerCreated(dedicated_worker_id, worker_process_id,
                              ancestor_render_frame_host_id);
   }
 }
 
 void DedicatedWorkerServiceImpl::NotifyBeforeWorkerDestroyed(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     GlobalFrameRoutingId ancestor_render_frame_host_id) {
-  size_t removed = dedicated_worker_infos_.erase(dedicated_worker_token);
-  DCHECK_EQ(1u, removed);
+  size_t removed = dedicated_worker_infos_.erase(dedicated_worker_id);
+  DCHECK_EQ(removed, 1u);
 
   for (Observer& observer : observers_) {
-    observer.OnBeforeWorkerDestroyed(dedicated_worker_token,
+    observer.OnBeforeWorkerDestroyed(dedicated_worker_id,
                                      ancestor_render_frame_host_id);
   }
 }
 
 void DedicatedWorkerServiceImpl::NotifyWorkerFinalResponseURLDetermined(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     const GURL& url) {
-  auto it = dedicated_worker_infos_.find(dedicated_worker_token);
+  auto it = dedicated_worker_infos_.find(dedicated_worker_id);
   DCHECK(it != dedicated_worker_infos_.end());
 
   it->second.final_response_url = url;
 
   for (Observer& observer : observers_)
-    observer.OnFinalResponseURLDetermined(dedicated_worker_token, url);
-}
-
-bool DedicatedWorkerServiceImpl::HasToken(
-    const blink::mojom::DedicatedWorkerToken& worker_token) const {
-  return dedicated_worker_infos_.count(worker_token);
+    observer.OnFinalResponseURLDetermined(dedicated_worker_id, url);
 }
 
 }  // namespace content
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.h b/content/browser/worker_host/dedicated_worker_service_impl.h
index f13db8ce..095c369 100644
--- a/content/browser/worker_host/dedicated_worker_service_impl.h
+++ b/content/browser/worker_host/dedicated_worker_service_impl.h
@@ -24,28 +24,27 @@
   void RemoveObserver(Observer* observer) override;
   void EnumerateDedicatedWorkers(Observer* observer) override;
 
+  DedicatedWorkerId GenerateNextDedicatedWorkerId();
+
   // Notifies all observers about a new worker.
-  void NotifyWorkerCreated(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
-      int worker_process_id,
-      GlobalFrameRoutingId ancestor_render_frame_host_id);
+  void NotifyWorkerCreated(DedicatedWorkerId dedicated_worker_id,
+                           int worker_process_id,
+                           GlobalFrameRoutingId ancestor_render_frame_host_id);
 
   // Notifies all observers about a worker being destroyed.
   void NotifyBeforeWorkerDestroyed(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       GlobalFrameRoutingId ancestor_render_frame_host_id);
 
   // Notifies all observers that a worker's final response URL was determined.
   void NotifyWorkerFinalResponseURLDetermined(
-      const blink::mojom::DedicatedWorkerToken& worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       const GURL& url);
 
-  // Returns true if a worker with the given token has already been registered
-  // with the service. This allows for malformed messages with duplicated
-  // tokens to be detected, and the offending renderer to be shutdown.
-  bool HasToken(const blink::mojom::DedicatedWorkerToken& worker_token) const;
-
  private:
+  // Generates IDs for new dedicated workers.
+  DedicatedWorkerId::Generator dedicated_worker_id_generator_;
+
   base::ObserverList<Observer> observers_;
 
   struct DedicatedWorkerInfo {
@@ -60,7 +59,7 @@
     GlobalFrameRoutingId ancestor_render_frame_host_id;
     base::Optional<GURL> final_response_url;
   };
-  base::flat_map<blink::mojom::DedicatedWorkerToken, DedicatedWorkerInfo>
+  base::flat_map<DedicatedWorkerId, DedicatedWorkerInfo>
       dedicated_worker_infos_;
 };
 
diff --git a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
index 63d8742a..d9e4832 100644
--- a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
+++ b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
@@ -20,17 +20,11 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h"
 #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
 
 namespace content {
 
-blink::mojom::DedicatedWorkerTokenPtr CreateDedicatedWorkerTokenPtr() {
-  return blink::mojom::DedicatedWorkerToken::New(
-      base::UnguessableToken::Create());
-}
-
 // Mocks a dedicated worker living in a renderer process.
 class MockDedicatedWorker
     : public blink::mojom::DedicatedWorkerHostFactoryClient {
@@ -52,14 +46,12 @@
 
     if (base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)) {
       factory_->CreateWorkerHostAndStartScriptLoad(
-          CreateDedicatedWorkerTokenPtr(),
           /*script_url=*/GURL(), network::mojom::CredentialsMode::kSameOrigin,
           blink::mojom::FetchClientSettingsObject::New(),
           mojo::PendingRemote<blink::mojom::BlobURLToken>(),
           receiver_.BindNewPipeAndPassRemote());
     } else {
       factory_->CreateWorkerHost(
-          CreateDedicatedWorkerTokenPtr(),
           browser_interface_broker_.BindNewPipeAndPassReceiver(),
           base::BindOnce([](const network::CrossOriginEmbedderPolicy&) {}));
     }
@@ -167,13 +159,14 @@
 
   // DedicatedWorkerService::Observer:
   void OnWorkerCreated(
-      const blink::mojom::DedicatedWorkerToken& token,
+      DedicatedWorkerId dedicated_worker_id,
       int worker_process_id,
       GlobalFrameRoutingId ancestor_render_frame_host_id) override {
     bool inserted =
         dedicated_worker_infos_
-            .emplace(token, DedicatedWorkerInfo{worker_process_id,
-                                                ancestor_render_frame_host_id})
+            .emplace(dedicated_worker_id,
+                     DedicatedWorkerInfo{worker_process_id,
+                                         ancestor_render_frame_host_id})
             .second;
     DCHECK(inserted);
 
@@ -181,17 +174,16 @@
       std::move(on_worker_event_callback_).Run();
   }
   void OnBeforeWorkerDestroyed(
-      const blink::mojom::DedicatedWorkerToken& token,
+      DedicatedWorkerId dedicated_worker_id,
       GlobalFrameRoutingId ancestor_render_frame_host_id) override {
-    size_t removed = dedicated_worker_infos_.erase(token);
+    size_t removed = dedicated_worker_infos_.erase(dedicated_worker_id);
     DCHECK_EQ(removed, 1u);
 
     if (on_worker_event_callback_)
       std::move(on_worker_event_callback_).Run();
   }
-  void OnFinalResponseURLDetermined(
-      const blink::mojom::DedicatedWorkerToken& token,
-      const GURL& url) override {}
+  void OnFinalResponseURLDetermined(DedicatedWorkerId dedicated_worker_id,
+                                    const GURL& url) override {}
 
   void RunUntilWorkerEvent() {
     base::RunLoop run_loop;
@@ -199,7 +191,7 @@
     run_loop.Run();
   }
 
-  const base::flat_map<blink::mojom::DedicatedWorkerToken, DedicatedWorkerInfo>&
+  const base::flat_map<DedicatedWorkerId, DedicatedWorkerInfo>&
   dedicated_worker_infos() const {
     return dedicated_worker_infos_;
   }
@@ -209,7 +201,7 @@
   // is called.
   base::OnceClosure on_worker_event_callback_;
 
-  base::flat_map<blink::mojom::DedicatedWorkerToken, DedicatedWorkerInfo>
+  base::flat_map<DedicatedWorkerId, DedicatedWorkerInfo>
       dedicated_worker_infos_;
 };
 
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 3d13e30d..fca0343ce0 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -327,8 +327,8 @@
   // data across NetworkIsolationKeys and allow same-site cookies to be sent in
   // cross-site contexts. Fix this.
   WorkerScriptFetchInitiator::Start(
-      worker_process_host->GetID(), blink::mojom::DedicatedWorkerToken(),
-      host->id(), host->instance().url(), creator_render_frame_host,
+      worker_process_host->GetID(), DedicatedWorkerId(), host->id(),
+      host->instance().url(), creator_render_frame_host,
       net::SiteForCookies::FromOrigin(worker_origin),
       host->instance().constructor_origin(),
       net::IsolationInfo::Create(
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index 5a11eb1f..06fb42d 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -64,7 +64,7 @@
 // static
 void WorkerScriptFetchInitiator::Start(
     int worker_process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     const GURL& initial_request_url,
     RenderFrameHost* creator_render_frame_host,
@@ -177,7 +177,7 @@
   AddAdditionalRequestHeaders(resource_request.get(), browser_context);
 
   CreateScriptLoader(
-      worker_process_id, dedicated_worker_token, shared_worker_id,
+      worker_process_id, dedicated_worker_id, shared_worker_id,
       initial_request_url, creator_render_frame_host, trusted_isolation_info,
       std::move(resource_request), std::move(factory_bundle_for_browser),
       std::move(subresource_loader_factories),
@@ -281,7 +281,7 @@
 
 void WorkerScriptFetchInitiator::CreateScriptLoader(
     int worker_process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     const GURL& initial_request_url,
     RenderFrameHost* creator_render_frame_host,
@@ -375,7 +375,7 @@
 
   WorkerScriptFetcher::CreateAndStart(
       std::make_unique<WorkerScriptLoaderFactory>(
-          worker_process_id, dedicated_worker_token, shared_worker_id,
+          worker_process_id, dedicated_worker_id, shared_worker_id,
           service_worker_handle, std::move(appcache_host),
           browser_context_getter, std::move(url_loader_factory)),
       std::move(throttles), std::move(resource_request),
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h
index cc5b552..6765a0e2 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.h
+++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -23,7 +24,6 @@
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
 
 namespace blink {
@@ -68,7 +68,7 @@
   // thread. |callback| will be called with the result on the UI thread.
   static void Start(
       int worker_process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id,
       const GURL& initial_request_url,
       RenderFrameHost* creator_render_frame_host,
@@ -113,7 +113,7 @@
 
   static void CreateScriptLoader(
       int worker_process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id,
       const GURL& initial_request_url,
       RenderFrameHost* creator_render_frame_host,
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index fd99abf..ff57e77 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -21,7 +21,7 @@
 
 WorkerScriptLoader::WorkerScriptLoader(
     int process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     int32_t routing_id,
     int32_t request_id,
@@ -51,8 +51,8 @@
   }
   auto service_worker_interceptor =
       ServiceWorkerMainResourceLoaderInterceptor::CreateForWorker(
-          resource_request_, process_id, dedicated_worker_token,
-          shared_worker_id, service_worker_handle_);
+          resource_request_, process_id, dedicated_worker_id, shared_worker_id,
+          service_worker_handle_);
 
   if (service_worker_interceptor)
     interceptors_.push_back(std::move(service_worker_interceptor));
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h
index 676cfc1..53849de 100644
--- a/content/browser/worker_host/worker_script_loader.h
+++ b/content/browser/worker_host/worker_script_loader.h
@@ -14,6 +14,7 @@
 #include "base/optional.h"
 #include "content/browser/loader/single_request_url_loader_factory.h"
 #include "content/browser/navigation_subresource_loader_params.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -23,7 +24,6 @@
 #include "net/url_request/url_request.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace blink {
 class ThrottlingURLLoader;
@@ -70,7 +70,7 @@
   // chrome-extension:// URL.
   WorkerScriptLoader(
       int process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id,
       int32_t routing_id,
       int32_t request_id,
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc
index bddc19f..386d6772 100644
--- a/content/browser/worker_host/worker_script_loader_factory.cc
+++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -22,14 +22,14 @@
 
 WorkerScriptLoaderFactory::WorkerScriptLoaderFactory(
     int process_id,
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+    DedicatedWorkerId dedicated_worker_id,
     SharedWorkerId shared_worker_id,
     ServiceWorkerMainResourceHandle* service_worker_handle,
     base::WeakPtr<AppCacheHost> appcache_host,
     const BrowserContextGetter& browser_context_getter,
     scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
     : process_id_(process_id),
-      dedicated_worker_token_(dedicated_worker_token),
+      dedicated_worker_id_(dedicated_worker_id),
       shared_worker_id_(shared_worker_id),
       appcache_host_(std::move(appcache_host)),
       browser_context_getter_(browser_context_getter),
@@ -63,7 +63,7 @@
 
   // Create a WorkerScriptLoader to load the script.
   auto script_loader = std::make_unique<WorkerScriptLoader>(
-      process_id_, dedicated_worker_token_, shared_worker_id_, routing_id,
+      process_id_, dedicated_worker_id_, shared_worker_id_, routing_id,
       request_id, options, resource_request, std::move(client),
       service_worker_handle_, appcache_host_, browser_context_getter_,
       loader_factory_, traffic_annotation);
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h
index d3a3702..274f5622 100644
--- a/content/browser/worker_host/worker_script_loader_factory.h
+++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -8,11 +8,11 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/navigation_subresource_loader_params.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace network {
 class SharedURLLoaderFactory;
@@ -50,7 +50,7 @@
   // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
   WorkerScriptLoaderFactory(
       int process_id,
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token,
+      DedicatedWorkerId dedicated_worker_id,
       SharedWorkerId shared_worker_id,
       ServiceWorkerMainResourceHandle* service_worker_handle,
       base::WeakPtr<AppCacheHost> appcache_host,
@@ -75,7 +75,7 @@
 
  private:
   const int process_id_;
-  const blink::mojom::DedicatedWorkerToken dedicated_worker_token_;
+  const DedicatedWorkerId dedicated_worker_id_;
   const SharedWorkerId shared_worker_id_;
   base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle_;
   base::WeakPtr<AppCacheHost> appcache_host_;
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index 19b31489..c3a3d34ad 100644
--- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -19,7 +19,6 @@
 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/test/test_url_loader_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace content {
 
@@ -27,10 +26,6 @@
 
 const int kProcessId = 1;
 
-blink::mojom::DedicatedWorkerToken CreateDedicatedWorkerToken() {
-  return blink::mojom::DedicatedWorkerToken(base::UnguessableToken());
-}
-
 }  // namespace
 
 class WorkerScriptLoaderFactoryTest : public testing::Test {
@@ -101,7 +96,7 @@
 TEST_F(WorkerScriptLoaderFactoryTest, ServiceWorkerContainerHost) {
   // Make the factory.
   auto factory = std::make_unique<WorkerScriptLoaderFactory>(
-      kProcessId, CreateDedicatedWorkerToken(), SharedWorkerId(),
+      kProcessId, DedicatedWorkerId(), SharedWorkerId(),
       service_worker_handle_.get(), /*appcache_host=*/nullptr,
       browser_context_getter_, network_loader_factory_);
 
@@ -126,7 +121,7 @@
 TEST_F(WorkerScriptLoaderFactoryTest, NullServiceWorkerHandle) {
   // Make the factory.
   auto factory = std::make_unique<WorkerScriptLoaderFactory>(
-      kProcessId, CreateDedicatedWorkerToken(), SharedWorkerId(),
+      kProcessId, DedicatedWorkerId(), SharedWorkerId(),
       service_worker_handle_.get(), nullptr /* appcache_host */,
       browser_context_getter_, network_loader_factory_);
 
@@ -150,7 +145,7 @@
 TEST_F(WorkerScriptLoaderFactoryTest, NullBrowserContext) {
   // Make the factory.
   auto factory = std::make_unique<WorkerScriptLoaderFactory>(
-      kProcessId, CreateDedicatedWorkerToken(), SharedWorkerId(),
+      kProcessId, DedicatedWorkerId(), SharedWorkerId(),
       service_worker_handle_.get(), nullptr /* appcache_host */,
       browser_context_getter_, network_loader_factory_);
 
diff --git a/content/common/android/cpu_time_metrics.cc b/content/common/android/cpu_time_metrics.cc
index 9601dce..ebd1b39b 100644
--- a/content/common/android/cpu_time_metrics.cc
+++ b/content/common/android/cpu_time_metrics.cc
@@ -15,13 +15,13 @@
 #include "base/containers/flat_map.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/process/process_metrics.h"
 #include "base/sequence_checker.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/task_observer.h"
 #include "base/threading/platform_thread.h"
@@ -517,7 +517,7 @@
   static bool did_setup = false;
   if (did_setup)
     return;
-  base::MessageLoopCurrent::Get()->AddTaskObserver(
+  base::CurrentThread::Get()->AddTaskObserver(
       ProcessCpuTimeTaskObserver::GetInstance());
   did_setup = true;
 }
diff --git a/content/common/service_manager/service_manager_connection_impl.cc b/content/common/service_manager/service_manager_connection_impl.cc
index 7c2140a..6b2ed58 100644
--- a/content/common/service_manager/service_manager_connection_impl.cc
+++ b/content/common/service_manager/service_manager_connection_impl.cc
@@ -14,7 +14,7 @@
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/thread_annotations.h"
 #include "base/threading/thread_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -115,16 +115,15 @@
  private:
   friend class base::RefCountedThreadSafe<IOThreadContext>;
 
-  class MessageLoopObserver
-      : public base::MessageLoopCurrent::DestructionObserver {
+  class MessageLoopObserver : public base::CurrentThread::DestructionObserver {
    public:
     explicit MessageLoopObserver(base::WeakPtr<IOThreadContext> context)
         : context_(context) {
-      base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+      base::CurrentThread::Get()->AddDestructionObserver(this);
     }
 
     ~MessageLoopObserver() override {
-      base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+      base::CurrentThread::Get()->RemoveDestructionObserver(this);
     }
 
     void ShutDown() {
diff --git a/content/gpu/gpu_sandbox_hook_linux.cc b/content/gpu/gpu_sandbox_hook_linux.cc
index 85a412bb..6c82ac8 100644
--- a/content/gpu/gpu_sandbox_hook_linux.cc
+++ b/content/gpu/gpu_sandbox_hook_linux.cc
@@ -100,7 +100,7 @@
 
 constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;
 
-void AddV4L2GpuWhitelist(
+void AddV4L2GpuPermissions(
     std::vector<BrokerFilePermission>* permissions,
     const sandbox::policy::SandboxSeccompBPF::Options& options) {
   if (options.accelerated_video_decode_enabled) {
@@ -160,7 +160,7 @@
   }
 }
 
-void AddArmMaliGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
+void AddArmMaliGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   // Device file needed by the ARM GPU userspace.
   static const char kMali0Path[] = "/dev/mali0";
 
@@ -177,14 +177,14 @@
   }
 }
 
-void AddImgPvrGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
+void AddImgPvrGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   // Device node needed by the IMG GPU userspace.
   static const char kPvrSyncPath[] = "/dev/pvr_sync";
 
   permissions->push_back(BrokerFilePermission::ReadWrite(kPvrSyncPath));
 }
 
-void AddAmdGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
+void AddAmdGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   static const char* const kReadOnlyList[] = {"/etc/ld.so.cache",
                                               "/usr/lib64/libEGL.so.1",
                                               "/usr/lib64/libGLESv2.so.2"};
@@ -212,7 +212,7 @@
   }
 }
 
-void AddIntelGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
+void AddIntelGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   static const char* const kReadOnlyList[] = {
       "/dev/dri",
       "/usr/share/vulkan/icd.d",
@@ -220,7 +220,7 @@
   for (const char* item : kReadOnlyList)
     permissions->push_back(BrokerFilePermission::ReadOnly(item));
 
-  // TODO(hob): Whitelist all valid render node paths.
+  // TODO(hob): Allow all valid render node paths.
   static const char kRenderNodePath[] = "/dev/dri/renderD128";
   struct stat st;
   if (stat(kRenderNodePath, &st) == 0) {
@@ -235,7 +235,7 @@
   }
 }
 
-void AddArmGpuWhitelist(std::vector<BrokerFilePermission>* permissions) {
+void AddArmGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   // On ARM we're enabling the sandbox before the X connection is made,
   // so we need to allow access to |.Xauthority|.
   static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
@@ -247,15 +247,15 @@
   permissions->push_back(BrokerFilePermission::ReadOnly(kLibGlesPath));
   permissions->push_back(BrokerFilePermission::ReadOnly(kLibEglPath));
 
-  AddArmMaliGpuWhitelist(permissions);
+  AddArmMaliGpuPermissions(permissions);
 }
 
 // Need to look in vendor paths for custom vendor implementations.
-static const char* const kWhitelistedChromecastPaths[] = {
+static const char* const kAllowedChromecastPaths[] = {
     "/oem_cast_shlib/", "/system/vendor/lib/", "/system/lib/",
     "/system/chrome/lib/"};
 
-void AddChromecastArmGpuWhitelist(
+void AddChromecastArmGpuPermissions(
     std::vector<BrokerFilePermission>* permissions) {
   // Device file needed by the ARM GPU userspace.
   static const char kMali0Path[] = "/dev/mali0";
@@ -264,11 +264,11 @@
   // Files needed by the ARM GPU userspace.
   static const char* const kReadOnlyLibraries[] = {"libGLESv2.so.2",
                                                    "libEGL.so.1",
-                                                   // Whitelist ANGLE libraries.
+                                                   // Allow ANGLE libraries.
                                                    "libGLESv2.so", "libEGL.so"};
 
   for (const char* library : kReadOnlyLibraries) {
-    for (const char* path : kWhitelistedChromecastPaths) {
+    for (const char* path : kAllowedChromecastPaths) {
       const std::string library_path(std::string(path) + std::string(library));
       permissions->push_back(BrokerFilePermission::ReadOnly(library_path));
     }
@@ -286,7 +286,7 @@
   }
 }
 
-void AddStandardGpuWhiteList(std::vector<BrokerFilePermission>* permissions) {
+void AddStandardGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
   static const char kDriCardBasePath[] = "/dev/dri/card";
   static const char kNvidiaCtlPath[] = "/dev/nvidiactl";
   static const char kNvidiaDeviceBasePath[] = "/dev/nvidia";
@@ -330,40 +330,40 @@
 
   if (IsChromeOS()) {
     if (UseV4L2Codec())
-      AddV4L2GpuWhitelist(&permissions, options);
+      AddV4L2GpuPermissions(&permissions, options);
     if (IsArchitectureArm()) {
-      AddImgPvrGpuWhitelist(&permissions);
-      AddArmGpuWhitelist(&permissions);
+      AddImgPvrGpuPermissions(&permissions);
+      AddArmGpuPermissions(&permissions);
       return permissions;
     }
     if (options.use_amd_specific_policies) {
-      AddAmdGpuWhitelist(&permissions);
+      AddAmdGpuPermissions(&permissions);
       return permissions;
     }
     if (options.use_intel_specific_policies) {
-      AddIntelGpuWhitelist(&permissions);
+      AddIntelGpuPermissions(&permissions);
       return permissions;
     }
   }
 
   if (UseChromecastSandboxAllowlist()) {
     if (UseV4L2Codec())
-      AddV4L2GpuWhitelist(&permissions, options);
+      AddV4L2GpuPermissions(&permissions, options);
 
     if (IsArchitectureArm()) {
-      AddChromecastArmGpuWhitelist(&permissions);
+      AddChromecastArmGpuPermissions(&permissions);
       return permissions;
     }
   }
 
-  AddStandardGpuWhiteList(&permissions);
+  AddStandardGpuPermissions(&permissions);
   return permissions;
 }
 
 void LoadArmGpuLibraries() {
   // Preload the Mali library.
   if (UseChromecastSandboxAllowlist()) {
-    for (const char* path : kWhitelistedChromecastPaths) {
+    for (const char* path : kAllowedChromecastPaths) {
       const std::string library_path(std::string(path) +
                                      std::string("libMali.so"));
       if (dlopen(library_path.c_str(), dlopen_flag))
@@ -414,7 +414,7 @@
 }
 
 void LoadChromecastV4L2Libraries() {
-  for (const char* path : kWhitelistedChromecastPaths) {
+  for (const char* path : kAllowedChromecastPaths) {
     const std::string library_path(std::string(path) +
                                    std::string("libvpcodec.so"));
     if (dlopen(library_path.c_str(), dlopen_flag))
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index 62f7afb..7176373f 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -886,7 +886,8 @@
     /**
      * Intialize the menu items for processing text, if there is any.
      */
-    private void initializeTextProcessingMenu(Menu menu) {
+    @VisibleForTesting
+    /* package */ void initializeTextProcessingMenu(Menu menu) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
                 || !isSelectActionModeAllowed(MENU_ITEM_PROCESS_TEXT)) {
             return;
@@ -896,6 +897,8 @@
                 PackageManagerUtils.queryIntentActivities(createProcessTextIntent(), 0);
         for (int i = 0; i < supportedActivities.size(); i++) {
             ResolveInfo resolveInfo = supportedActivities.get(i);
+            if (resolveInfo.activityInfo == null || !resolveInfo.activityInfo.exported) continue;
+
             CharSequence label = resolveInfo.loadLabel(mContext.getPackageManager());
             menu.add(R.id.select_action_menu_text_processing_menus, Menu.NONE,
                         MENU_ITEM_ORDER_TEXT_PROCESS_START + i, label)
diff --git a/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java b/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
index 2332136..c9b9309 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
+++ b/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
@@ -20,10 +20,15 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.provider.Settings;
 import android.view.ActionMode;
+import android.view.Menu;
 import android.view.ViewGroup;
 
 import org.junit.After;
@@ -35,8 +40,10 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.fakes.RoboMenu;
 import org.robolectric.shadows.ShadowLog;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.ContentClassFactory;
@@ -54,6 +61,8 @@
 import org.chromium.ui.touch_selection.SelectionEventType;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Unit tests for {@link SelectionPopupController}.
@@ -644,6 +653,69 @@
         Mockito.verify(spyController, times(3)).finishActionMode();
     }
 
+    @Test
+    @Config(sdk = Build.VERSION_CODES.O)
+    @Feature({"TextInput"})
+    public void testProcessTextMenuItemWithActivityInfo() {
+        // TODO(ctzsm): Consider a better way to distinguish app context and |mContext|.
+        ContextUtils.initApplicationContextForTests(mContext);
+        SelectionPopupControllerImpl spyController = Mockito.spy(mController);
+
+        // test activityInfo exported=false
+        List<ResolveInfo> list1 = new ArrayList();
+        ResolveInfo resolveInfo1 = createResolveInfoWithActivityInfo("ProcessTextActivity1", false);
+        list1.add(resolveInfo1);
+        when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(list1);
+
+        Menu menu1 = new RoboMenu();
+        assertEquals(0, menu1.size());
+        spyController.initializeTextProcessingMenu(menu1);
+        assertEquals(0, menu1.size());
+
+        // test activityInfo exported=true
+        List<ResolveInfo> list2 = new ArrayList();
+        ResolveInfo resolveInfo2 = createResolveInfoWithActivityInfo("ProcessTextActivity2", true);
+        list2.add(resolveInfo2);
+        when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(list2);
+
+        Menu menu2 = new RoboMenu();
+        assertEquals(0, menu2.size());
+        spyController.initializeTextProcessingMenu(menu2);
+        assertEquals(1, menu2.size());
+
+        // test null activityInfo
+        List<ResolveInfo> list3 = new ArrayList();
+        ResolveInfo resolveInfo3 = new ResolveInfo();
+        resolveInfo3.activityInfo = null;
+        list3.add(resolveInfo3);
+        when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(list3);
+
+        Menu menu3 = new RoboMenu();
+        assertEquals(0, menu3.size());
+        spyController.initializeTextProcessingMenu(menu3);
+        assertEquals(0, menu3.size());
+    }
+
+    private ResolveInfo createResolveInfoWithActivityInfo(String activityName, boolean exported) {
+        String packageName = "org.chromium.content.browser.selection.SelectionPopupControllerTest";
+
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = packageName;
+        activityInfo.name = activityName;
+        activityInfo.exported = exported;
+        activityInfo.applicationInfo = new ApplicationInfo();
+        activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        ResolveInfo resolveInfo = new ResolveInfo() {
+            @Override
+            public CharSequence loadLabel(PackageManager pm) {
+                return "TEST_LABEL";
+            }
+        };
+        resolveInfo.activityInfo = activityInfo;
+        return resolveInfo;
+    }
+
     // Result generated by long press "Amphitheatre" in "1600 Amphitheatre Parkway".
     private SelectionClient.Result resultForAmphitheatre() {
         SelectionClient.Result result = new SelectionClient.Result();
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index fca159a..153ebf0 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -131,6 +131,7 @@
     "cookie_store_factory.h",
     "cors_origin_pattern_setter.cc",
     "cors_origin_pattern_setter.h",
+    "dedicated_worker_id.h",
     "dedicated_worker_service.h",
     "desktop_capture.cc",
     "desktop_capture.h",
diff --git a/content/public/browser/browser_main_parts.h b/content/public/browser/browser_main_parts.h
index a792b55..2bfefad 100644
--- a/content/public/browser/browser_main_parts.h
+++ b/content/public/browser/browser_main_parts.h
@@ -29,7 +29,7 @@
 //    things which should be done immediately before the start of the main
 //    message loop should go in |PreMainMessageLoopStart()|.
 //  - RunMainMessageLoopParts:  things to be done before and after invoking the
-//    main message loop run method (e.g. MessageLoopCurrentForUI::Get()->Run()).
+//    main message loop run method (e.g. CurrentUIThread::Get()->Run()).
 //
 // How to add stuff (to existing parts):
 //  - Figure out when your new code should be executed. What must happen
diff --git a/content/public/browser/dedicated_worker_id.h b/content/public/browser/dedicated_worker_id.h
new file mode 100644
index 0000000..c626c53
--- /dev/null
+++ b/content/public/browser/dedicated_worker_id.h
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_ID_H_
+#define CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_ID_H_
+
+#include "base/util/type_safety/id_type.h"
+
+namespace content {
+
+using DedicatedWorkerId = util::IdType64<class DedicatedWorkerTag>;
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_ID_H_
diff --git a/content/public/browser/dedicated_worker_service.h b/content/public/browser/dedicated_worker_service.h
index 773b8eb..b062f04 100644
--- a/content/public/browser/dedicated_worker_service.h
+++ b/content/public/browser/dedicated_worker_service.h
@@ -7,8 +7,8 @@
 
 #include "base/observer_list_types.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/global_routing_id.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 class GURL;
 
@@ -24,11 +24,11 @@
     // yet started in the renderer since its script still has to be downloaded
     // and evaluated.
     virtual void OnWorkerCreated(
-        const blink::mojom::DedicatedWorkerToken& worker_token,
+        DedicatedWorkerId dedicated_worker_id,
         int worker_process_id,
         GlobalFrameRoutingId ancestor_render_frame_host_id) = 0;
     virtual void OnBeforeWorkerDestroyed(
-        const blink::mojom::DedicatedWorkerToken& worker_token,
+        DedicatedWorkerId dedicated_worker_id,
         GlobalFrameRoutingId ancestor_render_frame_host_id) = 0;
 
     // Called when the final response URL (the URL after redirects) was
@@ -36,7 +36,7 @@
     //
     // TODO(pmonette): Implement this in derived classes and make it pure.
     virtual void OnFinalResponseURLDetermined(
-        const blink::mojom::DedicatedWorkerToken& worker_token,
+        DedicatedWorkerId dedicated_worker_id,
         const GURL& url) {}
   };
 
diff --git a/content/public/browser/service_worker_client_info.cc b/content/public/browser/service_worker_client_info.cc
index a0a77eb..d38de92e 100644
--- a/content/public/browser/service_worker_client_info.cc
+++ b/content/public/browser/service_worker_client_info.cc
@@ -10,9 +10,9 @@
     : type_(blink::mojom::ServiceWorkerClientType::kWindow),
       frame_tree_node_id_(frame_tree_node_id) {}
 ServiceWorkerClientInfo::ServiceWorkerClientInfo(
-    const blink::mojom::DedicatedWorkerToken& dedicated_worker_token)
+    DedicatedWorkerId dedicated_worker_id)
     : type_(blink::mojom::ServiceWorkerClientType::kDedicatedWorker),
-      dedicated_worker_token_(dedicated_worker_token) {}
+      dedicated_worker_id_(dedicated_worker_id) {}
 ServiceWorkerClientInfo::ServiceWorkerClientInfo(
     SharedWorkerId shared_worker_id)
     : type_(blink::mojom::ServiceWorkerClientType::kSharedWorker),
@@ -31,10 +31,9 @@
   return frame_tree_node_id_;
 }
 
-const blink::mojom::DedicatedWorkerToken&
-ServiceWorkerClientInfo::GetDedicatedWorkerToken() const {
+DedicatedWorkerId ServiceWorkerClientInfo::GetDedicatedWorkerId() const {
   DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kDedicatedWorker);
-  return dedicated_worker_token_;
+  return dedicated_worker_id_;
 }
 
 SharedWorkerId ServiceWorkerClientInfo::GetSharedWorkerId() const {
diff --git a/content/public/browser/service_worker_client_info.h b/content/public/browser/service_worker_client_info.h
index a5c4a05c..2a5f02e 100644
--- a/content/public/browser/service_worker_client_info.h
+++ b/content/public/browser/service_worker_client_info.h
@@ -6,10 +6,10 @@
 #define CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CLIENT_INFO_H_
 
 #include "content/common/content_export.h"
+#include "content/public/browser/dedicated_worker_id.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/shared_worker_id.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 
 namespace content {
 
@@ -18,8 +18,7 @@
 class CONTENT_EXPORT ServiceWorkerClientInfo {
  public:
   explicit ServiceWorkerClientInfo(int frame_tree_node_id);
-  explicit ServiceWorkerClientInfo(
-      const blink::mojom::DedicatedWorkerToken& dedicated_worker_token);
+  explicit ServiceWorkerClientInfo(DedicatedWorkerId dedicated_worker_id);
   explicit ServiceWorkerClientInfo(SharedWorkerId shared_worker_id);
 
   ServiceWorkerClientInfo(const ServiceWorkerClientInfo& other);
@@ -31,7 +30,7 @@
   blink::mojom::ServiceWorkerClientType type() const { return type_; }
 
   int GetFrameTreeNodeId() const;
-  const blink::mojom::DedicatedWorkerToken& GetDedicatedWorkerToken() const;
+  DedicatedWorkerId GetDedicatedWorkerId() const;
   SharedWorkerId GetSharedWorkerId() const;
 
  private:
@@ -42,7 +41,7 @@
   int frame_tree_node_id_ = content::RenderFrameHost::kNoFrameTreeNodeId;
 
   // The ID of the client, if this is a dedicated worker client.
-  blink::mojom::DedicatedWorkerToken dedicated_worker_token_;
+  DedicatedWorkerId dedicated_worker_id_;
 
   // The ID of the client, if this is a shared worker client.
   SharedWorkerId shared_worker_id_;
diff --git a/content/public/test/browser_task_environment.cc b/content/public/test/browser_task_environment.cc
index 4aa7d15..b7d3c50e 100644
--- a/content/public/test/browser_task_environment.cc
+++ b/content/public/test/browser_task_environment.cc
@@ -11,9 +11,9 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -102,7 +102,7 @@
   // |BrowserThreadImpl::GetTaskRunnerForThread(identifier_)| will no longer
   // recognize their BrowserThreadImpl for RunsTasksInCurrentSequence(). This
   // happens most often when such verifications are made from
-  // MessageLoopCurrent::DestructionObservers. Callers that care to work around
+  // CurrentThread::DestructionObservers. Callers that care to work around
   // that should instead use this shutdown sequence:
   //   1) TestBrowserThread::Stop()
   //   2) ~MessageLoop()
@@ -188,9 +188,9 @@
   DeferredInitFromSubclass(std::move(default_ui_task_runner));
 
   if (HasIOMainLoop()) {
-    CHECK(base::MessageLoopCurrentForIO::IsSet());
+    CHECK(base::CurrentIOThread::IsSet());
   } else if (main_thread_type() == MainThreadType::UI) {
-    CHECK(base::MessageLoopCurrentForUI::IsSet());
+    CHECK(base::CurrentUIThread::IsSet());
   }
 
   // Set the current thread as the UI thread.
diff --git a/content/public/test/browser_task_environment_unittest.cc b/content/public/test/browser_task_environment_unittest.cc
index dc4a6da..1e50eb1 100644
--- a/content/public/test/browser_task_environment_unittest.cc
+++ b/content/public/test/browser_task_environment_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/atomicops.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/test/bind_test_util.h"
@@ -139,8 +139,8 @@
       BrowserTaskEnvironment::Options::REAL_IO_THREAD,
       base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED);
   // Should set up a UI main thread.
-  EXPECT_TRUE(base::MessageLoopCurrentForUI::IsSet());
-  EXPECT_FALSE(base::MessageLoopCurrentForIO::IsSet());
+  EXPECT_TRUE(base::CurrentUIThread::IsSet());
+  EXPECT_FALSE(base::CurrentIOThread::IsSet());
 
   // Should create a real IO thread. If it was on the same thread the following
   // will timeout.
@@ -171,8 +171,8 @@
       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
 
   // Should set up a UI main thread.
-  EXPECT_TRUE(base::MessageLoopCurrentForUI::IsSet());
-  EXPECT_FALSE(base::MessageLoopCurrentForIO::IsSet());
+  EXPECT_TRUE(base::CurrentUIThread::IsSet());
+  EXPECT_FALSE(base::CurrentIOThread::IsSet());
 
   // There should be a mock clock.
   EXPECT_THAT(task_environment.GetMockClock(), testing::NotNull());
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 79ce28b..5ab92dc 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -19,13 +19,13 @@
 #include "base/i18n/icu_util.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_run_loop_timeout.h"
@@ -644,7 +644,7 @@
     // This can be called from a posted task. Allow nested tasks here, because
     // otherwise the test body will have to do it in order to use RunLoop for
     // waiting.
-    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    base::CurrentThread::ScopedNestableTaskAllower allow;
 
 #if !defined(OS_ANDROID)
     // Fail the test if a renderer crashes while the test is running.
diff --git a/content/public/test/content_browser_test.cc b/content/public/test/content_browser_test.cc
index f5dc75c4..a9c21b9 100644
--- a/content/public/test/content_browser_test.cc
+++ b/content/public/test/content_browser_test.cc
@@ -6,9 +6,9 @@
 
 #include "base/check_op.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_paths.h"
@@ -122,7 +122,7 @@
 #endif
 
   // Pump startup related events.
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   base::RunLoop().RunUntilIdle();
 
 #if defined(OS_MACOSX)
diff --git a/content/public/test/frame_load_waiter.h b/content/public/test/frame_load_waiter.h
index 46af120..b032551 100644
--- a/content/public/test/frame_load_waiter.h
+++ b/content/public/test/frame_load_waiter.h
@@ -19,7 +19,7 @@
   explicit FrameLoadWaiter(RenderFrame* frame);
 
   // Note: single-process browser tests need to enable nestable tasks by
-  // instantiating a base::MessageLoopCurrent::ScopedNestableTaskAllower or this
+  // instantiating a base::CurrentThread::ScopedNestableTaskAllower or this
   // method will never return.
   void Wait();
 
diff --git a/content/public/test/network_service_test_helper.cc b/content/public/test/network_service_test_helper.cc
index 2a1b9c7..26bf6c82 100644
--- a/content/public/test/network_service_test_helper.cc
+++ b/content/public/test/network_service_test_helper.cc
@@ -13,9 +13,9 @@
 #include "base/environment.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/process/process.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -74,7 +74,7 @@
 
 class NetworkServiceTestHelper::NetworkServiceTestImpl
     : public network::mojom::NetworkServiceTest,
-      public base::MessageLoopCurrent::DestructionObserver {
+      public base::CurrentThread::DestructionObserver {
  public:
   NetworkServiceTestImpl()
       : test_host_resolver_(new TestHostResolver()),
@@ -268,12 +268,12 @@
       mojo::PendingReceiver<network::mojom::NetworkServiceTest> receiver) {
     receivers_.Add(this, std::move(receiver));
     if (!registered_as_destruction_observer_) {
-      base::MessageLoopCurrentForIO::Get()->AddDestructionObserver(this);
+      base::CurrentIOThread::Get()->AddDestructionObserver(this);
       registered_as_destruction_observer_ = true;
     }
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     // Needs to be called on the IO thread.
     receivers_.Clear();
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 8ddf6d8..9d0d369f 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -116,7 +116,7 @@
   // graphics services. Some tests have their own, so this only creates one
   // (single-threaded) when none exists. This means tests must ensure any
   // TaskEnvironment they make is created before the RenderViewHostTestEnabler.
-  if (!base::MessageLoopCurrent::Get()) {
+  if (!base::CurrentThread::Get()) {
     task_environment_ =
         std::make_unique<base::test::SingleThreadTaskEnvironment>();
   }
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index aa31e5e..d0e3f75 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -11,11 +11,11 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/sequence_manager/sequence_manager.h"
 #include "base/task/task_observer.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
@@ -130,7 +130,7 @@
 }
 
 void RunThisRunLoop(base::RunLoop* run_loop) {
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  base::CurrentThread::ScopedNestableTaskAllower allow;
   run_loop->Run();
 }
 
@@ -152,7 +152,7 @@
     // current loop iteration and loop in case the MessageLoop posts tasks to
     // the Task Scheduler after the initial flush.
     TaskObserver task_observer;
-    base::MessageLoopCurrent::Get()->AddTaskObserver(&task_observer);
+    base::CurrentThread::Get()->AddTaskObserver(&task_observer);
 
     // This must use RunLoop::Type::kNestableTasksAllowed in case this
     // RunAllTasksUntilIdle() call is nested inside an existing Run(). Without
@@ -165,7 +165,7 @@
 
     run_loop.Run();
 
-    base::MessageLoopCurrent::Get()->RemoveTaskObserver(&task_observer);
+    base::CurrentThread::Get()->RemoveTaskObserver(&task_observer);
 
     if (!task_observer.processed())
       break;
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index 01532ed..d611eeb 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -447,6 +447,10 @@
     tree_data->sel_focus_affinity = focus_affinity;
   }
 
+  // Get the tree ID for this frame.
+  if (WebLocalFrame* web_frame = document().GetFrame())
+    tree_data->tree_id = web_frame->GetAXTreeID();
+
   tree_data->root_scroller_id = root().RootScroller().AxID();
 
   return true;
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc
index 951adf6f..6f36fb6 100644
--- a/content/renderer/dom_serializer_browsertest.cc
+++ b/content/renderer/dom_serializer_browsertest.cc
@@ -10,9 +10,9 @@
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "content/public/browser/render_view_host.h"
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index 433aec7..b218158 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -653,8 +653,13 @@
 
 #if BUILDFLAG(IS_CHROMECAST)
   if (renderer_media_playback_options.is_remoting_renderer_enabled()) {
+#if BUILDFLAG(ENABLE_CAST_RENDERER)
+    auto default_factory = std::make_unique<CastRendererClientFactory>(
+        media_log, CreateMojoRendererFactory());
+#else
     auto default_factory = CreateDefaultRendererFactory(
         media_log, decoder_factory, render_thread, render_frame_);
+#endif
     mojo::PendingRemote<media::mojom::Remotee> remotee;
     interface_broker_->GetInterface(remotee.InitWithNewPipeAndPassReceiver());
     auto remoting_renderer_factory =
diff --git a/content/renderer/visual_state_browsertest.cc b/content/renderer/visual_state_browsertest.cc
index 1b3814f..3a6a05c 100644
--- a/content/renderer/visual_state_browsertest.cc
+++ b/content/renderer/visual_state_browsertest.cc
@@ -5,8 +5,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/containers/flat_map.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -75,7 +75,7 @@
   }
 
   void AssertIsIdle() {
-    ASSERT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+    ASSERT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   }
 
   void InvokeVisualStateCallback(bool result) {
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc
index 5fa43185..ecffcf8 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.cc
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -20,7 +20,6 @@
 #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom.h"
 #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
 #include "third_party/blink/public/platform/web_dedicated_worker.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -37,31 +36,26 @@
 DedicatedWorkerHostFactoryClient::~DedicatedWorkerHostFactoryClient() = default;
 
 void DedicatedWorkerHostFactoryClient::CreateWorkerHostDeprecated(
-    const base::UnguessableToken& dedicated_worker_token,
     base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)>
         callback) {
   DCHECK(!base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
-  DCHECK(!dedicated_worker_token.is_empty());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   factory_->CreateWorkerHost(
-      blink::mojom::DedicatedWorkerToken::New(dedicated_worker_token),
       browser_interface_broker.InitWithNewPipeAndPassReceiver(),
       std::move(callback));
   OnWorkerHostCreated(std::move(browser_interface_broker));
 }
 
 void DedicatedWorkerHostFactoryClient::CreateWorkerHost(
-    const base::UnguessableToken& dedicated_worker_token,
     const blink::WebURL& script_url,
     network::mojom::CredentialsMode credentials_mode,
     const blink::WebFetchClientSettingsObject& fetch_client_settings_object,
     blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase>
         blob_url_token) {
   DCHECK(base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
-  DCHECK(!dedicated_worker_token.is_empty());
+
   factory_->CreateWorkerHostAndStartScriptLoad(
-      blink::mojom::DedicatedWorkerToken::New(dedicated_worker_token),
       script_url, credentials_mode,
       FetchClientSettingsObjectFromWebToMojom(fetch_client_settings_object),
       std::move(blob_url_token), receiver_.BindNewPipeAndPassRemote());
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.h b/content/renderer/worker/dedicated_worker_host_factory_client.h
index e311bc4..9454baab 100644
--- a/content/renderer/worker/dedicated_worker_host_factory_client.h
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.h
@@ -44,11 +44,9 @@
 
   // Implements blink::WebDedicatedWorkerHostFactoryClient.
   void CreateWorkerHostDeprecated(
-      const base::UnguessableToken& dedicated_worker_token,
       base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)>
           callback) override;
   void CreateWorkerHost(
-      const base::UnguessableToken& dedicated_worker_token,
       const blink::WebURL& script_url,
       network::mojom::CredentialsMode credentials_mode,
       const blink::WebFetchClientSettingsObject& fetch_client_settings_object,
diff --git a/content/shell/browser/shell_browser_main_parts.cc b/content/shell/browser/shell_browser_main_parts.cc
index 5bdcff9..d033d1ff 100644
--- a/content/shell/browser/shell_browser_main_parts.cc
+++ b/content/shell/browser/shell_browser_main_parts.cc
@@ -9,7 +9,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
diff --git a/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-auralinux.txt b/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-auralinux.txt
index d7f55fb8..48cb3d9 100644
--- a/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-auralinux.txt
+++ b/content/test/data/accessibility/event/aria-combo-box-delay-show-list-expected-auralinux.txt
@@ -1,7 +1,6 @@
 CHILDREN-CHANGED index:0 CHILD:(role=ROLE_SECTION) role=ROLE_DOCUMENT_WEB ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
 CHILDREN-CHANGED index:1 CHILD:(role=ROLE_LIST_BOX) role=ROLE_DOCUMENT_WEB ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
 FOCUS-EVENT role=ROLE_LIST_ITEM name='Apple' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-NAME-CHANGED:(null) role=ROLE_LIST_BOX name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VERTICAL,VISIBLE
 SELECTION-CHANGED role=ROLE_LIST_BOX name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VERTICAL,VISIBLE
 STATE-CHANGE:FOCUSED:TRUE role=ROLE_LIST_ITEM name='Apple' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
 STATE-CHANGE:SELECTED:TRUE role=ROLE_LIST_ITEM name='Apple' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/disabled-state-changed-expected-auralinux.txt b/content/test/data/accessibility/event/disabled-state-changed-expected-auralinux.txt
new file mode 100644
index 0000000..dbd2d94d
--- /dev/null
+++ b/content/test/data/accessibility/event/disabled-state-changed-expected-auralinux.txt
@@ -0,0 +1,2 @@
+STATE-CHANGE:ENABLED:FALSE role=ROLE_PUSH_BUTTON name='Button 1 turns disabled on' SHOWING,VISIBLE
+STATE-CHANGE:ENABLED:TRUE role=ROLE_PUSH_BUTTON name='Button 2 turns disabled off' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-auralinux.txt b/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-auralinux.txt
new file mode 100644
index 0000000..f734138
--- /dev/null
+++ b/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-auralinux.txt
@@ -0,0 +1,9 @@
+STATE-CHANGE:ENABLED:FALSE role=ROLE_SLIDER name='(null)' HORIZONTAL,SHOWING,VISIBLE
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:TRUE role=ROLE_SLIDER name='(null)' ENABLED,FOCUSABLE,HORIZONTAL,SENSITIVE,SHOWING,VISIBLE
+=== Start Continuation ===
+=== Start Continuation ===
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:FALSE role=ROLE_SLIDER name='(null)' FOCUSABLE,HORIZONTAL,SHOWING,VISIBLE
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:TRUE role=ROLE_SLIDER name='(null)' ENABLED,FOCUSABLE,HORIZONTAL,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/style-changed-expected-auralinux.txt b/content/test/data/accessibility/event/style-changed-expected-auralinux.txt
new file mode 100644
index 0000000..819e354
--- /dev/null
+++ b/content/test/data/accessibility/event/style-changed-expected-auralinux.txt
@@ -0,0 +1,10 @@
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p1' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p2' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p3' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p4' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p5' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p6' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p7' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p8' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_PARAGRAPH name='p9' ENABLED,SENSITIVE,SHOWING,VISIBLE
+TEXT-ATTRIBUTES-CHANGED role=ROLE_SECTION name='span10' ENABLED,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/style-changed-expected-uia-win.txt b/content/test/data/accessibility/event/style-changed-expected-uia-win.txt
new file mode 100644
index 0000000..d10c369
--- /dev/null
+++ b/content/test/data/accessibility/event/style-changed-expected-uia-win.txt
@@ -0,0 +1,10 @@
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
+Text_TextChanged on role=document
diff --git a/content/test/data/accessibility/event/style-changed-expected-win.txt b/content/test/data/accessibility/event/style-changed-expected-win.txt
new file mode 100644
index 0000000..3899dc92
--- /dev/null
+++ b/content/test/data/accessibility/event/style-changed-expected-win.txt
@@ -0,0 +1,11 @@
+EVENT_OBJECT_LOCATIONCHANGE on <p#p10> role=ROLE_SYSTEM_GROUPING
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p1> role=ROLE_SYSTEM_GROUPING name="p1"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p2> role=ROLE_SYSTEM_GROUPING name="p2"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p3> role=ROLE_SYSTEM_GROUPING name="p3"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p4> role=ROLE_SYSTEM_GROUPING name="p4"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p5> role=ROLE_SYSTEM_GROUPING name="p5"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p6> role=ROLE_SYSTEM_GROUPING name="p6"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p7> role=ROLE_SYSTEM_GROUPING name="p7"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p8> role=ROLE_SYSTEM_GROUPING name="p8"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <p#p9> role=ROLE_SYSTEM_GROUPING name="p9"
+IA2_EVENT_TEXT_ATTRIBUTE_CHANGED on <span#span10> role=ROLE_SYSTEM_GROUPING name="span10"
diff --git a/content/test/data/accessibility/event/style-changed.html b/content/test/data/accessibility/event/style-changed.html
new file mode 100644
index 0000000..8bce52c
--- /dev/null
+++ b/content/test/data/accessibility/event/style-changed.html
@@ -0,0 +1,37 @@
+<!--
+@AURALINUX-DENY:STATE-CHANGE:DEFUNCT*
+-->
+<!DOCTYPE html>
+<p id="p1" aria-label="p1">One</p>
+<p id="p2" aria-label="p2">Two</p>
+<p id="p3" aria-label="p3">Three</p>
+<p id="p4" aria-label="p4">Four</p>
+<p id="p5" aria-label="p5">Five</p>
+<p id="p6" aria-label="p6">Six</p>
+<p id="p7" aria-label="p7">Seven</p>
+<p id="p8" aria-label="p8">Eight</p>
+<p id="p9" aria-label="p9">Nine</p>
+<p id="p10">Ten<span aria-label="span10" id="span10">10</span></p>
+<script>
+  function go() {
+    document.getElementById("p1").style.backgroundColor = "red";
+    document.getElementById("p2").style.color = "orange";
+    document.getElementById("p3").style.fontWeight = "bold";
+    document.getElementById("p4").style.fontStyle = "italic";
+    document.getElementById("p5").style.textDecoration = "overline";
+    document.getElementById("p6").style.textDecoration = "underline";
+    document.getElementById("p7").style.textDecoration = "line-through";
+
+    // To ensure we don't emit one event per change.
+    document.getElementById("p8").style.backgroundColor = "red";
+    document.getElementById("p8").style.color = "orange";
+    document.getElementById("p8").style.fontWeight = "bold";
+    document.getElementById("p8").style.fontStyle = "italic";
+    document.getElementById("p8").style.textDecoration = "overline";
+    document.getElementById("p8").style.textDecoration = "underline";
+    document.getElementById("p8").style.textDecoration = "line-through";
+
+    document.getElementById("p9").style.direction = "rtl";
+    document.getElementById("span10").style.verticalAlign = "super";
+  }
+</script>
diff --git a/content/test/data/accessibility/event/value-is-readonly-changed-expected-auralinux.txt b/content/test/data/accessibility/event/value-is-readonly-changed-expected-auralinux.txt
new file mode 100644
index 0000000..147442c
--- /dev/null
+++ b/content/test/data/accessibility/event/value-is-readonly-changed-expected-auralinux.txt
@@ -0,0 +1,11 @@
+STATE-CHANGE:ENABLED:FALSE role=ROLE_ENTRY name='(null)' EDITABLE,SHOWING,SINGLE-LINE,VISIBLE,SELECTABLE-TEXT
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:TRUE role=ROLE_ENTRY name='(null)' EDITABLE,ENABLED,FOCUSABLE,SENSITIVE,SHOWING,SINGLE-LINE,VISIBLE,SELECTABLE-TEXT
+=== Start Continuation ===
+=== Start Continuation ===
+=== Start Continuation ===
+=== Start Continuation ===
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:FALSE role=ROLE_ENTRY name='(null)' EDITABLE,FOCUSABLE,SHOWING,SINGLE-LINE,VISIBLE,SELECTABLE-TEXT
+=== Start Continuation ===
+STATE-CHANGE:ENABLED:TRUE role=ROLE_ENTRY name='(null)' EDITABLE,ENABLED,FOCUSABLE,SENSITIVE,SHOWING,SINGLE-LINE,VISIBLE,SELECTABLE-TEXT
diff --git a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
index a206b2a..1a932a8 100644
--- a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
@@ -11,10 +11,10 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/task_environment.h"
 #include "dbus/object_path.h"
@@ -286,7 +286,7 @@
   // without using this function.
   void DiscoverDevice(const std::string& address) {
     ASSERT_TRUE(adapter_.get() != nullptr);
-    ASSERT_TRUE(base::MessageLoopCurrent::IsSet());
+    ASSERT_TRUE(base::CurrentThread::IsSet());
     fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
 
     TestBluetoothAdapterObserver observer(adapter_);
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md
index 4e3b222..a7df61e2 100644
--- a/docs/threading_and_tasks.md
+++ b/docs/threading_and_tasks.md
@@ -879,7 +879,7 @@
 Sample workaround when inner task processing is needed:
   HRESULT hr;
   {
-    MessageLoopCurrent::ScopedNestableTaskAllower allow;
+    CurrentThread::ScopedNestableTaskAllower allow;
     hr = DoDragDrop(...); // Implicitly runs a modal message loop.
   }
   // Process |hr| (the result returned by DoDragDrop()).
@@ -887,7 +887,7 @@
 
 Please be SURE your task is reentrant (nestable) and all global variables
 are stable and accessible before before using
-MessageLoopCurrent::ScopedNestableTaskAllower.
+CurrentThread::ScopedNestableTaskAllower.
 
 ## APIs for general use
 
@@ -914,10 +914,10 @@
 Unit tests can use [TaskEnvironment](https://cs.chromium.org/chromium/src/base/test/task_environment.h)
 which is highly configurable.
 
-## MessageLoop and MessageLoopCurrent
+## MessageLoop and CurrentThread
 
-You might come across references to MessageLoop or MessageLoopCurrent in the
+You might come across references to MessageLoop or CurrentThread in the
 code or documentation. These classes no longer exist and we are in the process
-or getting rid of all references to them. base::MessageLoopCurrent was replaced
+or getting rid of all references to them. base::CurrentThread was replaced
 by base::CurrentThread and the drop in replacements for base::MessageLoop are
 base::SingleThreadTaskExecutor and base::Test::TaskEnvironment.
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
index 314f3d5..b11f5908 100644
--- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
+++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -228,6 +228,7 @@
     case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
     case ui::AXEventGenerator::Event::SORT_CHANGED:
     case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+    case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
     case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
diff --git a/extensions/shell/test/shell_test.cc b/extensions/shell/test/shell_test.cc
index 301b17d4e70..9053e2d9 100644
--- a/extensions/shell/test/shell_test.cc
+++ b/extensions/shell/test/shell_test.cc
@@ -7,8 +7,8 @@
 #include "base/check.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/shell/browser/desktop_controller.h"
@@ -45,7 +45,7 @@
   extension_system_ = static_cast<ShellExtensionSystem*>(
       ExtensionSystem::Get(browser_context_));
   extension_system_->FinishInitialization();
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/fuchsia/http/http_service_unittest.cc b/fuchsia/http/http_service_unittest.cc
index 2a6ca9f1..a7e5189a 100644
--- a/fuchsia/http/http_service_unittest.cc
+++ b/fuchsia/http/http_service_unittest.cc
@@ -5,8 +5,8 @@
 #include <fuchsia/net/oldhttp/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "fuchsia/http/http_service_impl.h"
 #include "fuchsia/http/url_loader_impl.h"
@@ -115,7 +115,7 @@
   TestZxHandleWatcher watcher(run_loop.QuitClosure());
   base::MessagePumpForIO::ZxHandleWatchController watch_contoller(FROM_HERE);
 
-  base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+  base::CurrentIOThread::Get()->WatchZxHandle(
       handle, /*persistent=*/false, signals, &watch_contoller, &watcher);
   run_loop.Run();
 
diff --git a/fuchsia/http/url_loader_impl.cc b/fuchsia/http/url_loader_impl.cc
index fdcdf92..75c3e7d 100644
--- a/fuchsia/http/url_loader_impl.cc
+++ b/fuchsia/http/url_loader_impl.cc
@@ -5,7 +5,7 @@
 #include "fuchsia/http/url_loader_impl.h"
 
 #include "base/fuchsia/fuchsia_logging.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "fuchsia/base/mem_buffer_util.h"
 #include "net/base/chunked_upload_data_stream.h"
@@ -361,7 +361,7 @@
     if (status == ZX_ERR_SHOULD_WAIT) {
       // Wait until the socket is writable again.
       buffered_bytes_ = result;
-      base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+      base::CurrentIOThread::Get()->WatchZxHandle(
           write_socket_.get(), false /* persistent */,
           ZX_SOCKET_WRITABLE | ZX_SOCKET_PEER_CLOSED, &write_watch_, this);
       return false;
diff --git a/fuchsia/runners/cast/cast_component.cc b/fuchsia/runners/cast/cast_component.cc
index 863de88..7bd5ed4 100644
--- a/fuchsia/runners/cast/cast_component.cc
+++ b/fuchsia/runners/cast/cast_component.cc
@@ -13,8 +13,8 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/fuchsia/fuchsia_logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
+#include "base/task/current_thread.h"
 #include "fuchsia/base/agent_manager.h"
 #include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
@@ -206,7 +206,7 @@
     // Scenic View. It is merely used as a conduit for propagating termination
     // signals.
     headless_view_token_ = std::move(view_token);
-    base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+    base::CurrentIOThread::Get()->WatchZxHandle(
         headless_view_token_.get(), false /* persistent */,
         ZX_SOCKET_PEER_CLOSED, &headless_disconnect_watch_, this);
 
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
index 570a23a..13f6369 100644
--- a/gin/isolate_holder.cc
+++ b/gin/isolate_holder.cc
@@ -12,9 +12,9 @@
 #include <utility>
 
 #include "base/check_op.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "gin/debug_impl.h"
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc
index c8036b3..0ed94e6e 100644
--- a/gpu/ipc/service/gpu_watchdog_thread.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread.cc
@@ -12,7 +12,6 @@
 #include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/process/process.h"
@@ -20,6 +19,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "gpu/config/gpu_crash_keys.h"
@@ -102,7 +102,7 @@
   UpdateActiveTTY();
   host_tty_ = active_tty_;
 #endif
-  base::MessageLoopCurrent::Get()->AddTaskObserver(&task_observer_);
+  base::CurrentThread::Get()->AddTaskObserver(&task_observer_);
 }
 
 // static
@@ -244,7 +244,7 @@
     fclose(tty_file_);
 #endif
 
-  base::MessageLoopCurrent::Get()->RemoveTaskObserver(&task_observer_);
+  base::CurrentThread::Get()->RemoveTaskObserver(&task_observer_);
 }
 
 void GpuWatchdogThreadImplV1::OnAcknowledge() {
diff --git a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
index 420faeb..2c3f81c 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
@@ -5,9 +5,9 @@
 #include "base/test/task_environment.h"
 #include "gpu/ipc/service/gpu_watchdog_thread_v2.h"
 
-#include "base/message_loop/message_loop_current.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
+#include "base/task/current_thread.h"
 #include "base/test/power_monitor_test_base.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -67,7 +67,7 @@
 
 void GpuWatchdogTest::SetUp() {
   ASSERT_TRUE(base::ThreadTaskRunnerHandle::IsSet());
-  ASSERT_TRUE(base::MessageLoopCurrent::IsSet());
+  ASSERT_TRUE(base::CurrentThread::IsSet());
 
   // Set watchdog timeout to 1000 milliseconds
   watchdog_thread_ = gpu::GpuWatchdogThreadImplV2::Create(
diff --git a/gpu/ipc/service/gpu_watchdog_thread_v2.cc b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
index c22b732..dd61be8 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_v2.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
@@ -13,7 +13,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/native_library.h"
@@ -21,6 +20,7 @@
 #include "base/process/process.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/system/sys_info.h"
+#include "base/task/current_thread.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -58,7 +58,7 @@
       max_extra_cycles_before_kill_(max_extra_cycles_before_kill),
       is_test_mode_(is_test_mode),
       watched_gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-  base::MessageLoopCurrent::Get()->AddTaskObserver(this);
+  base::CurrentThread::Get()->AddTaskObserver(this);
   num_of_processors_ = base::SysInfo::NumberOfProcessors();
 
 #if defined(OS_WIN)
@@ -92,7 +92,7 @@
 
   Stop();  // stop the watchdog thread
 
-  base::MessageLoopCurrent::Get()->RemoveTaskObserver(this);
+  base::CurrentThread::Get()->RemoveTaskObserver(this);
   base::PowerMonitor::RemoveObserver(this);
   GpuWatchdogHistogram(GpuWatchdogThreadEvent::kGpuWatchdogEnd);
 #if defined(OS_WIN)
diff --git a/headless/test/headless_browser_test.cc b/headless/test/headless_browser_test.cc
index 2bdcca96..7eb36b4 100644
--- a/headless/test/headless_browser_test.cc
+++ b/headless/test/headless_browser_test.cc
@@ -10,9 +10,9 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 8be1315..8dbcee9 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1623,11 +1623,11 @@
       <message name="IDS_IOS_CHECK_PASSWORDS_DESCRIPTION" desc="Description for the Password Check item in Settings" meaning="Label is shown to explain purpose of Password Check feature. This string is shown only if user didn't run Password Check before or check finished due to error without any results.  [iOS only]">
         Keep your passwords safe from security issues
       </message>
-      <message name="IDS_IOS_CHECK_PASSWORDS_SAFE_STATE" desc="Description for the Password Check item in Settings" meaning="Label is shown when no issues were found during password check. [iOS only]">
-        No passwords compromised
-      </message>
-      <message name="IDS_IOS_CHECK_PASSWORDS_UNSAFE_STATE" desc="Description for the Password Check item in Settings" meaning="Label is shown when compromised credentials were found during password check. [iOS only]">
-        Passwords compromised
+      <message name="IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT" desc="Displays the number of compromised passwords present in the database">
+        {COUNT, plural,
+          =0 {No passwords compromised}
+          =1 {{COUNT} Password compromised}
+          other {{COUNT} Passwords compromised}}
       </message>
       <message name="IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON" desc="Label of a button which starts Password Check [Length: 22em] [iOS only]" meaning="By clicking this button user will start checking all passwords for security issues.">
         Check Now
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1
new file mode 100644
index 0000000..6627543
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT.png.sha1
@@ -0,0 +1 @@
+50f9da3214aa8cc48c5c1038753cb1aa27073713
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_SAFE_STATE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_SAFE_STATE.png.sha1
deleted file mode 100644
index 6e1d01c..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_SAFE_STATE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-2ca0f184b7da1ef01735d614bb03a58467d6587e
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_UNSAFE_STATE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_UNSAFE_STATE.png.sha1
deleted file mode 100644
index ddd88fb..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CHECK_PASSWORDS_UNSAFE_STATE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-681e0ec48c1ac1017594daf5aed8dc8d3cb49f81
\ No newline at end of file
diff --git a/ios/chrome/browser/installation_notifier_unittest.mm b/ios/chrome/browser/installation_notifier_unittest.mm
index ea54d40..0e25f51 100644
--- a/ios/chrome/browser/installation_notifier_unittest.mm
+++ b/ios/chrome/browser/installation_notifier_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "ios/chrome/browser/installation_notifier.h"
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 
 #include <stdint.h>
 #import <UIKit/UIKit.h>
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index d795203..6fde3f56 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -366,9 +366,14 @@
 // Track detaching iframes.
 - (void)webState:(WebState*)webState
     frameWillBecomeUnavailable:(WebFrame*)web_frame {
+  // No need to try to detect submissions when the webState is being destroyed.
+  if (webState->IsBeingDestroyed())
+    return;
   if (web_frame->IsMainFrame() || !web_frame->CanCallJavaScriptFunction())
     return;
-  _passwordManager->OnIframeDetach(web_frame->GetFrameId());
+  _passwordManager->OnIframeDetach(web_frame->GetFrameId(),
+                                   self.passwordManagerDriver,
+                                   self.formHelper.fieldDataManager.get());
 }
 
 #pragma mark - FormSuggestionProvider
@@ -1064,7 +1069,8 @@
   // whether the form was submitted.
   if (params.type == "password_form_removed") {
     self.passwordManager->OnPasswordFormRemoved(
-        self.passwordManagerDriver, FormRendererId(params.unique_form_id));
+        self.passwordManagerDriver, self.formHelper.fieldDataManager.get(),
+        FormRendererId(params.unique_form_id));
   }
 }
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
index 69cdf8b..ac402dba 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
@@ -442,8 +442,7 @@
 
 // Tests that the credit card View Controller is dismissed when tapping the
 // keyboard.
-// TODO(crbug.com/1099432): Test fails on iPad when rolling EG2 version.
-- (void)DISABLED_testTappingKeyboardDismissCreditCardControllerPopOver {
+- (void)testTappingKeyboardDismissCreditCardControllerPopOver {
   if (![ChromeEarlGrey isIPadIdiom]) {
     return;
   }
@@ -462,9 +461,10 @@
       selectElementWithMatcher:ManualFallbackCreditCardTableViewMatcher()]
       assertWithMatcher:grey_sufficientlyVisible()];
 
-  [[EarlGrey
-      selectElementWithMatcher:[KeyboardAppInterface keyboardWindowMatcher]]
-      performAction:grey_typeText(@"text")];
+  // Tap a keyboard key directly. Typing with EG helpers do not trigger physical
+  // keyboard presses.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"G")]
+      performAction:grey_tap()];
 
   // Verify the credit card controller table view and the credit card icon is
   // NOT visible.
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 490bb81..de02ef5 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1599,6 +1599,13 @@
     [self.tabStripCoordinator hideTabStrip:![self canShowTabStrip]];
     _fakeStatusBarView.hidden = ![self canShowTabStrip];
     [self addConstraintsToPrimaryToolbar];
+    // If tabstrip is coming back due to a window resize or screen rotation,
+    // reset the full screen controller to adjust the tabstrip position.
+    if (ShouldShowCompactToolbar(previousTraitCollection) &&
+        !ShouldShowCompactToolbar()) {
+      [self
+          updateForFullscreenProgress:self.fullscreenController->GetProgress()];
+    }
   }
 
   [self setNeedsStatusBarAppearanceUpdate];
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
index a816cd9..5738aa0 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
@@ -94,8 +94,9 @@
   ~DownloadManagerCoordinatorTest() override {
     // Stop to avoid holding a dangling pointer to destroyed task.
     @autoreleasepool {
-      // task_environment_ has to outlive the coordinator. Dismissing
-      // coordinator retains are autoreleases it.
+      // Calling -stop will retain and autorelease coordinator_.
+      // task_environment_ has to outlive the coordinator, so wrapping -stop
+      // call in @autorelease will ensure that coordinator_ is deallocated.
       [coordinator_ stop];
     }
 
@@ -153,8 +154,9 @@
   coordinator_.downloadTask = &task;
   [coordinator_ start];
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -stop will retain and autorelease coordinator_. task_environment_
+    // has to outlive the coordinator, so wrapping -stop call in @autorelease
+    // will ensure that coordinator_ is deallocated.
     [coordinator_ stop];
   }
 
@@ -182,7 +184,10 @@
       base::ThreadTaskRunnerHandle::Get(), path));
 
   @autoreleasepool {
-    // These calls will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
 
@@ -298,8 +303,10 @@
                        didCreateDownload:task.get()
                        webStateIsVisible:YES];
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -downloadManagerTabHelper:didHideDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerTabHelper:didHideDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [coordinator_ downloadManagerTabHelper:&tab_helper_
                            didHideDownload:task.get()];
   }
@@ -346,7 +353,10 @@
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
   ASSERT_EQ(0, user_action_tester_.GetActionCount("IOSDownloadClose"));
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidClose: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidClose:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidClose:viewController];
   }
@@ -386,7 +396,10 @@
   ASSERT_EQ(
       0, user_action_tester_.GetActionCount("IOSDownloadInstallGoogleDrive"));
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -installDriveForDownloadManagerViewController: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -installDriveForDownloadManagerViewController:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         installDriveForDownloadManagerViewController:viewController];
   }
@@ -452,7 +465,11 @@
 
   // Present Open In... menu.
   @autoreleasepool {
-    // These calls will retain coordinator, which should outlive thread bundle.
+    // Calling -installDriveForDownloadManagerViewController: and
+    // presentOpenInForDownloadManagerViewController will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping calls in @autorelease will ensure that
+    // coordinator_ is deallocated.
     [view_controller.delegate
         downloadManagerViewControllerDidStartDownload:view_controller];
 
@@ -499,7 +516,10 @@
 
   // Start and the download.
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -540,7 +560,10 @@
 
   // Start and the download.
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -591,7 +614,10 @@
       &web_state_, OverlayModality::kWebContentArea);
   ASSERT_EQ(0U, queue->size());
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidClose: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidClose:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidClose:viewController];
   }
@@ -614,8 +640,9 @@
   // Stop to avoid holding a dangling pointer to destroyed task.
   queue->CancelAllRequests();
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -stop will retain and autorelease coordinator_. task_environment_
+    // has to outlive the coordinator, so wrapping -stop call in @autorelease
+    // will ensure that coordinator_ is deallocated.
     [coordinator_ stop];
   }
 
@@ -661,8 +688,9 @@
 
   queue->CancelAllRequests();
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -stop will retain and autorelease coordinator_. task_environment_
+    // has to outlive the coordinator, so wrapping -stop call in @autorelease
+    // will ensure that coordinator_ is deallocated.
     [coordinator_ stop];
   }
 
@@ -704,8 +732,9 @@
 
   queue->CancelAllRequests();
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -stop will retain and autorelease coordinator_. task_environment_
+    // has to outlive the coordinator, so wrapping -stop call in @autorelease
+    // will ensure that coordinator_ is deallocated.
     [coordinator_ stop];
   }
 
@@ -725,7 +754,10 @@
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -764,7 +796,10 @@
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
   ASSERT_EQ(0, user_action_tester_.GetActionCount("IOSDownloadStartDownload"));
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -773,7 +808,10 @@
   ASSERT_EQ(1, user_action_tester_.GetActionCount("IOSDownloadStartDownload"));
 
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -811,7 +849,10 @@
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -851,7 +892,10 @@
 
   // Start the download.
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // Calling -downloadManagerViewControllerDidStartDownload: will retain and
+    // autorelease coordinator_. task_environment_ has to outlive the
+    // coordinator, so wrapping -downloadManagerViewControllerDidStartDownload:
+    // call in @autorelease will ensure that coordinator_ is deallocated.
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
@@ -884,8 +928,9 @@
   EXPECT_NSEQ(viewController, coordinator_.viewController);
 
   @autoreleasepool {
-    // task_environment_ has to outlive the coordinator. Dismissing coordinator
-    // retains are autoreleases it.
+    // Calling -stop will retain and autorelease coordinator_. task_environment_
+    // has to outlive the coordinator, so wrapping -stop call in @autorelease
+    // will ensure that coordinator_ is deallocated.
     [coordinator_ stop];
   }
   EXPECT_FALSE(coordinator_.viewController);
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
index 9510a1b..acb4b78 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -75,6 +75,7 @@
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "net/base/mac/url_conversions.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
 
@@ -972,7 +973,9 @@
     }
     case PasswordCheckStateUnSafe: {
       _passwordProblemsItem.detailText =
-          l10n_util::GetNSString(IDS_IOS_CHECK_PASSWORDS_UNSAFE_STATE);
+          base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
+              IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT,
+              _passwordCheck->GetCompromisedCredentials().size()));
       UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
           imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
       _passwordProblemsItem.trailingImage = unSafeIconImage;
@@ -983,10 +986,12 @@
       break;
     }
     case PasswordCheckStateSafe: {
+      DCHECK(_passwordCheck->GetCompromisedCredentials().empty());
       UIImage* safeIconImage = [[UIImage imageNamed:@"settings_safe_state"]
           imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
       _passwordProblemsItem.detailText =
-          l10n_util::GetNSString(IDS_IOS_CHECK_PASSWORDS_SAFE_STATE);
+          base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
+              IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, 0));
       _passwordProblemsItem.trailingImage = safeIconImage;
       _passwordProblemsItem.trailingImageTintColor =
           [UIColor colorNamed:kGreenColor];
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
index 3b67139..02a92c4 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -6,6 +6,8 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #import "base/test/ios/wait_util.h"
@@ -38,11 +40,14 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+using password_manager::CompromiseType;
 using password_manager::TestPasswordStore;
 using password_manager::MockBulkLeakCheckService;
 using ::testing::Return;
@@ -226,6 +231,23 @@
     AddPasswordForm(std::move(form));
   }
 
+  password_manager::CompromisedCredentials MakeCompromised(
+      base::StringPiece signon_realm,
+      base::StringPiece username) {
+    return {
+        std::string(signon_realm),
+        base::ASCIIToUTF16(username),
+        base::Time::Now(),
+        CompromiseType::kLeaked,
+    };
+  }
+
+  void AddCompromisedCredential1() {
+    GetTestStore().AddCompromisedCredentials(
+        MakeCompromised("http://www.example.com/", "test@egmail.com"));
+    RunUntilIdle();
+  }
+
   // Deletes the item at (row, section) and wait util condition returns true or
   // timeout.
   bool deleteItemAndWait(int section, int row, ConditionBlock condition) {
@@ -237,6 +259,19 @@
         base::test::ios::kWaitForUIElementTimeout, condition);
   }
 
+  void CheckDetailItemTextWithPluralIds(int expected_text_id,
+                                        int expected_detail_text_id,
+                                        int count,
+                                        int section,
+                                        int item) {
+    SettingsCheckItem* cell =
+        static_cast<SettingsCheckItem*>(GetTableViewItem(section, item));
+    EXPECT_NSEQ(l10n_util::GetNSString(expected_text_id), [cell text]);
+    EXPECT_NSEQ(base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
+                    IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, count)),
+                [cell detailText]);
+  }
+
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
   web::WebTaskEnvironment task_environment_;
@@ -572,6 +607,45 @@
   EXPECT_FALSE(checkPassword.trailingImage);
 }
 
+// Test verifies safe state of password check cell.
+TEST_P(PasswordsTableViewControllerTest, PasswordCheckStateSafe) {
+  if (!GetParam().password_check_enabled)
+    return;
+
+  ChangePasswordCheckState(PasswordCheckStateSafe);
+
+  CheckTextCellTextWithId(IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON,
+                          GetSectionIndex(PasswordCheck), 1);
+  CheckDetailItemTextWithPluralIds(IDS_IOS_CHECK_PASSWORDS,
+                                   IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, 0,
+                                   GetSectionIndex(PasswordCheck), 0);
+  SettingsCheckItem* checkPassword =
+      GetTableViewItem(GetSectionIndex(PasswordCheck), 0);
+  EXPECT_TRUE(checkPassword.enabled);
+  EXPECT_TRUE(checkPassword.indicatorHidden);
+  EXPECT_TRUE(checkPassword.trailingImage);
+}
+
+// Test verifies unsafe state of password check cell.
+TEST_P(PasswordsTableViewControllerTest, PasswordCheckStateUnSafe) {
+  if (!GetParam().password_check_enabled)
+    return;
+  AddSavedForm1();
+  AddCompromisedCredential1();
+  ChangePasswordCheckState(PasswordCheckStateUnSafe);
+
+  CheckTextCellTextWithId(IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON,
+                          GetSectionIndex(PasswordCheck), 1);
+  CheckDetailItemTextWithPluralIds(IDS_IOS_CHECK_PASSWORDS,
+                                   IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, 1,
+                                   GetSectionIndex(PasswordCheck), 0);
+  SettingsCheckItem* checkPassword =
+      GetTableViewItem(GetSectionIndex(PasswordCheck), 0);
+  EXPECT_TRUE(checkPassword.enabled);
+  EXPECT_TRUE(checkPassword.indicatorHidden);
+  EXPECT_TRUE(checkPassword.trailingImage);
+}
+
 // Test verifies running state of password check cell.
 TEST_P(PasswordsTableViewControllerTest, PasswordCheckStateRunning) {
   if (!GetParam().password_check_enabled)
diff --git a/ios/chrome/browser/ui/settings/search_engine_settings_egtest.mm b/ios/chrome/browser/ui/settings/search_engine_settings_egtest.mm
index 74dc9dfdd..5cb9fe2 100644
--- a/ios/chrome/browser/ui/settings/search_engine_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/search_engine_settings_egtest.mm
@@ -165,7 +165,8 @@
 }
 
 // Deletes a custom search engine by swiping and tapping on the "Delete" button.
-- (void)testDeleteCustomSearchEngineSwipeAndTap {
+// TODO(crbug.com/1106735): reenable this test.
+- (void)DISABLED_testDeleteCustomSearchEngineSwipeAndTap {
   if (@available(iOS 13, *)) {
   } else {
     EARL_GREY_TEST_SKIPPED(
@@ -191,7 +192,8 @@
 }
 
 // Deletes a custom engine by swiping it.
-- (void)testDeleteCustomSearchEngineSwipe {
+// TODO(crbug.com/1106735): reenable this test.
+- (void)DISABLED_testDeleteCustomSearchEngineSwipe {
   [self enterSettingsWithCustomSearchEngine];
 
   id<GREYMatcher> customSearchEngineCell =
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
index 8b6a855..81d0347 100644
--- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -143,7 +143,6 @@
 
 - (void)viewWillDisappear:(BOOL)animated {
   [super viewWillDisappear:animated];
-  [self.navigationController setToolbarHidden:YES animated:YES];
 }
 
 - (void)setEditing:(BOOL)editing animated:(BOOL)animated {
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index 16af99c..e131c5b 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -15,19 +15,12 @@
   # $ cd src/ios/third_party/material_components_ios
   # $ find src -path 'src/components/*/src/*.h' -a \! -path '*Test*'|\
   #   sed -e 's:\(.*\):  "\1",:'|sort -u
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.h",
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.h",
-  "src/components/ActionSheet/src/ActionSheetThemer/MaterialActionSheet+ActionSheetThemer.h",
-  "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.h",
-  "src/components/ActionSheet/src/ColorThemer/MaterialActionSheet+ColorThemer.h",
   "src/components/ActionSheet/src/MDCActionSheetAction.h",
   "src/components/ActionSheet/src/MDCActionSheetController.h",
   "src/components/ActionSheet/src/MDCActionSheetControllerDelegate.h",
   "src/components/ActionSheet/src/MaterialActionSheet.h",
   "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.h",
   "src/components/ActionSheet/src/Theming/MaterialActionSheet+Theming.h",
-  "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.h",
-  "src/components/ActionSheet/src/TypographyThemer/MaterialActionSheet+TypographyThemer.h",
   "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.h",
   "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.h",
   "src/components/ActionSheet/src/private/MaterialActionSheetStrings.h",
@@ -565,10 +558,7 @@
   # $ find src -path 'src/components/*/src/*.h' -a \! -path '*Test*'|\
   #   sed -e 's:\(.*\)/[^/]*:  "\1",:'|sort -u
   "src/components/ActionSheet/src",
-  "src/components/ActionSheet/src/ActionSheetThemer",
-  "src/components/ActionSheet/src/ColorThemer",
   "src/components/ActionSheet/src/Theming",
-  "src/components/ActionSheet/src/TypographyThemer",
   "src/components/ActionSheet/src/private",
   "src/components/ActivityIndicator/src",
   "src/components/ActivityIndicator/src/private",
@@ -733,14 +723,6 @@
   # $ cd src/ios/third_party/material_components_ios
   # $ find src -path 'src/components/*/src/*.[hm]' -a \! -path '*Test*'|\
   #   sed -e 's:\(.*\):  "\1",:'|sort -u
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.h",
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.m",
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.h",
-  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.m",
-  "src/components/ActionSheet/src/ActionSheetThemer/MaterialActionSheet+ActionSheetThemer.h",
-  "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.h",
-  "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m",
-  "src/components/ActionSheet/src/ColorThemer/MaterialActionSheet+ColorThemer.h",
   "src/components/ActionSheet/src/MDCActionSheetAction.h",
   "src/components/ActionSheet/src/MDCActionSheetController.h",
   "src/components/ActionSheet/src/MDCActionSheetController.m",
@@ -749,9 +731,6 @@
   "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.h",
   "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.m",
   "src/components/ActionSheet/src/Theming/MaterialActionSheet+Theming.h",
-  "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.h",
-  "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m",
-  "src/components/ActionSheet/src/TypographyThemer/MaterialActionSheet+TypographyThemer.h",
   "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.h",
   "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.m",
   "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.h",
diff --git a/ios/web/init/ios_global_state.mm b/ios/web/init/ios_global_state.mm
index ec1da30..66f36e41 100644
--- a/ios/web/init/ios_global_state.mm
+++ b/ios/web/init/ios_global_state.mm
@@ -7,8 +7,8 @@
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/initialization_util.h"
 #include "net/base/network_change_notifier.h"
@@ -44,7 +44,7 @@
   dispatch_once(&once_token, ^{
     // Create a SingleThreadTaskExecutor if one does not already exist for the
     // current thread.
-    if (!base::MessageLoopCurrent::Get()) {
+    if (!base::CurrentThread::Get()) {
       g_task_executor =
           new base::SingleThreadTaskExecutor(base::MessagePumpType::UI);
     }
diff --git a/ios/web/public/init/web_main_parts.h b/ios/web/public/init/web_main_parts.h
index 8f6c0df..af72fafe 100644
--- a/ios/web/public/init/web_main_parts.h
+++ b/ios/web/public/init/web_main_parts.h
@@ -26,7 +26,7 @@
 //    should be done immediately before the start of the main message loop
 //    should go in |PreMainMessageLoopStart()|.
 //  - RunMainMessageLoopParts:  things to be done before and after invoking the
-//    main message loop run method (e.g. MessageLoopCurrentForUI::Get()->Run()).
+//    main message loop run method (e.g. CurrentUIThread::Get()->Run()).
 //
 // How to add stuff (to existing parts):
 //  - Figure out when your new code should be executed. What must happen
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm
index 2da3caff..65b604f 100644
--- a/ios/web/public/test/web_test_with_web_state.mm
+++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -5,10 +5,10 @@
 #import "ios/web/public/test/web_test_with_web_state.h"
 
 #include "base/ios/ios_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/task/current_thread.h"
 #import "base/test/ios/wait_util.h"
 #include "ios/web/common/features.h"
 #import "ios/web/js_messaging/crw_js_injector.h"
@@ -193,7 +193,7 @@
   // Because tasks can add new tasks to either queue, the loop continues until
   // the first pass where no activity is seen from either queue.
   bool activitySeen = false;
-  base::MessageLoopCurrent messageLoop = base::MessageLoopCurrent::Get();
+  base::CurrentThread messageLoop = base::CurrentThread::Get();
   messageLoop->AddTaskObserver(this);
   do {
     activitySeen = false;
diff --git a/ios/web/webui/url_fetcher_block_adapter_unittest.mm b/ios/web/webui/url_fetcher_block_adapter_unittest.mm
index 22e43766..4400738 100644
--- a/ios/web/webui/url_fetcher_block_adapter_unittest.mm
+++ b/ios/web/webui/url_fetcher_block_adapter_unittest.mm
@@ -31,7 +31,7 @@
       : task_environment_(
             base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
 
-  // Required for base::MessageLoopCurrent::Get().
+  // Required for base::CurrentThread::Get().
   base::test::SingleThreadTaskEnvironment task_environment_;
 };
 
diff --git a/jingle/glue/thread_wrapper.cc b/jingle/glue/thread_wrapper.cc
index 590fe9a..6d00223 100644
--- a/jingle/glue/thread_wrapper.cc
+++ b/jingle/glue/thread_wrapper.cc
@@ -42,7 +42,7 @@
     std::unique_ptr<JingleThreadWrapper> wrapper =
         JingleThreadWrapper::WrapTaskRunner(
             base::ThreadTaskRunnerHandle::Get());
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(wrapper.release());
+    base::CurrentThread::Get()->AddDestructionObserver(wrapper.release());
   }
 
   DCHECK_EQ(rtc::Thread::Current(), current());
diff --git a/jingle/glue/thread_wrapper.h b/jingle/glue/thread_wrapper.h
index ab94b3d..fad9794 100644
--- a/jingle/glue/thread_wrapper.h
+++ b/jingle/glue/thread_wrapper.h
@@ -14,10 +14,10 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "third_party/webrtc/rtc_base/thread.h"
 
 namespace jingle_glue {
@@ -33,9 +33,8 @@
 // - Using JingleThreadWrapper() constructor. In this case the creating code
 //   must pass a valid task runner for the current thread and also delete the
 //   wrapper later.
-class JingleThreadWrapper
-    : public base::MessageLoopCurrent::DestructionObserver,
-      public rtc::Thread {
+class JingleThreadWrapper : public base::CurrentThread::DestructionObserver,
+                            public rtc::Thread {
  public:
   // Create JingleThreadWrapper for the current thread if it hasn't been created
   // yet. The thread wrapper is destroyed automatically when the current
@@ -60,7 +59,7 @@
   // need to call Send() for other threads.
   void set_send_allowed(bool allowed) { send_allowed_ = allowed; }
 
-  // MessageLoopCurrent::DestructionObserver implementation.
+  // CurrentThread::DestructionObserver implementation.
   void WillDestroyCurrentMessageLoop() override;
 
   // rtc::MessageQueue overrides.
diff --git a/media/audio/scoped_task_runner_observer.cc b/media/audio/scoped_task_runner_observer.cc
index 1c730366..b4b7f5ba 100644
--- a/media/audio/scoped_task_runner_observer.cc
+++ b/media/audio/scoped_task_runner_observer.cc
@@ -24,7 +24,7 @@
     base::WaitableEvent* done) {
   // Note: |done| may be NULL.
   if (task_runner_->BelongsToCurrentThread()) {
-    base::MessageLoopCurrent loop = base::MessageLoopCurrent::Get();
+    base::CurrentThread loop = base::CurrentThread::Get();
     if (enable) {
       loop->AddDestructionObserver(this);
     } else {
diff --git a/media/audio/scoped_task_runner_observer.h b/media/audio/scoped_task_runner_observer.h
index b0f0b31..7e551dc9 100644
--- a/media/audio/scoped_task_runner_observer.h
+++ b/media/audio/scoped_task_runner_observer.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -23,7 +23,7 @@
 // NOTE: The class that inherits from this class must implement the
 // WillDestroyCurrentMessageLoop virtual method from DestructionObserver.
 class ScopedTaskRunnerObserver
-    : public base::MessageLoopCurrent::DestructionObserver {
+    : public base::CurrentThread::DestructionObserver {
  public:
   explicit ScopedTaskRunnerObserver(
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
diff --git a/media/base/status.cc b/media/base/status.cc
index 003b657..1e30c22 100644
--- a/media/base/status.cc
+++ b/media/base/status.cc
@@ -14,7 +14,11 @@
 Status::Status(StatusCode code,
                base::StringPiece message,
                const base::Location& location) {
-  DCHECK(code != StatusCode::kOk);
+  // Note that |message| is dropped in this case.
+  if (code == StatusCode::kOk) {
+    DCHECK(message.empty());
+    return;
+  }
   data_ = std::make_unique<StatusInternal>(code, message.as_string());
   AddFrame(location);
 }
@@ -70,7 +74,7 @@
 }
 
 Status OkStatus() {
-  return Status();
+  return Status(StatusCode::kOk);
 }
 
 }  // namespace media
diff --git a/media/base/status.h b/media/base/status.h
index 0e81b54f..96e26e6 100644
--- a/media/base/status.h
+++ b/media/base/status.h
@@ -40,13 +40,16 @@
 // successful returns.
 class MEDIA_EXPORT Status {
  public:
-  // Default constructor can be used for OkStatus();
+  // This will create a kOk status, but please don't use it.  Use either
+  // Status(StatusCode::kOk) or OkStatus().  This is here because the mojo
+  // bindings assume that it is.
+  // TODO(crbug.com/1106492): Remove this.
   Status();
 
   // Constructor to create a new Status from a numeric code & message.
   // These are immutable; if you'd like to change them, then you likely should
-  // create a new Status. {} or OkStatus() should be used to create a
-  // success status.
+  // create a new Status. Either {StatusCode::kOk} or OkStatus() may be used to
+  // create a success status.
   // NOTE: This should never be given a location parameter when called - It is
   // defaulted in order to grab the caller location.
   Status(StatusCode code,
@@ -147,6 +150,8 @@
 // if they are added.
 MEDIA_EXPORT Status OkStatus();
 
+// TODO(liberato): Add more helper functions for common error returns.
+
 // Helper class to allow returning a |T| or a Status.  Typical usage:
 //
 // ErrorOr<std::unique_ptr<MyObject>> FactoryFn() {
@@ -206,11 +211,13 @@
 
   // Return a ref to the value.  It's up to the caller to verify that we have a
   // value before calling this.
-  T& value() { return *value_; }
+  T& value() { return std::get<0>(*value_); }
 
  private:
   base::Optional<Status> error_;
-  base::Optional<T> value_;
+  // We wrap |T| in a container so that windows COM wrappers work.  They
+  // override operator& and similar, and won't compile in a base::Optional.
+  base::Optional<std::tuple<T>> value_;
 };
 
 }  // namespace media
diff --git a/media/base/status_codes.h b/media/base/status_codes.h
index 84fd4d50..e1c6369 100644
--- a/media/base/status_codes.h
+++ b/media/base/status_codes.h
@@ -36,10 +36,14 @@
   kEncryptedContentUnsupported = 0x00000106,
   kClearContentUnsupported = 0x00000107,
   kDecoderMissingCdmForEncryptedContent = 0x00000108,
-  kDecoderFailedInitialization = 0x00000109,
+  kDecoderInitializationFailed = 0x00000109,  // Prefer this one.
+  kDecoderFailedInitialization = kDecoderInitializationFailed,  // Do not use.
   kDecoderCantChangeCodec = 0x0000010A,
-  kDecoderFailedCreation = 0x0000010B,
+  kDecoderCreationFailed = 0x0000010B,              // Prefer this one.
+  kDecoderFailedCreation = kDecoderCreationFailed,  // Do not use.
   kInitializationUnspecifiedFailure = 0x0000010C,
+  kDecoderVideoFrameConstructionFailed = 0x0000010D,
+  kMakeContextCurrentFailed = 0x0000010E,
 
   // Windows Errors: 0x02
   kWindowsWrappedHresult = 0x00000201,
@@ -47,16 +51,26 @@
   kWindowsD3D11Error = 0x00000203,
 
   // D3D11VideoDecoder Errors: 0x03
-  kCantMakeContextCurrent = 0x00000301,
-  kCantPostTexture = 0x00000302,
-  kCantPostAcquireStream = 0x00000303,
-  kCantCreateEglStream = 0x00000304,
-  kCantCreateEglStreamConsumer = 0x00000305,
-  kCantCreateEglStreamProducer = 0x00000306,
-  kCannotCreateTextureSelector = 0x00000307,
-  kCannotQueryID3D11Multithread = 0x00000308,
-  kCannotGetDecoderConfigCount = 0x00000309,
-  kCannotGetDecoderConfig = 0x0000030A,
+  kPostTextureFailed = 0x00000301,
+  kPostAcquireStreamFailed = 0x00000302,
+  kCreateEglStreamFailed = 0x00000303,
+  kCreateEglStreamConsumerFailed = 0x00000304,
+  kCreateEglStreamProducerFailed = 0x00000305,
+  kCreateTextureSelectorFailed = 0x00000306,
+  kQueryID3D11MultithreadFailed = 0x00000307,
+  kGetDecoderConfigCountFailed = 0x00000308,
+  kGetDecoderConfigFailed = 0x00000309,
+  kProcessTextureFailed = 0x0000030A,
+  kUnsupportedTextureFormatForBind = 0x0000030B,
+  kCreateDecoderOutputViewFailed = 0x0000030C,
+  kAllocateTextureForCopyingWrapperFailed = 0x0000030D,
+  kCreateDecoderOutputTextureFailed = 0x0000030E,
+  kCreateVideoProcessorInputViewFailed = 0x0000030F,
+  kVideoProcessorBltFailed = 0x00000310,
+  kCreateVideoProcessorOutputViewFailed = 0x00000311,
+  kCreateVideoProcessorEnumeratorFailed = 0x00000312,
+  kCreateVideoProcessorFailed = 0x00000313,
+  kQueryVideoContextFailed = 0x00000314,
 
   // MojoDecoder Errors: 0x04
   kMojoDecoderNoWrappedDecoder = 0x00000401,
diff --git a/media/base/user_input_monitor_linux.cc b/media/base/user_input_monitor_linux.cc
index 2d31613..7cd7cd51 100644
--- a/media/base/user_input_monitor_linux.cc
+++ b/media/base/user_input_monitor_linux.cc
@@ -16,9 +16,9 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "media/base/keyboard_event_counter.h"
 #include "third_party/skia/include/core/SkPoint.h"
 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
@@ -32,7 +32,7 @@
 // UserInputMonitorLinux since it needs to be deleted on the IO thread.
 class UserInputMonitorLinuxCore
     : public base::SupportsWeakPtr<UserInputMonitorLinuxCore>,
-      public base::MessageLoopCurrent::DestructionObserver {
+      public base::CurrentThread::DestructionObserver {
  public:
   explicit UserInputMonitorLinuxCore(
       const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
@@ -192,7 +192,7 @@
 
   // Start observing message loop destruction if we start monitoring the first
   // event.
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  base::CurrentThread::Get()->AddDestructionObserver(this);
 
   // Fetch pending events if any.
   OnXEvent();
@@ -235,7 +235,7 @@
   key_press_count_mapping_.reset();
 
   // Stop observing message loop destruction if no event is being monitored.
-  base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+  base::CurrentThread::Get()->RemoveDestructionObserver(this);
 }
 
 void UserInputMonitorLinuxCore::OnXEvent() {
diff --git a/media/base/user_input_monitor_win.cc b/media/base/user_input_monitor_win.cc
index d42f98a2..48abe73 100644
--- a/media/base/user_input_monitor_win.cc
+++ b/media/base/user_input_monitor_win.cc
@@ -12,10 +12,10 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/win/message_window.h"
 #include "media/base/keyboard_event_counter.h"
 #include "third_party/skia/include/core/SkPoint.h"
@@ -41,7 +41,7 @@
 // UserInputMonitorWin since it needs to be deleted on the UI thread.
 class UserInputMonitorWinCore
     : public base::SupportsWeakPtr<UserInputMonitorWinCore>,
-      public base::MessageLoopCurrent::DestructionObserver {
+      public base::CurrentThread::DestructionObserver {
  public:
   enum EventBitMask {
     MOUSE_EVENT_MASK = 1,
@@ -146,7 +146,7 @@
   window_ = std::move(window);
   // Start observing message loop destruction if we start monitoring the first
   // event.
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  base::CurrentThread::Get()->AddDestructionObserver(this);
 }
 
 void UserInputMonitorWinCore::StartMonitorWithMapping(
@@ -175,7 +175,7 @@
   key_press_count_mapping_.reset();
 
   // Stop observing message loop destruction if no event is being monitored.
-  base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+  base::CurrentThread::Get()->RemoveDestructionObserver(this);
 }
 
 LRESULT UserInputMonitorWinCore::OnInput(HRAWINPUT input_handle) {
diff --git a/media/blink/video_decode_stats_reporter_unittest.cc b/media/blink/video_decode_stats_reporter_unittest.cc
index 402a60c..96a8f1e 100644
--- a/media/blink/video_decode_stats_reporter_unittest.cc
+++ b/media/blink/video_decode_stats_reporter_unittest.cc
@@ -7,9 +7,9 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -109,7 +109,7 @@
 
   void SetUp() override {
     // Do this first. Lots of pieces depend on the task runner.
-    auto message_loop = base::MessageLoopCurrent::Get();
+    auto message_loop = base::CurrentThread::Get();
     original_task_runner_ = base::ThreadTaskRunnerHandle::Get();
     task_runner_ = new base::TestMockTimeTaskRunner();
     message_loop.SetTaskRunner(task_runner_);
@@ -131,7 +131,7 @@
 
     // Run task runner to have Mojo cleanup interceptor_.
     task_runner_->RunUntilIdle();
-    base::MessageLoopCurrent::Get().SetTaskRunner(original_task_runner_);
+    base::CurrentThread::Get().SetTaskRunner(original_task_runner_);
   }
 
   PipelineStatistics MakeAdvancingDecodeStats() {
diff --git a/media/blink/watch_time_reporter_unittest.cc b/media/blink/watch_time_reporter_unittest.cc
index 7db8151..dbeab26 100644
--- a/media/blink/watch_time_reporter_unittest.cc
+++ b/media/blink/watch_time_reporter_unittest.cc
@@ -6,9 +6,9 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -288,7 +288,7 @@
         has_audio_(std::get<1>(GetParam())),
         fake_metrics_provider_(this) {
     // Do this first. Lots of pieces depend on the task runner.
-    auto message_loop = base::MessageLoopCurrent::Get();
+    auto message_loop = base::CurrentThread::Get();
     original_task_runner_ = base::ThreadTaskRunnerHandle::Get();
     task_runner_ = new base::TestMockTimeTaskRunner();
     message_loop.SetTaskRunner(task_runner_);
@@ -297,7 +297,7 @@
   ~WatchTimeReporterTest() override {
     CycleReportingTimer();
     task_runner_->RunUntilIdle();
-    base::MessageLoopCurrent::Get().SetTaskRunner(original_task_runner_);
+    base::CurrentThread::Get().SetTaskRunner(original_task_runner_);
   }
 
  protected:
diff --git a/media/fuchsia/camera/fake_fuchsia_camera.cc b/media/fuchsia/camera/fake_fuchsia_camera.cc
index cae3eca..9aa06b46 100644
--- a/media/fuchsia/camera/fake_fuchsia_camera.cc
+++ b/media/fuchsia/camera/fake_fuchsia_camera.cc
@@ -10,7 +10,7 @@
 #include "base/fuchsia/process_context.h"
 #include "base/memory/platform_shared_memory_region.h"
 #include "base/memory/writable_shared_memory_region.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
@@ -239,7 +239,7 @@
       ZX_OK);
 
   // Watch release fence to get notified when the frame is released.
-  base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+  base::CurrentIOThread::Get()->WatchZxHandle(
       buffer->release_fence.get(), /*persistent=*/false,
       ZX_EVENTPAIR_PEER_CLOSED, &buffer->release_fence_watch_controller, this);
 
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper.cc b/media/gpu/windows/d3d11_copying_texture_wrapper.cc
index 039062e..9157fe8 100644
--- a/media/gpu/windows/d3d11_copying_texture_wrapper.cc
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "gpu/command_buffer/service/mailbox_manager.h"
+#include "media/base/status_codes.h"
+#include "media/base/win/hresult_status_helper.h"
 #include "media/gpu/windows/d3d11_com_defs.h"
 #include "media/gpu/windows/display_helper.h"
 
@@ -27,14 +29,7 @@
 
 CopyingTexture2DWrapper::~CopyingTexture2DWrapper() = default;
 
-#define RETURN_ON_FAILURE(expr) \
-  do {                          \
-    if (!SUCCEEDED((expr))) {   \
-      return false;             \
-    }                           \
-  } while (0)
-
-bool CopyingTexture2DWrapper::ProcessTexture(
+Status CopyingTexture2DWrapper::ProcessTexture(
     ComD3D11Texture2D texture,
     size_t array_slice,
     const gfx::ColorSpace& input_color_space,
@@ -44,16 +39,24 @@
       D3D11_VPOV_DIMENSION_TEXTURE2D};
   output_view_desc.Texture2D.MipSlice = 0;
   ComD3D11VideoProcessorOutputView output_view;
-  RETURN_ON_FAILURE(video_processor_->CreateVideoProcessorOutputView(
-      output_texture_.Get(), &output_view_desc, &output_view));
+  HRESULT hr = video_processor_->CreateVideoProcessorOutputView(
+      output_texture_.Get(), &output_view_desc, &output_view);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kCreateVideoProcessorOutputViewFailed)
+        .AddCause(HresultToStatus(hr));
+  }
 
   D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0};
   input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
   input_view_desc.Texture2D.ArraySlice = array_slice;
   input_view_desc.Texture2D.MipSlice = 0;
   ComD3D11VideoProcessorInputView input_view;
-  RETURN_ON_FAILURE(video_processor_->CreateVideoProcessorInputView(
-      texture.Get(), &input_view_desc, &input_view));
+  hr = video_processor_->CreateVideoProcessorInputView(
+      texture.Get(), &input_view_desc, &input_view);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kCreateVideoProcessorInputViewFailed)
+        .AddCause(HresultToStatus(hr));
+  }
 
   D3D11_VIDEO_PROCESSOR_STREAM streams = {0};
   streams.Enable = TRUE;
@@ -73,20 +76,25 @@
     video_processor_->SetOutputColorSpace(copy_color_space);
   }
 
-  RETURN_ON_FAILURE(video_processor_->VideoProcessorBlt(output_view.Get(),
-                                                        0,  // output_frameno
-                                                        1,  // stream_count
-                                                        &streams));
+  hr = video_processor_->VideoProcessorBlt(output_view.Get(),
+                                           0,  // output_frameno
+                                           1,  // stream_count
+                                           &streams);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kVideoProcessorBltFailed)
+        .AddCause(HresultToStatus(hr));
+  }
 
   return output_texture_wrapper_->ProcessTexture(
       output_texture_, 0, copy_color_space, mailbox_dest, output_color_space);
 }
 
-bool CopyingTexture2DWrapper::Init(
+Status CopyingTexture2DWrapper::Init(
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
     GetCommandBufferHelperCB get_helper_cb) {
-  if (!video_processor_->Init(size_.width(), size_.height()))
-    return false;
+  auto result = video_processor_->Init(size_.width(), size_.height());
+  if (!result.is_ok())
+    return std::move(result).AddHere();
 
   return output_texture_wrapper_->Init(std::move(gpu_task_runner),
                                        std::move(get_helper_cb));
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper.h b/media/gpu/windows/d3d11_copying_texture_wrapper.h
index 0768f35..e62d1c7 100644
--- a/media/gpu/windows/d3d11_copying_texture_wrapper.h
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper.h
@@ -31,14 +31,14 @@
                           base::Optional<gfx::ColorSpace> output_color_space);
   ~CopyingTexture2DWrapper() override;
 
-  bool ProcessTexture(ComD3D11Texture2D texture,
-                      size_t array_slice,
-                      const gfx::ColorSpace& input_color_space,
-                      MailboxHolderArray* mailbox_dest,
-                      gfx::ColorSpace* output_color_space) override;
+  Status ProcessTexture(ComD3D11Texture2D texture,
+                        size_t array_slice,
+                        const gfx::ColorSpace& input_color_space,
+                        MailboxHolderArray* mailbox_dest,
+                        gfx::ColorSpace* output_color_space) override;
 
-  bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-            GetCommandBufferHelperCB get_helper_cb) override;
+  Status Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+              GetCommandBufferHelperCB get_helper_cb) override;
 
   void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) override;
   void SetDisplayHDRMetadata(
diff --git a/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc b/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc
index ed36baa..9677dcc6 100644
--- a/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc
+++ b/media/gpu/windows/d3d11_copying_texture_wrapper_unittest.cc
@@ -27,7 +27,7 @@
  public:
   MockVideoProcessorProxy() : VideoProcessorProxy(nullptr, nullptr) {}
 
-  bool Init(uint32_t width, uint32_t height) override {
+  Status Init(uint32_t width, uint32_t height) override {
     return MockInit(width, height);
   }
 
@@ -70,7 +70,7 @@
     return MockVideoProcessorBlt();
   }
 
-  MOCK_METHOD2(MockInit, bool(uint32_t, uint32_t));
+  MOCK_METHOD2(MockInit, Status(uint32_t, uint32_t));
   MOCK_METHOD0(MockCreateVideoProcessorOutputView, HRESULT());
   MOCK_METHOD0(MockCreateVideoProcessorInputView, HRESULT());
   MOCK_METHOD0(MockVideoProcessorBlt, HRESULT());
@@ -86,25 +86,25 @@
  public:
   MockTexture2DWrapper() {}
 
-  bool ProcessTexture(ComD3D11Texture2D texture,
-                      size_t array_slice,
-                      const gfx::ColorSpace& input_color_space,
-                      MailboxHolderArray* mailbox_dest,
-                      gfx::ColorSpace* output_color_space) override {
+  Status ProcessTexture(ComD3D11Texture2D texture,
+                        size_t array_slice,
+                        const gfx::ColorSpace& input_color_space,
+                        MailboxHolderArray* mailbox_dest,
+                        gfx::ColorSpace* output_color_space) override {
     // Pretend we created an arbitrary color space, so that we're sure that it
     // is returned from the copying wrapper.
     *output_color_space = gfx::ColorSpace::CreateHDR10();
     return MockProcessTexture();
   }
 
-  bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-            GetCommandBufferHelperCB get_helper_cb) override {
+  Status Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+              GetCommandBufferHelperCB get_helper_cb) override {
     gpu_task_runner_ = std::move(gpu_task_runner);
     return MockInit();
   }
 
-  MOCK_METHOD0(MockInit, bool());
-  MOCK_METHOD0(MockProcessTexture, bool());
+  MOCK_METHOD0(MockInit, Status());
+  MOCK_METHOD0(MockProcessTexture, Status());
   MOCK_METHOD1(SetStreamHDRMetadata, void(const HDRMetadata& stream_metadata));
   MOCK_METHOD1(SetDisplayHDRMetadata,
                void(const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata));
@@ -138,7 +138,9 @@
   std::unique_ptr<MockVideoProcessorProxy> ExpectProcessorProxy() {
     auto result = std::make_unique<MockVideoProcessorProxy>();
     ON_CALL(*result.get(), MockInit(_, _))
-        .WillByDefault(Return(GetProcessorProxyInit()));
+        .WillByDefault(Return(GetProcessorProxyInit()
+                                  ? StatusCode::kOk
+                                  : StatusCode::kCodeOnlyForTesting));
 
     ON_CALL(*result.get(), MockCreateVideoProcessorOutputView())
         .WillByDefault(Return(GetCreateVideoProcessorOutputView()));
@@ -156,10 +158,14 @@
     auto result = std::make_unique<MockTexture2DWrapper>();
 
     ON_CALL(*result.get(), MockInit())
-        .WillByDefault(Return(GetTextureWrapperInit()));
+        .WillByDefault(Return(GetTextureWrapperInit()
+                                  ? StatusCode::kOk
+                                  : StatusCode::kCodeOnlyForTesting));
 
     ON_CALL(*result.get(), MockProcessTexture())
-        .WillByDefault(Return(GetProcessTexture()));
+        .WillByDefault(Return(GetProcessTexture()
+                                  ? StatusCode::kOk
+                                  : StatusCode::kCodeOnlyForTesting));
 
     return result;
   }
@@ -216,13 +222,15 @@
   MailboxHolderArray mailboxes;
   gfx::ColorSpace input_color_space = gfx::ColorSpace::CreateSCRGBLinear();
   gfx::ColorSpace output_color_space;
-  EXPECT_EQ(wrapper->Init(gpu_task_runner_, CreateMockHelperCB()),
+  EXPECT_EQ(wrapper->Init(gpu_task_runner_, CreateMockHelperCB()).is_ok(),
             InitSucceeds());
   task_environment_.RunUntilIdle();
   if (GetProcessorProxyInit())
     EXPECT_EQ(texture_wrapper_raw->gpu_task_runner_, gpu_task_runner_);
-  EXPECT_EQ(wrapper->ProcessTexture(nullptr, 0, input_color_space, &mailboxes,
-                                    &output_color_space),
+  EXPECT_EQ(wrapper
+                ->ProcessTexture(nullptr, 0, input_color_space, &mailboxes,
+                                 &output_color_space)
+                .is_ok(),
             ProcessTextureSucceeds());
 
   if (ProcessTextureSucceeds()) {
diff --git a/media/gpu/windows/d3d11_decoder_configurator.cc b/media/gpu/windows/d3d11_decoder_configurator.cc
index 869106f..6f890f1 100644
--- a/media/gpu/windows/d3d11_decoder_configurator.cc
+++ b/media/gpu/windows/d3d11_decoder_configurator.cc
@@ -9,6 +9,8 @@
 #include "base/feature_list.h"
 #include "media/base/media_log.h"
 #include "media/base/media_switches.h"
+#include "media/base/status_codes.h"
+#include "media/base/win/hresult_status_helper.h"
 #include "media/gpu/windows/d3d11_copying_texture_wrapper.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gl/direct_composition_surface_win.h"
@@ -71,7 +73,7 @@
   return false;
 }
 
-ComD3D11Texture2D D3D11DecoderConfigurator::CreateOutputTexture(
+ErrorOr<ComD3D11Texture2D> D3D11DecoderConfigurator::CreateOutputTexture(
     ComD3D11Device device,
     gfx::Size size,
     uint32_t array_size) {
@@ -79,12 +81,15 @@
   output_texture_desc_.Height = size.height();
   output_texture_desc_.ArraySize = array_size;
 
-  ComD3D11Texture2D result;
-  if (!SUCCEEDED(
-          device->CreateTexture2D(&output_texture_desc_, nullptr, &result)))
-    return nullptr;
+  ComD3D11Texture2D texture;
+  HRESULT hr =
+      device->CreateTexture2D(&output_texture_desc_, nullptr, &texture);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kCreateDecoderOutputTextureFailed)
+        .AddCause(HresultToStatus(hr));
+  }
 
-  return result;
+  return texture;
 }
 
 // private
diff --git a/media/gpu/windows/d3d11_decoder_configurator.h b/media/gpu/windows/d3d11_decoder_configurator.h
index 3d6cd49..716f0e3 100644
--- a/media/gpu/windows/d3d11_decoder_configurator.h
+++ b/media/gpu/windows/d3d11_decoder_configurator.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include "media/base/status.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/gpu/windows/d3d11_picture_buffer.h"
 #include "media/gpu/windows/d3d11_video_processor_proxy.h"
@@ -40,9 +41,9 @@
   bool SupportsDevice(ComD3D11VideoDevice video_device);
 
   // Create the decoder's output texture.
-  ComD3D11Texture2D CreateOutputTexture(ComD3D11Device device,
-                                        gfx::Size size,
-                                        uint32_t array_size);
+  ErrorOr<ComD3D11Texture2D> CreateOutputTexture(ComD3D11Device device,
+                                                 gfx::Size size,
+                                                 uint32_t array_size);
 
   const D3D11_VIDEO_DECODER_DESC* DecoderDescriptor() const {
     return &decoder_desc_;
diff --git a/media/gpu/windows/d3d11_picture_buffer.cc b/media/gpu/windows/d3d11_picture_buffer.cc
index 60d1720e..ee56553 100644
--- a/media/gpu/windows/d3d11_picture_buffer.cc
+++ b/media/gpu/windows/d3d11_picture_buffer.cc
@@ -14,6 +14,8 @@
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "media/base/media_log.h"
+#include "media/base/status_codes.h"
+#include "media/base/win/hresult_status_helper.h"
 #include "media/base/win/mf_helpers.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
@@ -39,7 +41,7 @@
 D3D11PictureBuffer::~D3D11PictureBuffer() {
 }
 
-bool D3D11PictureBuffer::Init(
+Status D3D11PictureBuffer::Init(
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
     GetCommandBufferHelperCB get_helper_cb,
     ComD3D11VideoDevice video_device,
@@ -50,10 +52,11 @@
   view_desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
   view_desc.Texture2D.ArraySlice = array_slice_;
 
-  if (!texture_wrapper_->Init(std::move(gpu_task_runner),
-                              std::move(get_helper_cb))) {
+  Status result = texture_wrapper_->Init(std::move(gpu_task_runner),
+                                         std::move(get_helper_cb));
+  if (!result.is_ok()) {
     MEDIA_LOG(ERROR, media_log) << "Failed to Initialize the wrapper";
-    return false;
+    return result;
   }
 
   HRESULT hr = video_device->CreateVideoDecoderOutputView(
@@ -61,13 +64,14 @@
 
   if (!SUCCEEDED(hr)) {
     MEDIA_LOG(ERROR, media_log) << "Failed to CreateVideoDecoderOutputView";
-    return false;
+    return Status(StatusCode::kCreateDecoderOutputViewFailed)
+        .AddCause(HresultToStatus(hr));
   }
 
-  return true;
+  return OkStatus();
 }
 
-bool D3D11PictureBuffer::ProcessTexture(
+Status D3D11PictureBuffer::ProcessTexture(
     const gfx::ColorSpace& input_color_space,
     MailboxHolderArray* mailbox_dest,
     gfx::ColorSpace* output_color_space) {
diff --git a/media/gpu/windows/d3d11_picture_buffer.h b/media/gpu/windows/d3d11_picture_buffer.h
index 08e2c30..70d48fc7 100644
--- a/media/gpu/windows/d3d11_picture_buffer.h
+++ b/media/gpu/windows/d3d11_picture_buffer.h
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/ipc/service/command_buffer_stub.h"
 #include "media/base/media_log.h"
+#include "media/base/status.h"
 #include "media/base/video_frame.h"
 #include "media/gpu/command_buffer_helper.h"
 #include "media/gpu/media_gpu_export.h"
@@ -60,19 +61,19 @@
       gfx::Size size,
       size_t picture_index);
 
-  bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-            GetCommandBufferHelperCB get_helper_cb,
-            ComD3D11VideoDevice video_device,
-            const GUID& decoder_guid,
-            std::unique_ptr<MediaLog> media_log);
+  Status Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+              GetCommandBufferHelperCB get_helper_cb,
+              ComD3D11VideoDevice video_device,
+              const GUID& decoder_guid,
+              std::unique_ptr<MediaLog> media_log);
 
   // Set the contents of a mailbox holder array, return true if successful.
   // |input_color_space| is the color space of our input texture, and
   // |output_color_space| will be set, on success, to the color space that the
   // processed texture has.
-  bool ProcessTexture(const gfx::ColorSpace& input_color_space,
-                      MailboxHolderArray* mailbox_dest,
-                      gfx::ColorSpace* output_color_space);
+  Status ProcessTexture(const gfx::ColorSpace& input_color_space,
+                        MailboxHolderArray* mailbox_dest,
+                        gfx::ColorSpace* output_color_space);
   ComD3D11Texture2D Texture() const;
 
   const gfx::Size& size() const { return size_; }
diff --git a/media/gpu/windows/d3d11_texture_wrapper.cc b/media/gpu/windows/d3d11_texture_wrapper.cc
index b7a44cd7..4be405b 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -62,7 +62,7 @@
 
 DefaultTexture2DWrapper::~DefaultTexture2DWrapper() = default;
 
-bool DefaultTexture2DWrapper::ProcessTexture(
+Status DefaultTexture2DWrapper::ProcessTexture(
     ComD3D11Texture2D texture,
     size_t array_slice,
     const gfx::ColorSpace& input_color_space,
@@ -72,7 +72,8 @@
   // from some previous operation.
   // TODO(liberato): Return the error.
   if (received_error_)
-    return false;
+    return Status(StatusCode::kProcessTextureFailed)
+        .AddCause(std::move(*received_error_));
 
   // Temporary check to track down https://crbug.com/1077645
   CHECK(texture);
@@ -90,10 +91,10 @@
   // We're just binding, so the output and output color spaces are the same.
   *output_color_space = input_color_space;
 
-  return true;
+  return OkStatus();
 }
 
-bool DefaultTexture2DWrapper::Init(
+Status DefaultTexture2DWrapper::Init(
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
     GetCommandBufferHelperCB get_helper_cb) {
   gpu_resources_ = base::SequenceBound<GpuResources>(
@@ -113,7 +114,8 @@
       textures_per_picture = 1;
       break;
     default:
-      return false;
+      return Status(StatusCode::kUnsupportedTextureFormatForBind)
+          .WithData("dxgi_format", dxgi_format_);
   }
 
   // Generate mailboxes and holders.
@@ -134,7 +136,7 @@
   gpu_resources_.Post(FROM_HERE, &GpuResources::Init, std::move(get_helper_cb),
                       std::move(mailboxes), GL_TEXTURE_EXTERNAL_OES, size_,
                       textures_per_picture);
-  return true;
+  return OkStatus();
 }
 
 void DefaultTexture2DWrapper::OnError(Status status) {
@@ -167,7 +169,7 @@
   helper_ = get_helper_cb.Run();
 
   if (!helper_ || !helper_->MakeContextCurrent()) {
-    NotifyError(StatusCode::kCantMakeContextCurrent);
+    NotifyError(StatusCode::kMakeContextCurrentFailed);
     return;
   }
 
@@ -193,7 +195,7 @@
   };
   EGLStreamKHR stream = eglCreateStreamKHR(egl_display, stream_attributes);
   if (!stream) {
-    NotifyError(StatusCode::kCantCreateEglStream);
+    NotifyError(StatusCode::kCreateEglStreamFailed);
     return;
   }
 
@@ -232,7 +234,7 @@
   EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
       egl_display, stream, consumer_attributes.data());
   if (!result) {
-    NotifyError(StatusCode::kCantCreateEglStreamConsumer);
+    NotifyError(StatusCode::kCreateEglStreamConsumerFailed);
     return;
   }
 
@@ -243,7 +245,7 @@
   result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream,
                                                   producer_attributes);
   if (!result) {
-    NotifyError(StatusCode::kCantCreateEglStreamProducer);
+    NotifyError(StatusCode::kCreateEglStreamProducerFailed);
     return;
   }
 
@@ -269,7 +271,7 @@
   gl_image_->SetTexture(texture, array_slice);
 
   if (!helper_ || !helper_->MakeContextCurrent()) {
-    NotifyError(StatusCode::kCantMakeContextCurrent);
+    NotifyError(StatusCode::kMakeContextCurrentFailed);
     return;
   }
 
@@ -284,12 +286,12 @@
   if (!eglStreamPostD3DTextureANGLE(egl_display, stream_,
                                     static_cast<void*>(texture.Get()),
                                     frame_attributes)) {
-    NotifyError(StatusCode::kCantPostTexture);
+    NotifyError(StatusCode::kPostTextureFailed);
     return;
   }
 
   if (!eglStreamConsumerAcquireKHR(egl_display, stream_)) {
-    NotifyError(StatusCode::kCantPostAcquireStream);
+    NotifyError(StatusCode::kPostAcquireStreamFailed);
     return;
   }
 }
diff --git a/media/gpu/windows/d3d11_texture_wrapper.h b/media/gpu/windows/d3d11_texture_wrapper.h
index 5d71e20..3878f4fd9 100644
--- a/media/gpu/windows/d3d11_texture_wrapper.h
+++ b/media/gpu/windows/d3d11_texture_wrapper.h
@@ -45,16 +45,17 @@
   virtual ~Texture2DWrapper();
 
   // Initialize the wrapper.
-  virtual bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-                    GetCommandBufferHelperCB get_helper_cb) = 0;
+  virtual Status Init(
+      scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+      GetCommandBufferHelperCB get_helper_cb) = 0;
 
   // Import |texture|, |array_slice| and return the mailbox(es) that can be
   // used to refer to it.
-  virtual bool ProcessTexture(ComD3D11Texture2D texture,
-                              size_t array_slice,
-                              const gfx::ColorSpace& input_color_space,
-                              MailboxHolderArray* mailbox_dest_out,
-                              gfx::ColorSpace* output_color_space) = 0;
+  virtual Status ProcessTexture(ComD3D11Texture2D texture,
+                                size_t array_slice,
+                                const gfx::ColorSpace& input_color_space,
+                                MailboxHolderArray* mailbox_dest_out,
+                                gfx::ColorSpace* output_color_space) = 0;
 
   virtual void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) = 0;
   virtual void SetDisplayHDRMetadata(
@@ -75,14 +76,14 @@
   DefaultTexture2DWrapper(const gfx::Size& size, DXGI_FORMAT dxgi_format);
   ~DefaultTexture2DWrapper() override;
 
-  bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
-            GetCommandBufferHelperCB get_helper_cb) override;
+  Status Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
+              GetCommandBufferHelperCB get_helper_cb) override;
 
-  bool ProcessTexture(ComD3D11Texture2D texture,
-                      size_t array_slice,
-                      const gfx::ColorSpace& input_color_space,
-                      MailboxHolderArray* mailbox_dest,
-                      gfx::ColorSpace* output_color_space) override;
+  Status ProcessTexture(ComD3D11Texture2D texture,
+                        size_t array_slice,
+                        const gfx::ColorSpace& input_color_space,
+                        MailboxHolderArray* mailbox_dest,
+                        gfx::ColorSpace* output_color_space) override;
 
   void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) override;
   void SetDisplayHDRMetadata(
diff --git a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
index 4b355a1..fe7b9179 100644
--- a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
@@ -90,8 +90,8 @@
   const DXGI_FORMAT dxgi_format = DXGI_FORMAT_NV12;
 
   auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, dxgi_format);
-  const bool init_result = wrapper->Init(task_runner_, get_helper_cb_);
-  EXPECT_TRUE(init_result);
+  const Status init_result = wrapper->Init(task_runner_, get_helper_cb_);
+  EXPECT_TRUE(init_result.is_ok());
 
   // TODO: verify that ProcessTexture processes both textures.
 }
@@ -101,8 +101,8 @@
   const DXGI_FORMAT dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;
 
   auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, dxgi_format);
-  const bool init_result = wrapper->Init(task_runner_, get_helper_cb_);
-  EXPECT_TRUE(init_result);
+  const Status init_result = wrapper->Init(task_runner_, get_helper_cb_);
+  EXPECT_TRUE(init_result.is_ok());
 }
 
 TEST_F(D3D11TextureWrapperUnittest, FP16InitSucceeds) {
@@ -110,8 +110,8 @@
   const DXGI_FORMAT dxgi_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
 
   auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, dxgi_format);
-  const bool init_result = wrapper->Init(task_runner_, get_helper_cb_);
-  EXPECT_TRUE(init_result);
+  const Status init_result = wrapper->Init(task_runner_, get_helper_cb_);
+  EXPECT_TRUE(init_result.is_ok());
 }
 
 TEST_F(D3D11TextureWrapperUnittest, P010InitSucceeds) {
@@ -119,8 +119,8 @@
   const DXGI_FORMAT dxgi_format = DXGI_FORMAT_P010;
 
   auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, dxgi_format);
-  const bool init_result = wrapper->Init(task_runner_, get_helper_cb_);
-  EXPECT_TRUE(init_result);
+  const Status init_result = wrapper->Init(task_runner_, get_helper_cb_);
+  EXPECT_TRUE(init_result.is_ok());
 }
 
 }  // namespace media
\ No newline at end of file
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index 087b5fab..cfd57878 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -217,13 +217,13 @@
                         : TextureSelector::HDRMode::kSDROnly,
       &format_checker, media_log_.get());
   if (!texture_selector_)
-    return StatusCode::kCannotCreateTextureSelector;
+    return StatusCode::kCreateTextureSelectorFailed;
 
   UINT config_count = 0;
   hr = video_device_->GetVideoDecoderConfigCount(
       decoder_configurator_->DecoderDescriptor(), &config_count);
   if (FAILED(hr) || config_count == 0) {
-    return Status(StatusCode::kCannotGetDecoderConfigCount)
+    return Status(StatusCode::kGetDecoderConfigCountFailed)
         .AddCause(HresultToStatus(hr));
   }
 
@@ -234,7 +234,7 @@
     hr = video_device_->GetVideoDecoderConfig(
         decoder_configurator_->DecoderDescriptor(), i, &dec_config);
     if (FAILED(hr)) {
-      return Status(StatusCode::kCannotGetDecoderConfig)
+      return Status(StatusCode::kGetDecoderConfigFailed)
           .AddCause(HresultToStatus(hr));
     }
 
@@ -278,7 +278,7 @@
   hr = video_device_->CreateVideoDecoder(
       decoder_configurator_->DecoderDescriptor(), &dec_config, &video_decoder);
   if (!video_decoder.Get() || FAILED(hr)) {
-    return Status(StatusCode::kDecoderFailedCreation)
+    return Status(StatusCode::kDecoderCreationFailed)
         .AddCause(HresultToStatus(hr));
   }
 
@@ -369,7 +369,7 @@
     ComD3D11Multithread multi_threaded;
     hr = device_->QueryInterface(IID_PPV_ARGS(&multi_threaded));
     if (!SUCCEEDED(hr)) {
-      NotifyError(Status(StatusCode::kCannotQueryID3D11Multithread)
+      NotifyError(Status(StatusCode::kQueryID3D11MultithreadFailed)
                       .AddCause(HresultToStatus(hr)));
       return;
     }
@@ -705,22 +705,25 @@
   for (size_t i = 0; i < D3D11DecoderConfigurator::BUFFER_COUNT; i++) {
     // Create an input texture / texture array if we haven't already.
     if (!in_texture) {
-      in_texture = decoder_configurator_->CreateOutputTexture(
+      auto result = decoder_configurator_->CreateOutputTexture(
           device_, size,
           use_single_video_decoder_texture_
               ? 1
               : D3D11DecoderConfigurator::BUFFER_COUNT);
+      if (result.has_value()) {
+        in_texture = std::move(result.value());
+      } else {
+        NotifyError(std::move(result.error()).AddHere());
+        return;
+      }
     }
 
-    if (!in_texture) {
-      NotifyError("Failed to create a Texture2D for PictureBuffers");
-      return;
-    }
+    DCHECK(!!in_texture);
 
     auto tex_wrapper = texture_selector_->CreateTextureWrapper(
         device_, video_device_, device_context_, size);
     if (!tex_wrapper) {
-      NotifyError("Unable to allocate a texture for a CopyingTexture2DWrapper");
+      NotifyError(StatusCode::kAllocateTextureForCopyingWrapperFailed);
       return;
     }
 
@@ -728,10 +731,11 @@
     picture_buffers_.push_back(
         new D3D11PictureBuffer(decoder_task_runner_, in_texture, array_slice,
                                std::move(tex_wrapper), size, i /* level */));
-    if (!picture_buffers_[i]->Init(
-            gpu_task_runner_, get_helper_cb_, video_device_,
-            decoder_configurator_->DecoderGuid(), media_log_->Clone())) {
-      NotifyError("Unable to allocate PictureBuffer");
+    Status result = picture_buffers_[i]->Init(
+        gpu_task_runner_, get_helper_cb_, video_device_,
+        decoder_configurator_->DecoderGuid(), media_log_->Clone());
+    if (!result.is_ok()) {
+      NotifyError(std::move(result).AddHere());
       return;
     }
 
@@ -790,10 +794,11 @@
 
   MailboxHolderArray mailbox_holders;
   gfx::ColorSpace output_color_space;
-  if (!picture_buffer->ProcessTexture(
-          picture->get_colorspace().ToGfxColorSpace(), &mailbox_holders,
-          &output_color_space)) {
-    NotifyError("Unable to process texture");
+  Status result = picture_buffer->ProcessTexture(
+      picture->get_colorspace().ToGfxColorSpace(), &mailbox_holders,
+      &output_color_space);
+  if (!result.is_ok()) {
+    NotifyError(std::move(result).AddHere());
     return false;
   }
 
@@ -805,7 +810,7 @@
   if (!frame) {
     // This can happen if, somehow, we get an unsupported combination of
     // pixel format, etc.
-    NotifyError("Failed to construct video frame");
+    NotifyError(StatusCode::kDecoderVideoFrameConstructionFailed);
     return false;
   }
 
diff --git a/media/gpu/windows/d3d11_video_processor_proxy.cc b/media/gpu/windows/d3d11_video_processor_proxy.cc
index 2799986..31e0946 100644
--- a/media/gpu/windows/d3d11_video_processor_proxy.cc
+++ b/media/gpu/windows/d3d11_video_processor_proxy.cc
@@ -4,6 +4,8 @@
 
 #include "media/gpu/windows/d3d11_video_processor_proxy.h"
 
+#include "media/base/status_codes.h"
+#include "media/gpu/windows/hresult_status_debug_device.h"
 #include "ui/gfx/color_space_win.h"
 
 namespace media {
@@ -15,7 +17,7 @@
     ComD3D11DeviceContext d3d11_device_context)
     : video_device_(video_device), device_context_(d3d11_device_context) {}
 
-bool VideoProcessorProxy::Init(uint32_t width, uint32_t height) {
+Status VideoProcessorProxy::Init(uint32_t width, uint32_t height) {
   processor_enumerator_.Reset();
   video_processor_.Reset();
 
@@ -31,18 +33,31 @@
   desc.OutputHeight = height;
   desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
 
-  if (!SUCCEEDED(video_device_->CreateVideoProcessorEnumerator(
-          &desc, &processor_enumerator_)))
-    return false;
+  // Get the device in case we need it for error generation.
+  ComD3D11Device device;
+  device_context_->GetDevice(&device);
 
-  if (!SUCCEEDED(video_device_->CreateVideoProcessor(
-          processor_enumerator_.Get(), 0, &video_processor_)))
-    return false;
+  HRESULT hr = video_device_->CreateVideoProcessorEnumerator(
+      &desc, &processor_enumerator_);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kCreateVideoProcessorEnumeratorFailed)
+        .AddCause(D3D11HresultToStatus(hr, device));
+  }
 
-  if (!SUCCEEDED(device_context_.As(&video_context_)))
-    return false;
+  hr = video_device_->CreateVideoProcessor(processor_enumerator_.Get(), 0,
+                                           &video_processor_);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kCreateVideoProcessorFailed)
+        .AddCause(D3D11HresultToStatus(hr, device));
+  }
 
-  return true;
+  hr = device_context_.As(&video_context_);
+  if (!SUCCEEDED(hr)) {
+    return Status(StatusCode::kQueryVideoContextFailed)
+        .AddCause(D3D11HresultToStatus(hr, device));
+  }
+
+  return OkStatus();
 }
 
 HRESULT VideoProcessorProxy::CreateVideoProcessorOutputView(
diff --git a/media/gpu/windows/d3d11_video_processor_proxy.h b/media/gpu/windows/d3d11_video_processor_proxy.h
index 1e5679a..6543fff 100644
--- a/media/gpu/windows/d3d11_video_processor_proxy.h
+++ b/media/gpu/windows/d3d11_video_processor_proxy.h
@@ -10,6 +10,7 @@
 #include <cstdint>
 
 #include "media/base/hdr_metadata.h"
+#include "media/base/status.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/gpu/windows/d3d11_com_defs.h"
 #include "ui/gfx/color_space.h"
@@ -24,7 +25,7 @@
                       ComD3D11DeviceContext d3d11_device_context);
   virtual ~VideoProcessorProxy();
 
-  virtual bool Init(uint32_t width, uint32_t height);
+  virtual Status Init(uint32_t width, uint32_t height);
 
   // TODO(tmathmeyer) implement color space modification.
 
diff --git a/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc b/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc
index f50a6ea..d46a469 100644
--- a/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc
+++ b/media/gpu/windows/d3d11_video_processor_proxy_unittest.cc
@@ -86,7 +86,7 @@
   EXPECT_CALL(*vctx_.Get(),
               VideoProcessorBlt(proc_.Get(), out_view, 6, 7, streams));
 
-  EXPECT_TRUE(proxy->Init(0, 0));
+  EXPECT_TRUE(proxy->Init(0, 0).is_ok());
   proxy->CreateVideoProcessorOutputView(texture, out_desc, nullptr);
   proxy->CreateVideoProcessorInputView(texture, in_desc, nullptr);
   proxy->VideoProcessorBlt(out_view, 6, 7, streams);
diff --git a/mojo/core/broker_host.cc b/mojo/core/broker_host.cc
index a555bcc..d3ee9f78 100644
--- a/mojo/core/broker_host.cc
+++ b/mojo/core/broker_host.cc
@@ -33,7 +33,7 @@
   CHECK(connection_params.endpoint().is_valid() ||
         connection_params.server_endpoint().is_valid());
 
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  base::CurrentThread::Get()->AddDestructionObserver(this);
 
   channel_ = Channel::Create(this, std::move(connection_params),
                              Channel::HandlePolicy::kAcceptHandles,
@@ -43,7 +43,7 @@
 
 BrokerHost::~BrokerHost() {
   // We're always destroyed on the creation thread, which is the IO thread.
-  base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+  base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
   if (channel_)
     channel_->ShutDown();
diff --git a/mojo/core/broker_host.h b/mojo/core/broker_host.h
index 3ff36ea..f921cba 100644
--- a/mojo/core/broker_host.h
+++ b/mojo/core/broker_host.h
@@ -9,9 +9,9 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/process_handle.h"
 #include "base/strings/string_piece.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "mojo/core/channel.h"
 #include "mojo/core/connection_params.h"
@@ -26,7 +26,7 @@
 // The BrokerHost is a channel to a broker client process, servicing synchronous
 // IPCs issued by the client.
 class BrokerHost : public Channel::Delegate,
-                   public base::MessageLoopCurrent::DestructionObserver {
+                   public base::CurrentThread::DestructionObserver {
  public:
   BrokerHost(base::ProcessHandle client_process,
              ConnectionParams connection_params,
@@ -51,7 +51,7 @@
                         std::vector<PlatformHandle> handles) override;
   void OnChannelError(Channel::Error error) override;
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override;
 
   void OnBufferRequest(uint32_t num_bytes);
diff --git a/mojo/core/channel_fuchsia.cc b/mojo/core/channel_fuchsia.cc
index 2d818ac..4b3db93 100644
--- a/mojo/core/channel_fuchsia.cc
+++ b/mojo/core/channel_fuchsia.cc
@@ -20,10 +20,10 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/stl_util.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/task_runner.h"
 #include "mojo/core/platform_handle_in_transit.h"
 
@@ -148,7 +148,7 @@
 };
 
 class ChannelFuchsia : public Channel,
-                       public base::MessageLoopCurrent::DestructionObserver,
+                       public base::CurrentThread::DestructionObserver,
                        public base::MessagePumpForIO::ZxHandleWatcher {
  public:
   ChannelFuchsia(Delegate* delegate,
@@ -243,17 +243,17 @@
   void StartOnIOThread() {
     DCHECK(!read_watch_);
 
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+    base::CurrentThread::Get()->AddDestructionObserver(this);
 
     read_watch_.reset(
         new base::MessagePumpForIO::ZxHandleWatchController(FROM_HERE));
-    base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+    base::CurrentIOThread::Get()->WatchZxHandle(
         handle_.get(), true /* persistent */,
         ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, read_watch_.get(), this);
   }
 
   void ShutDownOnIOThread() {
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
     read_watch_.reset();
     if (leak_handle_)
@@ -264,7 +264,7 @@
     self_ = nullptr;
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
     if (self_)
diff --git a/mojo/core/channel_mac.cc b/mojo/core/channel_mac.cc
index 52a8a0d..d212aa8 100644
--- a/mojo/core/channel_mac.cc
+++ b/mojo/core/channel_mac.cc
@@ -22,9 +22,9 @@
 #include "base/mac/scoped_mach_msg_destroy.h"
 #include "base/mac/scoped_mach_port.h"
 #include "base/mac/scoped_mach_vm.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 
 extern "C" {
 kern_return_t fileport_makeport(int fd, mach_port_t*);
@@ -41,7 +41,7 @@
 constexpr mach_msg_id_t kChannelMacOOLMsgId = 'MOJ+';
 
 class ChannelMac : public Channel,
-                   public base::MessageLoopCurrent::DestructionObserver,
+                   public base::CurrentThread::DestructionObserver,
                    public base::MessagePumpKqueue::MachPortWatcher {
  public:
   ChannelMac(Delegate* delegate,
@@ -193,13 +193,13 @@
       NOTREACHED();
     }
 
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
-    base::MessageLoopCurrentForIO::Get()->WatchMachReceivePort(
+    base::CurrentThread::Get()->AddDestructionObserver(this);
+    base::CurrentIOThread::Get()->WatchMachReceivePort(
         receive_port_.get(), &watch_controller_, this);
   }
 
   void ShutDownOnIOThread() {
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
     watch_controller_.StopWatchingMachPort();
 
@@ -467,7 +467,7 @@
     return true;
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
     if (self_)
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
index 465457b..8a60724 100644
--- a/mojo/core/channel_posix.cc
+++ b/mojo/core/channel_posix.cc
@@ -16,9 +16,9 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/task_runner.h"
 #include "build/build_config.h"
 #include "mojo/core/core.h"
@@ -91,7 +91,7 @@
 };
 
 class ChannelPosix : public Channel,
-                     public base::MessageLoopCurrent::DestructionObserver,
+                     public base::CurrentThread::DestructionObserver,
                      public base::MessagePumpForIO::FdWatcher {
  public:
   ChannelPosix(Delegate* delegate,
@@ -183,15 +183,15 @@
     DCHECK(!write_watcher_);
     read_watcher_.reset(
         new base::MessagePumpForIO::FdWatchController(FROM_HERE));
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+    base::CurrentThread::Get()->AddDestructionObserver(this);
     if (server_.is_valid()) {
-      base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+      base::CurrentIOThread::Get()->WatchFileDescriptor(
           server_.platform_handle().GetFD().get(), false /* persistent */,
           base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
     } else {
       write_watcher_.reset(
           new base::MessagePumpForIO::FdWatchController(FROM_HERE));
-      base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+      base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_.get(), true /* persistent */,
           base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
       base::AutoLock lock(write_lock_);
@@ -211,7 +211,7 @@
       return;
     if (io_task_runner_->RunsTasksInCurrentSequence()) {
       pending_write_ = true;
-      base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+      base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_.get(), false /* persistent */,
           base::MessagePumpForIO::WATCH_WRITE, write_watcher_.get(), this);
     } else {
@@ -222,7 +222,7 @@
   }
 
   void ShutDownOnIOThread() {
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
     read_watcher_.reset();
     write_watcher_.reset();
@@ -241,7 +241,7 @@
     self_ = nullptr;
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
     if (self_)
@@ -254,7 +254,7 @@
       CHECK_EQ(fd, server_.platform_handle().GetFD().get());
 #if !defined(OS_NACL)
       read_watcher_.reset();
-      base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+      base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
       AcceptSocketConnection(server_.platform_handle().GetFD().get(), &socket_);
       ignore_result(server_.TakePlatformHandle());
diff --git a/mojo/core/channel_win.cc b/mojo/core/channel_win.cc
index 3fee0f2..6b5edf6 100644
--- a/mojo/core/channel_win.cc
+++ b/mojo/core/channel_win.cc
@@ -18,10 +18,10 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/process/process_handle.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/task_runner.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/win_util.h"
@@ -78,7 +78,7 @@
 };
 
 class ChannelWin : public Channel,
-                   public base::MessageLoopCurrent::DestructionObserver,
+                   public base::CurrentThread::DestructionObserver,
                    public base::MessagePumpForIO::IOHandler {
  public:
   ChannelWin(Delegate* delegate,
@@ -190,9 +190,8 @@
   ~ChannelWin() override = default;
 
   void StartOnIOThread() {
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
-    base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.Get(),
-                                                            this);
+    base::CurrentThread::Get()->AddDestructionObserver(this);
+    base::CurrentIOThread::Get()->RegisterIOHandler(handle_.Get(), this);
 
     if (needs_connection_) {
       BOOL ok = ::ConnectNamedPipe(handle_.Get(), &connect_context_.overlapped);
@@ -233,7 +232,7 @@
   }
 
   void ShutDownOnIOThread() {
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
 
     // TODO(https://crbug.com/583525): This function is expected to be called
     // once, and |handle_| should be valid at this point.
@@ -248,7 +247,7 @@
     self_ = nullptr;
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
     if (self_)
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
index ff93f0c..f4657b3 100644
--- a/mojo/core/node_controller.cc
+++ b/mojo/core/node_controller.cc
@@ -13,9 +13,9 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/process_handle.h"
 #include "base/rand_util.h"
+#include "base/task/current_thread.h"
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
 #include "mojo/core/broker.h"
@@ -108,7 +108,7 @@
 // the IO thread is killed, the NodeController can cleanly drop all its peers
 // at that time.
 class ThreadDestructionObserver
-    : public base::MessageLoopCurrent::DestructionObserver {
+    : public base::CurrentThread::DestructionObserver {
  public:
   static void Create(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                      base::OnceClosure callback) {
@@ -124,14 +124,14 @@
  private:
   explicit ThreadDestructionObserver(base::OnceClosure callback)
       : callback_(std::move(callback)) {
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+    base::CurrentThread::Get()->AddDestructionObserver(this);
   }
 
   ~ThreadDestructionObserver() override {
-    base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+    base::CurrentThread::Get()->RemoveDestructionObserver(this);
   }
 
-  // base::MessageLoopCurrent::DestructionObserver:
+  // base::CurrentThread::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
     std::move(callback_).Run();
     delete this;
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index c342d655..4840109 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -12,13 +12,13 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/threading/sequence_local_storage_slot.h"
 #include "base/trace_event/trace_event.h"
 #include "mojo/public/c/system/quota.h"
@@ -96,7 +96,7 @@
   }
 
   static RunLoopNestingObserver* GetForThread() {
-    if (!base::MessageLoopCurrent::Get())
+    if (!base::CurrentThread::Get())
       return nullptr;
     // The NestingObserver for each thread. Note that this is always a
     // Connector::RunLoopNestingObserver; we use the base type here because that
diff --git a/mojo/public/cpp/bindings/tests/e2e_perftest.cc b/mojo/public/cpp/bindings/tests/e2e_perftest.cc
index 91910a4..0b0733c2 100644
--- a/mojo/public/cpp/bindings/tests/e2e_perftest.cc
+++ b/mojo/public/cpp/bindings/tests/e2e_perftest.cc
@@ -8,9 +8,9 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/test/perf_time_logger.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 25af94a4..5ec78a7 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -692,8 +692,8 @@
       if self._IsTypemappedKind(kind) or IsNativeOnlyKind(kind):
         yield '%s->SetInteger("%s", static_cast<int>(%s));' % value_name_cppname
       else:
-        yield '%s->SetString("%s", base::trace_event::'\
-            'TracedValue::ValueToString(%s));' % value_name_cppname
+        yield '%s->SetString("%s", base::trace_event::ValueToString(%s));'\
+            % value_name_cppname
       return
     if mojom.IsStringKind(kind):
       if self.for_blink:
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc
index ffb6e6ef211..34130d1e 100644
--- a/net/base/address_tracker_linux.cc
+++ b/net/base/address_tracker_linux.cc
@@ -13,9 +13,9 @@
 #include "base/bind_helpers.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/task/current_thread.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "net/base/network_interfaces_linux.h"
 
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index b1680d1b..9cfc6272 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -11,9 +11,9 @@
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/io_buffer.h"
@@ -110,7 +110,7 @@
 }
 
 void FileStream::Context::OnFileOpened() {
-  HRESULT hr = base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
+  HRESULT hr = base::CurrentIOThread::Get()->RegisterIOHandler(
       file_.GetPlatformFile(), this);
   if (!SUCCEEDED(hr))
     file_.Close();
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index c8656a9..b918da2 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -11,12 +11,12 @@
 #include "base/files/file.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc
index ea499cf..9e6eda1 100644
--- a/net/base/network_config_watcher_mac.cc
+++ b/net/base/network_config_watcher_mac.cc
@@ -265,7 +265,7 @@
     : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) {
   // We create this notifier thread because the notification implementation
   // needs a thread with a CFRunLoop, and there's no guarantee that
-  // MessageLoopCurrent::Get() meets that criterion.
+  // CurrentThread::Get() meets that criterion.
   base::Thread::Options thread_options(base::MessagePumpType::UI, 0);
   notifier_thread_->StartWithOptions(thread_options);
 }
diff --git a/net/cert/cert_database_mac.cc b/net/cert/cert_database_mac.cc
index c9ad52b9..574b377 100644
--- a/net/cert/cert_database_mac.cc
+++ b/net/cert/cert_database_mac.cc
@@ -10,11 +10,11 @@
 #include "base/check.h"
 #include "base/location.h"
 #include "base/mac/mac_logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/notreached.h"
 #include "base/process/process_handle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "crypto/mac_security_services_lock.h"
 #include "net/base/net_errors.h"
@@ -36,7 +36,7 @@
         registered_(false),
         called_shutdown_(false) {
     // Ensure an associated CFRunLoop.
-    DCHECK(base::MessageLoopCurrentForUI::IsSet());
+    DCHECK(base::CurrentUIThread::IsSet());
     DCHECK(task_runner_->BelongsToCurrentThread());
     task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&Notifier::Init, base::Unretained(this)));
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index 4c6f855..9200593 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -589,6 +589,14 @@
   // match the cookie-path.
   if (!IsOnPath(url.path()))
     status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_NOT_ON_PATH);
+
+  // For LEGACY cookies we should always return the schemeless context,
+  // otherwise let GetContextForCookieInclusion() decide.
+  CookieOptions::SameSiteCookieContext::ContextType cookie_inclusion_context =
+      access_semantics == CookieAccessSemantics::LEGACY
+          ? options.same_site_cookie_context().context()
+          : options.same_site_cookie_context().GetContextForCookieInclusion();
+
   // Don't include same-site cookies for cross-site requests.
   CookieEffectiveSameSite effective_same_site =
       GetEffectiveSameSite(access_semantics);
@@ -601,20 +609,19 @@
                               CookieEffectiveSameSite::COUNT);
   }
   UMA_HISTOGRAM_ENUMERATION(
-      "Cookie.RequestSameSiteContext",
-      options.same_site_cookie_context().GetContextForCookieInclusion(),
+      "Cookie.RequestSameSiteContext", cookie_inclusion_context,
       CookieOptions::SameSiteCookieContext::ContextType::COUNT);
 
   switch (effective_same_site) {
     case CookieEffectiveSameSite::STRICT_MODE:
-      if (options.same_site_cookie_context().GetContextForCookieInclusion() <
+      if (cookie_inclusion_context <
           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT) {
         status.AddExclusionReason(
             CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT);
       }
       break;
     case CookieEffectiveSameSite::LAX_MODE:
-      if (options.same_site_cookie_context().GetContextForCookieInclusion() <
+      if (cookie_inclusion_context <
           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
         status.AddExclusionReason(
             (SameSite() == CookieSameSite::UNSPECIFIED)
@@ -626,7 +633,7 @@
     // TODO(crbug.com/990439): Add a browsertest for this behavior.
     case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
       DCHECK(SameSite() == CookieSameSite::UNSPECIFIED);
-      if (options.same_site_cookie_context().GetContextForCookieInclusion() <
+      if (cookie_inclusion_context <
           CookieOptions::SameSiteCookieContext::ContextType::
               SAME_SITE_LAX_METHOD_UNSAFE) {
         // TODO(chlily): Do we need a separate CookieInclusionStatus for this?
@@ -707,16 +714,22 @@
     UMA_HISTOGRAM_BOOLEAN("Cookie.SameSiteNoneIsSecure", IsSecure());
   }
 
+  // For LEGACY cookies we should always return the schemeless context,
+  // otherwise let GetContextForCookieInclusion() decide.
+  CookieOptions::SameSiteCookieContext::ContextType cookie_inclusion_context =
+      access_semantics == CookieAccessSemantics::LEGACY
+          ? options.same_site_cookie_context().context()
+          : options.same_site_cookie_context().GetContextForCookieInclusion();
+
   access_result->effective_same_site = GetEffectiveSameSite(access_semantics);
   DCHECK(access_result->effective_same_site !=
          CookieEffectiveSameSite::UNDEFINED);
-
   switch (access_result->effective_same_site) {
     case CookieEffectiveSameSite::STRICT_MODE:
       // This intentionally checks for `< SAME_SITE_LAX`, as we allow
       // `SameSite=Strict` cookies to be set for top-level navigations that
       // qualify for receipt of `SameSite=Lax` cookies.
-      if (options.same_site_cookie_context().GetContextForCookieInclusion() <
+      if (cookie_inclusion_context <
           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
         DVLOG(net::cookie_util::kVlogSetCookies)
             << "Trying to set a `SameSite=Strict` cookie from a "
@@ -727,7 +740,7 @@
       break;
     case CookieEffectiveSameSite::LAX_MODE:
     case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
-      if (options.same_site_cookie_context().GetContextForCookieInclusion() <
+      if (cookie_inclusion_context <
           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
         if (SameSite() == CookieSameSite::UNSPECIFIED) {
           DVLOG(net::cookie_util::kVlogSetCookies)
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 4fce6bd..04c1b64 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -758,9 +758,8 @@
   using SameSiteCookieContext = CookieOptions::SameSiteCookieContext;
 
   // Test cases that are the same regardless of feature status or access
-  // semantics:
-  // TODO(https://crbug.com/1030938): This test will need to consider
-  // SchemefulSameSite when it is added to CanonicalCookie.
+  // semantics. For Schemeful Same-Site this means that the context downgrade is
+  // a no-op (such as for NO_RESTRICTION cookies) or that there is no downgrade:
   std::vector<IncludeForRequestURLTestCase> common_test_cases = {
       // Strict cookies:
       {"Common=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
@@ -781,104 +780,86 @@
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
        CookieInclusionStatus()},
-      // Strict cookies with downgrade:
-      {"Common=5;SameSite=Strict", CookieSameSite::STRICT_MODE,
-       CookieEffectiveSameSite::STRICT_MODE,
-       SameSiteCookieContext(
-           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
-           SameSiteCookieContext::ContextType::SAME_SITE_LAX),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE})},
-      {"Common=6;SameSite=Strict", CookieSameSite::STRICT_MODE,
-       CookieEffectiveSameSite::STRICT_MODE,
-       SameSiteCookieContext(
-           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
-           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::
-                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
-      {"Common=7;SameSite=Strict", CookieSameSite::STRICT_MODE,
-       CookieEffectiveSameSite::STRICT_MODE,
-       SameSiteCookieContext(
-           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
-           SameSiteCookieContext::ContextType::CROSS_SITE),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::
-                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
       // Lax cookies:
-      {"Common=8;SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=5;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
        CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
-      {"Common=9;SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=6;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
        CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
-      {"Common=10;SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=7;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
        CookieInclusionStatus()},
-      {"Common=11;SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=8;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
        CookieInclusionStatus()},
       // Lax cookies with downgrade:
-      {"Common=12;SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=9;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
            SameSiteCookieContext::ContextType::SAME_SITE_LAX),
        CookieInclusionStatus()},
-      {"Common=13;SameSite=Lax", CookieSameSite::LAX_MODE,
-       CookieEffectiveSameSite::LAX_MODE,
-       SameSiteCookieContext(
-           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
-           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
-      {"Common=14;SameSite=Lax", CookieSameSite::LAX_MODE,
-       CookieEffectiveSameSite::LAX_MODE,
-       SameSiteCookieContext(
-           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
-           SameSiteCookieContext::ContextType::CROSS_SITE),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
-      {"Common=15;SameSite=Lax", CookieSameSite::LAX_MODE,
-       CookieEffectiveSameSite::LAX_MODE,
-       SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
-                             SameSiteCookieContext::ContextType::CROSS_SITE),
-       CookieInclusionStatus::MakeFromReasonsForTesting(
-           std::vector<CookieInclusionStatus::ExclusionReason>(),
-           {CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE})},
       // None and Secure cookies:
-      {"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=10;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
        CookieInclusionStatus()},
-      {"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=11;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
        CookieInclusionStatus()},
-      {"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=12;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
        CookieInclusionStatus()},
-      {"Common=19;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=13;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        SameSiteCookieContext(
            SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
-       CookieInclusionStatus()}};
+       CookieInclusionStatus()},
+      // Because NO_RESTRICTION cookies are always sent, the schemeful context
+      // downgrades shouldn't matter.
+      {"Common=14;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+       CookieEffectiveSameSite::NO_RESTRICTION,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX),
+       CookieInclusionStatus()},
+      {"Common=15;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+       CookieEffectiveSameSite::NO_RESTRICTION,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
+       CookieInclusionStatus()},
+      {"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+       CookieEffectiveSameSite::NO_RESTRICTION,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus()},
+      {"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+       CookieEffectiveSameSite::NO_RESTRICTION,
+       SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
+                             SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus()},
+      {"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
+       CookieEffectiveSameSite::NO_RESTRICTION,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus()},
+  };
 
   // Test cases where the default is None (either access semantics is LEGACY, or
-  // semantics is UNKNOWN and feature is enabled):
+  // semantics is UNKNOWN and SameSiteByDefaultCookies feature is disabled):
   std::vector<IncludeForRequestURLTestCase> default_none_test_cases = {
       // Unspecified cookies (without SameSite-by-default):
       {"DefaultNone=1", CookieSameSite::UNSPECIFIED,
@@ -907,7 +888,8 @@
        CookieInclusionStatus()}};
 
   // Test cases where the default is Lax (either access semantics is NONLEGACY,
-  // or access semantics is UNKNOWN and feature is enabled):
+  // or access semantics is UNKNOWN and SameSiteByDefaultCookies feature is
+  // enabled):
   std::vector<IncludeForRequestURLTestCase> default_lax_test_cases = {
       // Unspecified recently-created cookies (with SameSite-by-default):
       {"DefaultLax=1", CookieSameSite::UNSPECIFIED,
@@ -961,30 +943,173 @@
        CookieInclusionStatus(), kLongAge},
   };
 
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
-                                      default_lax_test_cases);
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
-                                      default_none_test_cases);
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
-                                      default_lax_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
-                                      default_none_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
-                                      default_none_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
-                                      common_test_cases);
-  VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
-                                      default_lax_test_cases);
+  // Test cases that require LEGACY semantics or Schemeful Same-Site to be
+  // disabled.
+  std::vector<IncludeForRequestURLTestCase> schemeful_disabled_test_cases = {
+      {"LEGACY_Schemeful=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE})},
+      {"LEGACY_Schemeful=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::
+                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
+      {"LEGACY_Schemeful=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::
+                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
+      {"LEGACY_Schemeful=4;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
+      {"LEGACY_Schemeful=5;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
+      {"LEGACY_Schemeful=6;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
+                             SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<CookieInclusionStatus::ExclusionReason>(),
+           {CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE})},
+  };
+
+  // Test cases that require NONLEGACY or UNKNOWN semantics with Schemeful
+  // Same-Site enabled
+  std::vector<IncludeForRequestURLTestCase> schemeful_enabled_test_cases = {
+      {"NONLEGACY_Schemeful=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+           {CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE})},
+      {"NONLEGACY_Schemeful=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+           {CookieInclusionStatus::
+                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
+      {"NONLEGACY_Schemeful=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
+       CookieEffectiveSameSite::STRICT_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+           {CookieInclusionStatus::
+                WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
+      {"NONLEGACY_Schemeful=4;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
+      {"NONLEGACY_Schemeful=5;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(
+           SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+           SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+           {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
+      {"NONLEGACY_Schemeful=6;SameSite=Lax", CookieSameSite::LAX_MODE,
+       CookieEffectiveSameSite::LAX_MODE,
+       SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
+                             SameSiteCookieContext::ContextType::CROSS_SITE),
+       CookieInclusionStatus::MakeFromReasonsForTesting(
+           {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+           {CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE})},
+  };
+
+  auto SchemefulIndependentCases = [&]() {
+    // Run the test cases that are independent of Schemeful Same-Site.
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
+                                        default_lax_test_cases);
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
+                                        default_none_test_cases);
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
+                                        default_lax_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+                                        default_none_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+                                        default_none_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+                                        common_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+                                        default_lax_test_cases);
+  };
+
+  {
+    // Schemeful Same-Site disabled.
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
+
+    SchemefulIndependentCases();
+
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+                                        schemeful_disabled_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+                                        schemeful_disabled_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+                                        schemeful_disabled_test_cases);
+  }
+  {
+    // Schemeful Same-Site enabled.
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
+
+    SchemefulIndependentCases();
+
+    // With LEGACY access the cases should act as if schemeful is disabled, even
+    // when it's not.
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+                                        schemeful_disabled_test_cases);
+
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+                                        schemeful_enabled_test_cases);
+    VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+                                        schemeful_enabled_test_cases);
+  }
 }
 
 // Test that non-SameSite, insecure cookies are excluded if both
@@ -2045,24 +2170,54 @@
                     .IsSetPermittedInContext(context_same_site_strict)
                     .status.IsInclude());
 
-    CookieInclusionStatus status_strict_to_lax =
-        cookie_same_site_unrestricted
-            .IsSetPermittedInContext(context_same_site_strict_to_lax)
-            .status;
-    EXPECT_TRUE(status_strict_to_lax.IsInclude());
-    EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
-    CookieInclusionStatus status_strict_to_cross =
-        cookie_same_site_unrestricted
-            .IsSetPermittedInContext(context_same_site_strict_to_cross)
-            .status;
-    EXPECT_TRUE(status_strict_to_cross.IsInclude());
-    EXPECT_FALSE(status_strict_to_cross.HasDowngradeWarning());
-    CookieInclusionStatus status_lax_to_cross =
-        cookie_same_site_unrestricted
-            .IsSetPermittedInContext(context_same_site_lax_to_cross)
-            .status;
-    EXPECT_TRUE(status_lax_to_cross.IsInclude());
-    EXPECT_FALSE(status_lax_to_cross.HasDowngradeWarning());
+    {
+      // Schemeful Same-Site disabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_TRUE(status_strict_to_cross.IsInclude());
+      EXPECT_FALSE(status_strict_to_cross.HasDowngradeWarning());
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_TRUE(status_lax_to_cross.IsInclude());
+      EXPECT_FALSE(status_lax_to_cross.HasDowngradeWarning());
+    }
+    {
+      // Schemeful Same-Site enabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_TRUE(status_strict_to_cross.IsInclude());
+      EXPECT_FALSE(status_strict_to_cross.HasDowngradeWarning());
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_unrestricted
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_TRUE(status_lax_to_cross.IsInclude());
+      EXPECT_FALSE(status_lax_to_cross.HasDowngradeWarning());
+    }
   }
 
   {
@@ -2081,26 +2236,62 @@
         cookie_same_site_lax.IsSetPermittedInContext(context_same_site_strict)
             .status.IsInclude());
 
-    CookieInclusionStatus status_strict_to_lax =
-        cookie_same_site_lax
-            .IsSetPermittedInContext(context_same_site_strict_to_lax)
-            .status;
-    EXPECT_TRUE(status_strict_to_lax.IsInclude());
-    EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
-    CookieInclusionStatus status_strict_to_cross =
-        cookie_same_site_lax
-            .IsSetPermittedInContext(context_same_site_strict_to_cross)
-            .status;
-    EXPECT_TRUE(status_strict_to_cross.IsInclude());
-    EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
-        CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE));
-    CookieInclusionStatus status_lax_to_cross =
-        cookie_same_site_lax
-            .IsSetPermittedInContext(context_same_site_lax_to_cross)
-            .status;
-    EXPECT_TRUE(status_lax_to_cross.IsInclude());
-    EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
-        CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE));
+    {
+      // Schemeful Same-Site disabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_TRUE(status_strict_to_cross.IsInclude());
+      EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE));
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_TRUE(status_lax_to_cross.IsInclude());
+      EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE));
+    }
+    {
+      // Schemeful Same-Site enabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_FALSE(status_strict_to_cross.IsInclude());
+      EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE));
+      EXPECT_TRUE(status_strict_to_cross.HasExclusionReason(
+          CookieInclusionStatus::EXCLUDE_SAMESITE_LAX));
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_lax
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_FALSE(status_lax_to_cross.IsInclude());
+      EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE));
+      EXPECT_TRUE(status_strict_to_cross.HasExclusionReason(
+          CookieInclusionStatus::EXCLUDE_SAMESITE_LAX));
+    }
   }
 
   {
@@ -2122,26 +2313,87 @@
                     .IsSetPermittedInContext(context_same_site_strict)
                     .status.IsInclude());
 
-    CookieInclusionStatus status_strict_to_lax =
-        cookie_same_site_strict
-            .IsSetPermittedInContext(context_same_site_strict_to_lax)
-            .status;
-    EXPECT_TRUE(status_strict_to_lax.IsInclude());
-    EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
-    CookieInclusionStatus status_strict_to_cross =
-        cookie_same_site_strict
-            .IsSetPermittedInContext(context_same_site_strict_to_cross)
-            .status;
-    EXPECT_TRUE(status_strict_to_cross.IsInclude());
-    EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
-        CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE));
-    CookieInclusionStatus status_lax_to_cross =
-        cookie_same_site_strict
-            .IsSetPermittedInContext(context_same_site_lax_to_cross)
-            .status;
-    EXPECT_TRUE(status_lax_to_cross.IsInclude());
-    EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
-        CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE));
+    {
+      // Schemeful Same-Site disabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_TRUE(status_strict_to_cross.IsInclude());
+      EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE));
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_TRUE(status_lax_to_cross.IsInclude());
+      EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE));
+    }
+    {
+      // Schemeful Same-Site enabled.
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
+
+      CookieInclusionStatus status_strict_to_lax =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_lax)
+              .status;
+      EXPECT_TRUE(status_strict_to_lax.IsInclude());
+      EXPECT_FALSE(status_strict_to_lax.HasDowngradeWarning());
+      CookieInclusionStatus status_strict_to_cross =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_cross)
+              .status;
+      EXPECT_FALSE(status_strict_to_cross.IsInclude());
+      EXPECT_TRUE(status_strict_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE));
+      EXPECT_TRUE(status_strict_to_cross.HasExclusionReason(
+          CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT));
+      CookieInclusionStatus status_lax_to_cross =
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_lax_to_cross)
+              .status;
+      EXPECT_FALSE(status_lax_to_cross.IsInclude());
+      EXPECT_TRUE(status_lax_to_cross.HasWarningReason(
+          CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE));
+      EXPECT_TRUE(status_strict_to_cross.HasExclusionReason(
+          CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT));
+    }
+
+    // Even with Schemeful Same-Site enabled, cookies semantics could change the
+    // inclusion.
+    {
+      base::test::ScopedFeatureList feature_list;
+      feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
+
+      EXPECT_FALSE(
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_cross,
+                                       CookieAccessSemantics::UNKNOWN)
+              .status.IsInclude());
+      EXPECT_FALSE(
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_cross,
+                                       CookieAccessSemantics::NONLEGACY)
+              .status.IsInclude());
+      // LEGACY semantics should allow cookies which Schemeful Same-Site would
+      // normally block.
+      EXPECT_TRUE(
+          cookie_same_site_strict
+              .IsSetPermittedInContext(context_same_site_strict_to_cross,
+                                       CookieAccessSemantics::LEGACY)
+              .status.IsInclude());
+    }
   }
 
   // Behavior of UNSPECIFIED depends on an experiment and CookieAccessSemantics.
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index e67d627e..c2f495b 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -14,9 +14,9 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_tokenizer.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -127,7 +127,7 @@
         http_bar_com_("http://bar.com") {
     // This test may be used outside of the net test suite, and thus may not
     // have a task environment.
-    if (!base::MessageLoopCurrent::Get()) {
+    if (!base::CurrentThread::Get()) {
       task_environment_ =
           std::make_unique<base::test::SingleThreadTaskEnvironment>();
     }
diff --git a/net/disk_cache/blockfile/file_win.cc b/net/disk_cache/blockfile/file_win.cc
index 250aece..9dfb629 100644
--- a/net/disk_cache/blockfile/file_win.cc
+++ b/net/disk_cache/blockfile/file_win.cc
@@ -9,9 +9,9 @@
 
 #include "base/files/file_path.h"
 #include "base/lazy_instance.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "net/base/net_errors.h"
 #include "net/disk_cache/disk_cache.h"
 
@@ -122,8 +122,8 @@
   if (!base_file_.IsValid())
     return false;
 
-  base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
-      base_file_.GetPlatformFile(), CompletionHandler::Get());
+  base::CurrentIOThread::Get()->RegisterIOHandler(base_file_.GetPlatformFile(),
+                                                  CompletionHandler::Get());
 
   init_ = true;
   sync_base_file_ =
@@ -280,7 +280,7 @@
     // Asynchronous IO operations may be in flight and the completion may end
     // up calling us back so let's wait for them.
     base::MessagePumpForIO::IOHandler* handler = CompletionHandler::Get();
-    base::MessageLoopCurrentForIO::Get()->WaitForIOCompletion(100, handler);
+    base::CurrentIOThread::Get()->WaitForIOCompletion(100, handler);
   }
 }
 
diff --git a/net/dns/dns_reloader.cc b/net/dns/dns_reloader.cc
index 0c0d0d8..6c33951 100644
--- a/net/dns/dns_reloader.cc
+++ b/net/dns/dns_reloader.cc
@@ -11,9 +11,9 @@
 
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/notreached.h"
 #include "base/synchronization/lock.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_local.h"
 #include "net/base/network_change_notifier.h"
 
diff --git a/net/dns/serial_worker_unittest.cc b/net/dns/serial_worker_unittest.cc
index d7ce1f8..061b54a0 100644
--- a/net/dns/serial_worker_unittest.cc
+++ b/net/dns/serial_worker_unittest.cc
@@ -6,11 +6,11 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/test/test_with_task_environment.h"
@@ -158,7 +158,7 @@
     WaitForWork();
     RunUntilBreak("OnWorkFinished");
 
-    EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+    EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
   }
 
   // Schedule two calls. OnWork checks if it is called serially.
@@ -171,7 +171,7 @@
   RunUntilBreak("OnWorkFinished");
 
   // No more tasks should remain.
-  EXPECT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
+  EXPECT_TRUE(base::CurrentThread::Get()->IsIdleForTesting());
 }
 
 }  // namespace
diff --git a/net/http/transport_security_persister_unittest.cc b/net/http/transport_security_persister_unittest.cc
index c9a893b..6dbd628 100644
--- a/net/http/transport_security_persister_unittest.cc
+++ b/net/http/transport_security_persister_unittest.cc
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/features.h"
@@ -45,13 +45,13 @@
   }
 
   ~TransportSecurityPersisterTest() override {
-    EXPECT_TRUE(base::MessageLoopCurrentForIO::IsSet());
+    EXPECT_TRUE(base::CurrentIOThread::IsSet());
     base::RunLoop().RunUntilIdle();
   }
 
   void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
+    ASSERT_TRUE(base::CurrentIOThread::IsSet());
     scoped_refptr<base::SequencedTaskRunner> background_runner(
         base::ThreadPool::CreateSequencedTaskRunner(
             {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
index 807ef26..57989da 100644
--- a/net/socket/socket_posix.cc
+++ b/net/socket/socket_posix.cc
@@ -13,8 +13,8 @@
 #include "base/callback_helpers.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "net/base/io_buffer.h"
@@ -178,7 +178,7 @@
   if (rv != ERR_IO_PENDING)
     return rv;
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
           &accept_socket_watcher_, this)) {
     PLOG(ERROR) << "WatchFileDescriptor failed on accept";
@@ -203,7 +203,7 @@
   if (rv != ERR_IO_PENDING)
     return rv;
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
           &write_socket_watcher_, this)) {
     PLOG(ERROR) << "WatchFileDescriptor failed on connect";
@@ -299,7 +299,7 @@
   if (rv != ERR_IO_PENDING)
     return rv;
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
           &read_socket_watcher_, this)) {
     PLOG(ERROR) << "WatchFileDescriptor failed on read";
@@ -349,7 +349,7 @@
   DCHECK(!callback.is_null());
   DCHECK_LT(0, buf_len);
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
           &write_socket_watcher_, this)) {
     PLOG(ERROR) << "WatchFileDescriptor failed on write";
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
index 32f0f19..08d8748 100644
--- a/net/socket/udp_socket_posix.cc
+++ b/net/socket/udp_socket_posix.cc
@@ -18,10 +18,10 @@
 #include "base/debug/alias.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/rand_util.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/task_runner_util.h"
@@ -393,7 +393,7 @@
   if (nread != ERR_IO_PENDING)
     return nread;
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_, true, base::MessagePumpForIO::WATCH_READ,
           &read_socket_watcher_, &read_watcher_)) {
     PLOG(ERROR) << "WatchFileDescriptor failed on read";
@@ -438,7 +438,7 @@
   if (result != ERR_IO_PENDING)
     return result;
 
-  if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
           socket_, true, base::MessagePumpForIO::WATCH_WRITE,
           &write_socket_watcher_, &write_watcher_)) {
     DVPLOG(1) << "WatchFileDescriptor failed on write";
@@ -1464,7 +1464,7 @@
 }
 
 bool UDPSocketPosix::InternalWatchFileDescriptor() {
-  return base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+  return base::CurrentIOThread::Get()->WatchFileDescriptor(
       socket_, true, base::MessagePumpForIO::WATCH_WRITE,
       &write_socket_watcher_, write_async_watcher_.get());
 }
diff --git a/net/spdy/spdy_session_test_util.cc b/net/spdy/spdy_session_test_util.cc
index 7179242..29e1c40 100644
--- a/net/spdy/spdy_session_test_util.cc
+++ b/net/spdy/spdy_session_test_util.cc
@@ -5,8 +5,8 @@
 #include "net/spdy/spdy_session_test_util.h"
 
 #include "base/location.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 
 namespace net {
 
@@ -14,11 +14,11 @@
     const std::string& file_name,
     const std::string& function_name)
     : executed_count_(0), file_name_(file_name), function_name_(function_name) {
-  base::MessageLoopCurrent::Get()->AddTaskObserver(this);
+  base::CurrentThread::Get()->AddTaskObserver(this);
 }
 
 SpdySessionTestTaskObserver::~SpdySessionTestTaskObserver() {
-  base::MessageLoopCurrent::Get()->RemoveTaskObserver(this);
+  base::CurrentThread::Get()->RemoveTaskObserver(this);
 }
 
 void SpdySessionTestTaskObserver::WillProcessTask(
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc
index de54595..48e12cc 100644
--- a/net/test/embedded_test_server/embedded_test_server.cc
+++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -11,7 +11,6 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/path_service.h"
 #include "base/process/process_metrics.h"
@@ -19,6 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task_runner_util.h"
 #include "base/test/bind_test_util.h"
@@ -1000,7 +1000,7 @@
   // TODO(mattm): Is this still necessary/desirable? Try removing this and see
   // if anything breaks.
   std::unique_ptr<base::SingleThreadTaskExecutor> temporary_loop;
-  if (!base::MessageLoopCurrent::Get())
+  if (!base::CurrentThread::Get())
     temporary_loop = std::make_unique<base::SingleThreadTaskExecutor>();
 
   base::RunLoop run_loop;
@@ -1027,7 +1027,7 @@
   // TODO(mattm): Is this still necessary/desirable? Try removing this and see
   // if anything breaks.
   std::unique_ptr<base::SingleThreadTaskExecutor> temporary_loop;
-  if (!base::MessageLoopCurrent::Get())
+  if (!base::CurrentThread::Get())
     temporary_loop = std::make_unique<base::SingleThreadTaskExecutor>();
 
   base::RunLoop run_loop;
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index 6b0f70a..3a8f7f2 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -5,8 +5,8 @@
 #include "net/url_request/url_request_filter.h"
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job_factory_impl.h"
 
@@ -22,15 +22,14 @@
   // MessageLoop is required for some tests where there is no chance to insert
   // an interceptor between a networking thread being started and a resource
   // request being issued.
-  return base::MessageLoopCurrentForIO::IsSet() ||
-         !base::MessageLoopCurrent::IsSet();
+  return base::CurrentIOThread::IsSet() || !base::CurrentThread::IsSet();
 }
 
 // When removing interceptors, DCHECK that this function returns true.
 bool OnMessageLoopForInterceptorRemoval() {
-  // Checking for a MessageLoopCurrentForIO is a best effort at determining
+  // Checking for a CurrentIOThread is a best effort at determining
   // whether the current thread is a networking thread.
-  return base::MessageLoopCurrentForIO::IsSet();
+  return base::CurrentIOThread::IsSet();
 }
 
 }  // namespace
@@ -112,7 +111,7 @@
 URLRequestJob* URLRequestFilter::MaybeInterceptRequest(
     URLRequest* request,
     NetworkDelegate* network_delegate) const {
-  DCHECK(base::MessageLoopCurrentForIO::Get());
+  DCHECK(base::CurrentIOThread::Get());
   URLRequestJob* job = nullptr;
   if (!request->url().is_valid())
     return nullptr;
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
index a53e404..d3c8677 100644
--- a/printing/printing_context_system_dialog_win.cc
+++ b/printing/printing_context_system_dialog_win.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/auto_reset.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "printing/backend/win_helper.h"
 #include "printing/print_settings_initializer_win.h"
 #include "skia/ext/skia_utils_win.h"
@@ -90,7 +90,7 @@
   // browser frame (but still being modal) so neither the browser frame nor
   // the print dialog will get any input. See http://crbug.com/342697
   // http://crbug.com/180997 for details.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
+  base::CurrentThread::ScopedNestableTaskAllower allow;
 
   return PrintDlgEx(options);
 }
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 02e8981c4..825a147 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -13,9 +13,9 @@
 
 #include "base/bind.h"
 #include "base/memory/free_deleter.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "printing/backend/print_backend.h"
 #include "printing/backend/win_helper.h"
 #include "printing/buildflags/buildflags.h"
@@ -299,8 +299,8 @@
   }
 
   // No message loop running in unit tests.
-  DCHECK(!base::MessageLoopCurrent::Get() ||
-         !base::MessageLoopCurrent::Get()->NestableTasksAllowed());
+  DCHECK(!base::CurrentThread::Get() ||
+         !base::CurrentThread::Get()->NestableTasksAllowed());
 
   // Begin a print job by calling the StartDoc function.
   // NOTE: StartDoc() starts a message loop. That causes a lot of problems with
diff --git a/remoting/base/auto_thread.h b/remoting/base/auto_thread.h
index 04ce162..0a37cdf 100644
--- a/remoting/base/auto_thread.h
+++ b/remoting/base/auto_thread.h
@@ -30,7 +30,7 @@
 //
 //  (1) Thread::CleanUp()
 //  (2) MessageLoop::~MessageLoop
-//  (3.b) MessageLoopCurrent::DestructionObserver::WillDestroyCurrentMessageLoop
+//  (3.b) CurrentThread::DestructionObserver::WillDestroyCurrentMessageLoop
 class AutoThread : base::PlatformThread::Delegate {
  public:
   // Create an AutoThread with the specified message-loop |type| and |name|.
diff --git a/remoting/client/chromoting_client_runtime.cc b/remoting/client/chromoting_client_runtime.cc
index dce9221..0393c81 100644
--- a/remoting/client/chromoting_client_runtime.cc
+++ b/remoting/client/chromoting_client_runtime.cc
@@ -8,8 +8,8 @@
 #include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "build/build_config.h"
@@ -31,7 +31,7 @@
 ChromotingClientRuntime::ChromotingClientRuntime() {
   base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Remoting");
 
-  DCHECK(!base::MessageLoopCurrent::Get());
+  DCHECK(!base::CurrentThread::Get());
 
   VLOG(1) << "Starting main message loop";
   ui_task_executor_.reset(
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc
index 0576be8..2460df2 100644
--- a/remoting/host/desktop_process.cc
+++ b/remoting/host/desktop_process.cc
@@ -14,9 +14,9 @@
 #include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "remoting/base/auto_thread.h"
@@ -41,7 +41,7 @@
       io_task_runner_(io_task_runner),
       daemon_channel_handle_(std::move(daemon_channel_handle)) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 }
 
 DesktopProcess::~DesktopProcess() {
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc
index 1935b24..6075bc9 100644
--- a/remoting/host/win/rdp_client.cc
+++ b/remoting/host/win/rdp_client.cc
@@ -12,9 +12,9 @@
 #include "base/bind_helpers.h"
 #include "base/check_op.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
 #include "remoting/base/typed_buffer.h"
@@ -139,7 +139,7 @@
     return;
   }
 
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(!rdp_client_window_);
   DCHECK(!self_.get());
 
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
index a1a3bc5..ea2047b 100644
--- a/remoting/host/win/wts_session_process_delegate.cc
+++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -15,12 +15,12 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/process_handle.h"
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/win/scoped_handle.h"
 #include "ipc/ipc_channel.h"
@@ -209,7 +209,7 @@
     // the completion port represented by |io_task_runner|. The registration has
     // to be done on the I/O thread because
     // MessageLoopForIO::RegisterJobObject() can only be called via
-    // MessageLoopCurrentForIO::Get().
+    // CurrentIOThread::Get().
     io_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&Core::InitializeJob, this, std::move(job)));
   }
@@ -484,8 +484,7 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
   // Register to receive job notifications via the I/O thread's completion port.
-  if (!base::MessageLoopCurrentForIO::Get()->RegisterJobObject(job.Get(),
-                                                               this)) {
+  if (!base::CurrentIOThread::Get()->RegisterJobObject(job.Get(), this)) {
     PLOG(ERROR) << "Failed to associate the job object with a completion port";
     return;
   }
diff --git a/sandbox/BUILD.gn b/sandbox/BUILD.gn
index 27dea2c2..f75d4340 100644
--- a/sandbox/BUILD.gn
+++ b/sandbox/BUILD.gn
@@ -56,7 +56,10 @@
   if (!is_win) {
     defines = [ "SANDBOX_FUZZ_TARGET" ]
   }
-  deps = [ "//base" ]
+  deps = [
+    ":sandbox",
+    "//base",
+  ]
   dict = "ipc.dict"
   libfuzzer_options = [ "max_len=1024" ]
 }
diff --git a/sandbox/policy/BUILD.gn b/sandbox/policy/BUILD.gn
index 13f8fab..26c5ac1 100644
--- a/sandbox/policy/BUILD.gn
+++ b/sandbox/policy/BUILD.gn
@@ -154,6 +154,7 @@
   deps = [
     ":policy",
     "//base",
+    "//base/test:test_support",
     "//testing/gtest",
   ]
 
diff --git a/services/device/screen_orientation/screen_orientation_listener_android.cc b/services/device/screen_orientation/screen_orientation_listener_android.cc
index 0b36405..40b8798 100644
--- a/services/device/screen_orientation/screen_orientation_listener_android.cc
+++ b/services/device/screen_orientation/screen_orientation_listener_android.cc
@@ -6,7 +6,7 @@
 
 #include "base/android/jni_android.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/device/screen_orientation/screen_orientation_jni_headers/ScreenOrientationListener_jni.h"
 
@@ -23,7 +23,7 @@
 ScreenOrientationListenerAndroid::ScreenOrientationListenerAndroid() = default;
 
 ScreenOrientationListenerAndroid::~ScreenOrientationListenerAndroid() {
-  DCHECK(base::MessageLoopCurrentForIO::IsSet());
+  DCHECK(base::CurrentIOThread::IsSet());
 }
 
 void ScreenOrientationListenerAndroid::IsAutoRotateEnabledByUser(
diff --git a/services/device/serial/serial_io_handler_win.cc b/services/device/serial/serial_io_handler_win.cc
index 29a69f26..9b273f8 100644
--- a/services/device/serial/serial_io_handler_win.cc
+++ b/services/device/serial/serial_io_handler_win.cc
@@ -13,9 +13,9 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/scoped_observer.h"
 #include "base/sequence_checker.h"
+#include "base/task/current_thread.h"
 #include "device/base/device_info_query_win.h"
 #include "device/base/device_monitor_win.h"
 #include "services/device/serial/serial_device_enumerator_win.h"
@@ -235,8 +235,8 @@
   DCHECK(!read_context_);
   DCHECK(!write_context_);
 
-  base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
-      file().GetPlatformFile(), this);
+  base::CurrentIOThread::Get()->RegisterIOHandler(file().GetPlatformFile(),
+                                                  this);
 
   comm_context_.reset(new base::MessagePumpForIO::IOContext());
   read_context_.reset(new base::MessagePumpForIO::IOContext());
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 3bb208b..a400f406 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -17,13 +17,13 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/optional.h"
 #include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 123591d..afddb92 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -131,6 +131,7 @@
 
   deps = [
     "//base",
+    "//base/util/ranges:ranges",
     "//components/prefs",
     "//ipc",
     "//services/proxy_resolver/public/mojom",
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy.cc b/services/network/public/cpp/content_security_policy/content_security_policy.cc
index 43e09d1..fcdcdac3 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -6,12 +6,13 @@
 
 #include <sstream>
 #include <string>
-#include "base/containers/flat_map.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/util/ranges/algorithm.h"
 #include "net/http/http_response_headers.h"
 #include "services/network/public/cpp/content_security_policy/csp_context.h"
 #include "services/network/public/cpp/content_security_policy/csp_source.h"
@@ -27,10 +28,20 @@
 namespace network {
 
 using CSPDirectiveName = mojom::CSPDirectiveName;
-using DirectivesMap = base::flat_map<base::StringPiece, base::StringPiece>;
+using DirectivesMap =
+    std::vector<std::pair<base::StringPiece, base::StringPiece>>;
 
 namespace {
 
+bool IsDirectiveNameCharacter(char c) {
+  return base::IsAsciiAlpha(c) || c == '-';
+}
+
+bool IsDirectiveValueCharacter(char c) {
+  return base::IsAsciiWhitespace(c) ||
+         base::IsAsciiPrintable(c);  // Whitespace + VCHAR
+}
+
 static CSPDirectiveName CSPFallback(CSPDirectiveName directive,
                                     CSPDirectiveName original_directive) {
   switch (directive) {
@@ -226,21 +237,16 @@
     size_t pos = directive.find_first_of(base::kWhitespaceASCII);
     base::StringPiece name = directive.substr(0, pos);
 
-    // 5. If policy's directive set contains a directive whose name is
-    // directive name, continue.
-    if (result.find(name) != result.end())
-      continue;
-
-    // 6. Let directive value be the result of splitting token on ASCII
+    // 5. Let directive value be the result of splitting token on ASCII
     // whitespace.
     base::StringPiece value;
     if (pos != std::string::npos)
       value = directive.substr(pos + 1);
 
-    // 7. Let directive be a new directive whose name is directive name,
+    // 6. Let directive be a new directive whose name is directive name,
     // and value is directive value.
-    // 8. Append directive to policy's directive set.
-    result.insert({name, value});
+    // 7. Append directive to policy's directive set.
+    result.emplace_back(std::make_pair(name, value));
   }
 
   return result;
@@ -325,10 +331,6 @@
   if (path[0] != '/')
     return false;
 
-  // TODO(lfg): Emit a warning to the user when a path containing # or ? is
-  // seen.
-  path = path.substr(0, path.find_first_of("#?"));
-
   url::RawCanonOutputT<base::char16> unescaped;
   url::DecodeURLEscapeSequences(path.data(), path.size(),
                                 url::DecodeURLMode::kUTF8OrIsomorphic,
@@ -342,12 +344,13 @@
 // https://w3c.github.io/webappsec-csp/#source-lists
 //
 // Return false on errors.
-bool ParseSource(base::StringPiece expression, mojom::CSPSource* csp_source) {
-  // TODO(arthursonzogni): Blink reports an invalid source expression when
-  // 'none' is parsed here.
-  if (base::EqualsCaseInsensitiveASCII(expression, "'none'"))
-    return false;
-
+// Adds parsing error messages to |parsing_errors|.
+// Notice that this can return true and still add some parsing error message
+// (for example, if there is a url with a non-empty query part).
+bool ParseSource(CSPDirectiveName directive_name,
+                 base::StringPiece expression,
+                 mojom::CSPSource* csp_source,
+                 std::vector<std::string>& parsing_errors) {
   size_t position = expression.find_first_of(":/");
   if (position != std::string::npos && expression[position] == ':') {
     // scheme:
@@ -394,7 +397,25 @@
 
   // /
   // ^
-  return expression.empty() || ParsePath(expression, csp_source);
+  if (expression.empty())
+    return true;
+
+  // Emit a warning to the user when a url contains a # or ?.
+  position = expression.find_first_of("#?");
+  bool path_parsed = ParsePath(expression.substr(0, position), csp_source);
+  if (path_parsed && position != std::string::npos) {
+    const char* ignoring =
+        expression[position] == '?'
+            ? "The query component, including the '?', will be ignored."
+            : "The fragment identifier, including the '#', will be ignored.";
+    parsing_errors.emplace_back(base::StringPrintf(
+        "The source list for Content-Security-Policy directive '%s' "
+        "contains a source with an invalid path: '%s'. %s",
+        ToString(directive_name).c_str(), expression.as_string().c_str(),
+        ignoring));
+  }
+
+  return path_parsed;
 }
 
 bool IsBase64Char(char c) {
@@ -488,8 +509,11 @@
 
 // Parse source-list grammar.
 // https://www.w3.org/TR/CSP3/#grammardef-serialized-source-list
-mojom::CSPSourceListPtr ParseSourceList(CSPDirectiveName directive_name,
-                                        base::StringPiece directive_value) {
+// Append parsing errors to |parsing_errors|.
+mojom::CSPSourceListPtr ParseSourceList(
+    CSPDirectiveName directive_name,
+    base::StringPiece directive_value,
+    std::vector<std::string>& parsing_errors) {
   base::StringPiece value =
       base::TrimString(directive_value, base::kWhitespaceASCII, base::TRIM_ALL);
 
@@ -501,6 +525,16 @@
   for (const auto& expression : base::SplitStringPiece(
            value, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
            base::SPLIT_WANT_NONEMPTY)) {
+    if (base::EqualsCaseInsensitiveASCII(expression, "'none'")) {
+      parsing_errors.emplace_back(base::StringPrintf(
+          "The Content-Security-Policy directive '%s' contains the keyword "
+          "'none' alongside with other source expressions. The keyword 'none' "
+          "must be the only source expression in the directive value, "
+          "otherwise it is ignored.",
+          ToString(directive_name).c_str()));
+      continue;
+    }
+
     if (base::EqualsCaseInsensitiveASCII(expression, "'self'")) {
       directive->allow_self = true;
       continue;
@@ -511,8 +545,18 @@
       continue;
     }
 
+    if (ToCSPDirectiveName(expression.as_string()) !=
+        CSPDirectiveName::Unknown) {
+      parsing_errors.emplace_back(base::StringPrintf(
+          "The Content-Security-Policy directive '%s' contains '%s' as a "
+          "source expression. Did you want to add it as a directive and forget "
+          "a semicolon?",
+          ToString(directive_name).c_str(), expression.as_string().c_str()));
+    }
+
     auto csp_source = mojom::CSPSource::New();
-    if (ParseSource(expression, csp_source.get())) {
+    if (ParseSource(directive_name, expression, csp_source.get(),
+                    parsing_errors)) {
       directive->sources.push_back(std::move(csp_source));
       continue;
     }
@@ -520,8 +564,10 @@
     if (directive_name == CSPDirectiveName::FrameAncestors) {
       // The frame-ancestors directive does not support anything else
       // https://w3c.github.io/webappsec-csp/#directive-frame-ancestors
-      // TODO(antoniosartori): This is a parsing error, so we should emit a
-      // warning.
+      parsing_errors.emplace_back(base::StringPrintf(
+          "The Content-Security-Policy directive 'frame-ancestors' does not "
+          "support the source expression '%s'",
+          expression.as_string().c_str()));
       continue;
     }
 
@@ -576,8 +622,10 @@
 
     // Parsing error.
     // Ignore this source-expression.
-    // TODO(lfg): Emit a warning to the user when parsing an invalid
-    // expression.
+    parsing_errors.emplace_back(base::StringPrintf(
+        "The source list for the Content-Security-Policy directive '%s' "
+        "contains an invalid source: '%s'.",
+        ToString(directive_name).c_str(), expression.as_string().c_str()));
   }
 
   return directive;
@@ -620,42 +668,6 @@
   }
 }
 
-// Parses a directive of a Content-Security-Policy header that adheres to the
-// source list grammar.
-void ParseSourceListTypeDirective(const mojom::ContentSecurityPolicyPtr& policy,
-                                  CSPDirectiveName directive_name,
-                                  base::StringPiece value) {
-  // A directive with this name has already been parsed. Skip further
-  // directives per
-  // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
-  // TODO(arthursonzogni, lfg): Should a warning be fired to the user here?
-  if (policy->directives.count(directive_name))
-    return;
-
-  auto source_list = ParseSourceList(directive_name, value);
-
-  // TODO(lfg): Emit a warning to the user when parsing an invalid
-  // expression.
-  if (!source_list)
-    return;
-
-  policy->directives[directive_name] = std::move(source_list);
-}
-
-// Parses the report-uri directive of a Content-Security-Policy header.
-void ParseReportEndpoint(const mojom::ContentSecurityPolicyPtr& policy,
-                         const GURL& base_url,
-                         base::StringPiece header_value,
-                         bool using_reporting_api) {
-  // A report-uri directive has already been parsed. Skip further directives per
-  // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
-  if (!policy->report_endpoints.empty())
-    return;
-
-  ParseReportDirective(base_url, header_value, using_reporting_api,
-                       &(policy->report_endpoints));
-}
-
 void AddContentSecurityPolicyFromHeader(base::StringPiece header,
                                         mojom::ContentSecurityPolicyType type,
                                         const GURL& base_url,
@@ -665,8 +677,38 @@
       header.as_string(), type, mojom::ContentSecurityPolicySource::kHTTP);
 
   for (auto directive : directives) {
+    if (!util::ranges::all_of(directive.first, IsDirectiveNameCharacter)) {
+      out->parsing_errors.emplace_back(base::StringPrintf(
+          "The Content-Security-Policy directive name '%s' contains one or "
+          "more invalid characters. Only ASCII alphanumeric characters or "
+          "dashes '-' are allowed in directive names.",
+          directive.first.as_string().c_str()));
+      continue;
+    }
+
+    if (!util::ranges::all_of(directive.second, IsDirectiveValueCharacter)) {
+      out->parsing_errors.emplace_back(base::StringPrintf(
+          "The value for the Content-Security-Policy directive '%s' contains "
+          "one or more invalid characters. Non-whitespace characters outside "
+          "ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, "
+          "section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
+          directive.first.as_string().c_str()));
+      continue;
+    }
+
     CSPDirectiveName directive_name =
         ToCSPDirectiveName(directive.first.as_string());
+
+    // A directive with this name has already been parsed. Skip further
+    // directives per
+    // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
+    if (out->directives.count(directive_name)) {
+      out->parsing_errors.emplace_back(base::StringPrintf(
+          "Ignoring duplicate Content-Security-Policy directive '%s'.",
+          directive.first.as_string().c_str()));
+      continue;
+    }
+
     switch (directive_name) {
       case CSPDirectiveName::BaseURI:
       case CSPDirectiveName::ChildSrc:
@@ -689,33 +731,56 @@
       case CSPDirectiveName::StyleSrcAttr:
       case CSPDirectiveName::StyleSrcElem:
       case CSPDirectiveName::WorkerSrc:
-        ParseSourceListTypeDirective(out, directive_name, directive.second);
+        out->directives[directive_name] = ParseSourceList(
+            directive_name, directive.second, out->parsing_errors);
         break;
       case CSPDirectiveName::Sandbox:
         // Note: |ParseSandboxPolicy(...).error_message| is ignored here.
         // Blink's CSP parser is already in charge of displaying it.
-        out->sandbox = ~ParseWebSandboxPolicy(directive.second,
-                                              mojom::WebSandboxFlags::kNone)
-                            .flags;
+        {
+          auto sandbox = ParseWebSandboxPolicy(directive.second,
+                                               mojom::WebSandboxFlags::kNone);
+          out->sandbox = ~sandbox.flags;
+          out->parsing_errors.emplace_back(std::move(sandbox.error_message));
+        }
         break;
       case CSPDirectiveName::UpgradeInsecureRequests:
         out->upgrade_insecure_requests = true;
+        if (!directive.second.empty()) {
+          out->parsing_errors.emplace_back(base::StringPrintf(
+              "The Content Security Policy directive "
+              "'upgrade-insecure-requests' should be empty, but was delivered "
+              "with a value of '%s'. The directive has been applied, and the "
+              "value ignored.",
+              directive.second.as_string().c_str()));
+        }
         break;
       case CSPDirectiveName::TreatAsPublicAddress:
         out->treat_as_public_address = true;
+        if (!directive.second.empty()) {
+          out->parsing_errors.emplace_back(base::StringPrintf(
+              "The Content Security Policy directive 'treat-as-public-address' "
+              "should be empty, but was delivered with a value of '%s'. The "
+              "directive has been applied, and the value ignored.",
+              directive.second.as_string().c_str()));
+        }
         break;
       case CSPDirectiveName::ReportTo:
         out->use_reporting_api = true;
         out->report_endpoints.clear();
-        ParseReportEndpoint(out, base_url, directive.second,
-                            out->use_reporting_api);
+        ParseReportDirective(base_url, directive.second, out->use_reporting_api,
+                             &(out->report_endpoints));
         break;
       case CSPDirectiveName::ReportURI:
         if (!out->use_reporting_api)
-          ParseReportEndpoint(out, base_url, directive.second,
-                              out->use_reporting_api);
+          ParseReportDirective(base_url, directive.second,
+                               out->use_reporting_api,
+                               &(out->report_endpoints));
         break;
       case CSPDirectiveName::Unknown:
+        out->parsing_errors.emplace_back(base::StringPrintf(
+            "Unrecognized Content-Security-Policy directive '%s'.",
+            directive.first.as_string().c_str()));
         break;
     }
   }
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
index fb0eeb7..90b1b86 100644
--- a/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
+++ b/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
@@ -233,17 +233,19 @@
     TestFrameAncestorsCSPParser(test.header, &test.expected_result);
 }
 
-TEST(ContentSecurityPolicy, ParseMultipleDirectives) {
-  // First directive is valid, second one is ignored.
+TEST(ContentSecurityPolicy, ParseDirectives) {
+  // One duplicate directive.
   {
     scoped_refptr<net::HttpResponseHeaders> headers(
         new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
     headers->SetHeader("Content-Security-Policy",
-                       "frame-ancestors example.com; other_directive "
-                       "value; frame-ancestors example.org");
+                       "frame-ancestors example.com; script-src "
+                       "example2.com; frame-ancestors example3.com");
     std::vector<mojom::ContentSecurityPolicyPtr> policies;
     AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
                                         &policies);
+    EXPECT_EQ(2U, policies[0]->directives.size());
+
     auto& frame_ancestors =
         policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
     EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -254,18 +256,37 @@
     EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
     EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
     EXPECT_EQ(frame_ancestors->allow_self, false);
+
+    auto& script_src =
+        policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc];
+    EXPECT_EQ(script_src->sources.size(), 1U);
+    EXPECT_EQ(script_src->sources[0]->scheme, "");
+    EXPECT_EQ(script_src->sources[0]->host, "example2.com");
+    EXPECT_EQ(script_src->sources[0]->port, url::PORT_UNSPECIFIED);
+    EXPECT_EQ(script_src->sources[0]->path, "");
+    EXPECT_EQ(script_src->sources[0]->is_host_wildcard, false);
+    EXPECT_EQ(script_src->sources[0]->is_port_wildcard, false);
+    EXPECT_EQ(script_src->allow_self, false);
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "Ignoring duplicate Content-Security-Policy directive "
+        "'frame-ancestors'.",
+        policies[0]->parsing_errors[0]);
   }
 
-  // Skip the first directive, which is not frame-ancestors.
+  // One invalid directive.
   {
     scoped_refptr<net::HttpResponseHeaders> headers(
         new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
     headers->SetHeader("Content-Security-Policy",
-                       "other_directive value; frame-ancestors "
+                       "other-directive value; frame-ancestors "
                        "example.org");
     std::vector<mojom::ContentSecurityPolicyPtr> policies;
     AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
                                         &policies);
+    EXPECT_EQ(1U, policies[0]->directives.size());
+
     auto& frame_ancestors =
         policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
     EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -277,6 +298,143 @@
     EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
     EXPECT_EQ(frame_ancestors->allow_self, false);
     EXPECT_EQ(frame_ancestors->allow_star, false);
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "Unrecognized Content-Security-Policy directive 'other-directive'.",
+        policies[0]->parsing_errors[0]);
+  }
+
+  // Invalid characters in directive name.
+  {
+    scoped_refptr<net::HttpResponseHeaders> headers(
+        new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+    headers->SetHeader("Content-Security-Policy",
+                       "frame_ancestors example.com;");
+    std::vector<mojom::ContentSecurityPolicyPtr> policies;
+    AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+                                        &policies);
+    EXPECT_TRUE(policies[0]->directives.empty());
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "The Content-Security-Policy directive name 'frame_ancestors' contains "
+        "one or more invalid characters. Only ASCII alphanumeric characters or "
+        "dashes '-' are allowed in directive names.",
+        policies[0]->parsing_errors[0]);
+  }
+
+  // Invalid characters in directive value.
+  {
+    scoped_refptr<net::HttpResponseHeaders> headers(
+        new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+    headers->SetHeader("Content-Security-Policy", "frame-ancestors ü.com;");
+    std::vector<mojom::ContentSecurityPolicyPtr> policies;
+    AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+                                        &policies);
+    EXPECT_TRUE(policies[0]->directives.empty());
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "The value for the Content-Security-Policy directive 'frame-ancestors' "
+        "contains one or more invalid characters. Non-whitespace characters "
+        "outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC "
+        "3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
+        policies[0]->parsing_errors[0]);
+  }
+
+  // Missing semicolon between directive names.
+  {
+    scoped_refptr<net::HttpResponseHeaders> headers(
+        new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+    headers->SetHeader("Content-Security-Policy", "frame-ancestors object-src");
+    std::vector<mojom::ContentSecurityPolicyPtr> policies;
+    AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+                                        &policies);
+    EXPECT_EQ(1U, policies[0]->directives.size());
+
+    auto& frame_ancestors =
+        policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+    EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+    EXPECT_EQ(frame_ancestors->sources[0]->scheme, "");
+    EXPECT_EQ(frame_ancestors->sources[0]->host, "object-src");
+    EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+    EXPECT_EQ(frame_ancestors->sources[0]->path, "");
+    EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+    EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+    EXPECT_EQ(frame_ancestors->allow_self, false);
+    EXPECT_EQ(frame_ancestors->allow_star, false);
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "The Content-Security-Policy directive 'frame-ancestors' contains "
+        "'object-src' as a source expression. Did you want to add it as a "
+        "directive and forget a semicolon?",
+        policies[0]->parsing_errors[0]);
+  }
+
+  // Path containing query.
+  {
+    scoped_refptr<net::HttpResponseHeaders> headers(
+        new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+    headers->SetHeader("Content-Security-Policy",
+                       "frame-ancestors http://example.org/index.html?a=b;");
+    std::vector<mojom::ContentSecurityPolicyPtr> policies;
+    AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+                                        &policies);
+    EXPECT_EQ(1U, policies[0]->directives.size());
+
+    auto& frame_ancestors =
+        policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+    EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+    EXPECT_EQ(frame_ancestors->sources[0]->scheme, "http");
+    EXPECT_EQ(frame_ancestors->sources[0]->host, "example.org");
+    EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+    EXPECT_EQ(frame_ancestors->sources[0]->path, "/index.html");
+    EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+    EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+    EXPECT_EQ(frame_ancestors->allow_self, false);
+    EXPECT_EQ(frame_ancestors->allow_star, false);
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "The source list for Content-Security-Policy directive "
+        "'frame-ancestors' contains a source with an invalid path: "
+        "'/index.html?a=b'. The query component, including the '?', will be "
+        "ignored.",
+        policies[0]->parsing_errors[0]);
+  }
+
+  // Path containing ref.
+  {
+    scoped_refptr<net::HttpResponseHeaders> headers(
+        new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+    headers->SetHeader("Content-Security-Policy",
+                       "frame-ancestors http://example.org/index.html#a;");
+    std::vector<mojom::ContentSecurityPolicyPtr> policies;
+    AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+                                        &policies);
+    EXPECT_EQ(1U, policies[0]->directives.size());
+
+    auto& frame_ancestors =
+        policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+    EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+    EXPECT_EQ(frame_ancestors->sources[0]->scheme, "http");
+    EXPECT_EQ(frame_ancestors->sources[0]->host, "example.org");
+    EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+    EXPECT_EQ(frame_ancestors->sources[0]->path, "/index.html");
+    EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+    EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+    EXPECT_EQ(frame_ancestors->allow_self, false);
+    EXPECT_EQ(frame_ancestors->allow_star, false);
+
+    EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+    EXPECT_EQ(
+        "The source list for Content-Security-Policy directive "
+        "'frame-ancestors' contains a source with an invalid path: "
+        "'/index.html#a'. The fragment identifier, including the '#', will be "
+        "ignored.",
+        policies[0]->parsing_errors[0]);
   }
 
   // Multiple CSP headers with multiple frame-ancestors directives present.
@@ -323,7 +481,7 @@
     scoped_refptr<net::HttpResponseHeaders> headers(
         new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
     headers->SetHeader("Content-Security-Policy",
-                       "other_directive value, frame-ancestors example.org");
+                       "other-directive value, frame-ancestors example.org");
     std::vector<mojom::ContentSecurityPolicyPtr> policies;
     AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
                                         &policies);
@@ -809,6 +967,7 @@
   struct TestCase {
     std::string directive_value;
     base::Callback<mojom::CSPSourceListPtr()> expected;
+    std::string expected_error;
   } cases[] = {
       {
           "'nonce-a' 'nonce-a=' 'nonce-a==' 'nonce-a===' 'nonce-==' 'nonce-' "
@@ -823,6 +982,7 @@
             csp->nonces.push_back("cde==");
             return csp;
           }),
+          "",
       },
       {
           "'sha256-abc' 'sha256-ABC' 'sha256 'sha256-' 'sha384-abc' "
@@ -846,13 +1006,39 @@
                 mojom::CSPHashAlgorithm::SHA512, "cde"));
             return csp;
           }),
+          "",
       },
       {
           "'none' ",
           base::Bind([] { return mojom::CSPSourceList::New(); }),
+          "",
       },
       {
-          "'wrong' 'self'",
+          "'none' 'self'",
+          base::Bind([] {
+            auto csp = mojom::CSPSourceList::New();
+            csp->allow_self = true;
+            return csp;
+          }),
+          "The Content-Security-Policy directive 'script-src' contains the "
+          "keyword 'none' alongside with other source expressions. The keyword "
+          "'none' must be the only source expression in the directive value, "
+          "otherwise it is ignored.",
+      },
+      {
+          "'self' 'none'",
+          base::Bind([] {
+            auto csp = mojom::CSPSourceList::New();
+            csp->allow_self = true;
+            return csp;
+          }),
+          "The Content-Security-Policy directive 'script-src' contains the "
+          "keyword 'none' alongside with other source expressions. The keyword "
+          "'none' must be the only source expression in the directive value, "
+          "otherwise it is ignored.",
+      },
+      {
+          "'self'",
           base::Bind([] {
             auto csp = mojom::CSPSourceList::New();
             csp->allow_self = true;
@@ -866,6 +1052,8 @@
             csp->allow_star = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'unsafe-inline'",
@@ -874,6 +1062,8 @@
             csp->allow_inline = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'unsafe-eval'",
@@ -882,6 +1072,8 @@
             csp->allow_eval = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'wasm-eval'",
@@ -890,6 +1082,8 @@
             csp->allow_wasm_eval = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'strict-dynamic'",
@@ -898,6 +1092,8 @@
             csp->allow_dynamic = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'unsafe-hashes'",
@@ -906,6 +1102,8 @@
             csp->allow_unsafe_hashes = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
       {
           "'wrong' 'report-sample'",
@@ -914,6 +1112,8 @@
             csp->report_sample = true;
             return csp;
           }),
+          "The source list for the Content-Security-Policy directive "
+          "'script-src' contains an invalid source: ''wrong''.",
       },
   };
 
@@ -928,6 +1128,9 @@
                                         &policies);
     EXPECT_TRUE(test.expected.Run().Equals(
         policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]));
+
+    if (!test.expected_error.empty())
+      EXPECT_EQ(test.expected_error, policies[0]->parsing_errors[0]);
   }
 }
 
diff --git a/services/network/public/mojom/content_security_policy.mojom b/services/network/public/mojom/content_security_policy.mojom
index a4fc9e8..e552cf79 100644
--- a/services/network/public/mojom/content_security_policy.mojom
+++ b/services/network/public/mojom/content_security_policy.mojom
@@ -149,6 +149,9 @@
 
   // Set of reporting endpoints to which violation reports are sent.
   array<string> report_endpoints;
+
+  // An array containing a set of errors occurred while parsing the CSP header.
+  array<string> parsing_errors;
 };
 
 // Data to report Content-Security-Policy violations.
diff --git a/services/service_manager/public/cpp/service_executable/service_executable_environment.cc b/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
index af9a635b..3b08dd9a 100644
--- a/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
+++ b/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
@@ -6,9 +6,9 @@
 
 #include "base/check.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "build/build_config.h"
 #include "mojo/core/embedder/embedder.h"
@@ -29,7 +29,7 @@
 
 ServiceExecutableEnvironment::ServiceExecutableEnvironment()
     : ipc_thread_("IPC Thread") {
-  DCHECK(!base::MessageLoopCurrent::Get());
+  DCHECK(!base::CurrentThread::Get());
 
 #if defined(OS_LINUX)
   const base::CommandLine& command_line =
diff --git a/services/service_manager/tests/connect/connect_test_app.cc b/services/service_manager/tests/connect/connect_test_app.cc
index f72e302..d921f8f 100644
--- a/services/service_manager/tests/connect/connect_test_app.cc
+++ b/services/service_manager/tests/connect/connect_test_app.cc
@@ -6,9 +6,9 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/task/single_thread_task_executor.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index cafa13d..26ed9b1 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -444,24 +444,6 @@
             ]
         }
     ],
-    "AndroidTouchToFill": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "params": {
-                        "show_confirmation_button": "false"
-                    },
-                    "enable_features": [
-                        "TouchToFillAndroid"
-                    ]
-                }
-            ]
-        }
-    ],
     "AppListLaunchRecorder": [
         {
             "platforms": [
diff --git a/third_party/blink/public/mojom/tokens/BUILD.gn b/third_party/blink/public/mojom/tokens/BUILD.gn
index 0eed6cc..5d2e992 100644
--- a/third_party/blink/public/mojom/tokens/BUILD.gn
+++ b/third_party/blink/public/mojom/tokens/BUILD.gn
@@ -9,10 +9,7 @@
   output_prefix = "tokens_mojom"
   macro_prefix = "TOKENS_MOJOM"
 
-  sources = [
-    "frame_token.mojom",
-    "worker_tokens.mojom",
-  ]
+  sources = [ "frame_token.mojom" ]
 
   public_deps = [ "//mojo/public/mojom/base" ]
 
@@ -20,9 +17,9 @@
   export_define = "BLINK_COMMON_IMPLEMENTATION=1"
   export_header = "third_party/blink/public/common/common_export.h"
 
-  export_class_attribute_blink = "PLATFORM_EXPORT"
-  export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
-  export_header_blink = "third_party/blink/renderer/platform/platform_export.h"
+  export_class_attribute_blink = "CORE_EXPORT"
+  export_define_blink = "BLINK_CORE_IMPLEMENTATION=1"
+  export_header_blink = "third_party/blink/renderer/core/core_export.h"
 
   generate_java = true
 }
diff --git a/third_party/blink/public/mojom/tokens/worker_tokens.mojom b/third_party/blink/public/mojom/tokens/worker_tokens.mojom
deleted file mode 100644
index fd79521..0000000
--- a/third_party/blink/public/mojom/tokens/worker_tokens.mojom
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "mojo/public/mojom/base/unguessable_token.mojom";
-
-// These identifiers uniquely represent workers (dedicated/shared/service)
-// across the content and blink layers. It is only intended to be transferred
-// between the browser process and the renderer process hosting the worker.
-// This is a simple wrapper that provides type safety.
-
-struct DedicatedWorkerToken {
-  mojo_base.mojom.UnguessableToken value;
-};
-
-struct SharedWorkerToken {
-  mojo_base.mojom.UnguessableToken value;
-};
-
-struct ServiceWorkerToken {
-  mojo_base.mojom.UnguessableToken value;
-};
diff --git a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
index 3d20f54..ed455c0 100644
--- a/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
+++ b/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
@@ -14,7 +14,6 @@
 import "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_container.mojom";
-import "third_party/blink/public/mojom/tokens/worker_tokens.mojom";
 import "url/mojom/url.mojom";
 
 // The name of the InterfaceProviderSpec in service manifests used by the
@@ -75,7 +74,6 @@
   // Creates a new DedicatedWorkerHost, and requests |browser_interface_broker|
   // to provide the worker access to mojo interfaces.
   CreateWorkerHost(
-      blink.mojom.DedicatedWorkerToken token,
       pending_receiver<blink.mojom.BrowserInterfaceBroker>
           browser_interface_broker) =>
     (network.mojom.CrossOriginEmbedderPolicy parent_coep);
@@ -91,7 +89,6 @@
   // |client| is used for notifying the renderer process of results of worker
   // host creation and script loading.
   CreateWorkerHostAndStartScriptLoad(
-      blink.mojom.DedicatedWorkerToken token,
       url.mojom.Url script_url,
       network.mojom.CredentialsMode credentials_mode,
       blink.mojom.FetchClientSettingsObject
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index 5a970bf..82a64c8 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -54,7 +54,6 @@
     "+services/service_manager/public/mojom",
     "+third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h",
     "+third_party/blink/public/platform",
-    "+third_party/blink/public/mojom/tokens",
     "-third_party/blink/public/web",
     "-third_party/blink/renderer/bindings",
     "+third_party/skia",
diff --git a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
index 20536f98..fa8c65f 100644
--- a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
+++ b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
 
 #include "base/memory/ref_counted.h"
-#include "base/unguessable_token.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
@@ -36,23 +35,12 @@
 
   // Requests the creation of DedicatedWorkerHost in the browser process.
   // For non-PlzDedicatedWorker. This will be removed once PlzDedicatedWorker is
-  // enabled by default. This code is called by Blink so it wants to use the
-  // Blink variant of DedicatedWorker and can't use the non-Blink variant.
-  // TODO(chrisha): Unfortunately, this header is part of the blink_headers
-  //     target, which itself is a dependency of blink Mojom targets, so this
-  //     creates a dependency cycle. To break this cycle the token is passed as
-  //     an untyped UnguessableToken through this interface. The implementation
-  //     of this interface should immediately cast this back to a
-  //     DedicatedWorkerToken! Break this dependency cycle and keep strong
-  //     typing by introducing a non-Mojo concrete type for the token, and use
-  //     Mojo bindings to convert to and from it.
+  // enabled by default.
   virtual void CreateWorkerHostDeprecated(
-      const base::UnguessableToken& dedicated_worker_token,
       base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)>
           callback) = 0;
   // For PlzDedicatedWorker.
   virtual void CreateWorkerHost(
-      const base::UnguessableToken& dedicated_worker_token,
       const blink::WebURL& script_url,
       network::mojom::CredentialsMode credentials_mode,
       const blink::WebFetchClientSettingsObject& fetch_client_settings_object,
diff --git a/third_party/blink/public/web/DEPS b/third_party/blink/public/web/DEPS
index 1dc3dceb..d83977d1 100644
--- a/third_party/blink/public/web/DEPS
+++ b/third_party/blink/public/web/DEPS
@@ -52,6 +52,7 @@
     "+third_party/blink/public/web",
     "+ui/accessibility/ax_enums.mojom-shared.h",
     "+ui/accessibility/ax_event.h",
+    "+ui/accessibility/ax_tree_id.h",
     "+ui/base/ime/mojom/ime_types.mojom-shared.h",
     "+ui/base/ime/mojom/virtual_keyboard_types.mojom-shared.h",
 
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index a6b33cc..728ca88 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -39,6 +39,7 @@
 #include "third_party/blink/public/web/web_frame.h"
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/public/web/web_navigation_params.h"
+#include "ui/accessibility/ax_tree_id.h"
 #include "ui/base/ime/ime_text_span.h"
 #include "v8/include/v8.h"
 
@@ -177,6 +178,12 @@
   // Sets the name of this frame.
   virtual void SetName(const WebString&) = 0;
 
+  // Returns the AXTreeID associated to the current frame. It is tied to the
+  // frame's associated EmbeddingToken, and so it will only be a valid one after
+  // the first time that document has been loaded, and will change whenever the
+  // loaded document changes (e.g. frame navigated to a different document).
+  virtual ui::AXTreeID GetAXTreeID() const = 0;
+
   // Hierarchy ----------------------------------------------------------
 
   // Returns true if the current frame is a provisional frame.
@@ -208,7 +215,8 @@
   // Returns the embedding token for this frame or nullopt if the frame hasn't
   // committed a navigation. This token changes when a new document is committed
   // in this WebLocalFrame.
-  virtual const base::Optional<base::UnguessableToken>& GetEmbeddingToken() = 0;
+  virtual const base::Optional<base::UnguessableToken>& GetEmbeddingToken()
+      const = 0;
 
   // Navigation Ping --------------------------------------------------------
 
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni
index 2a569d9..225dcfd 100644
--- a/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -180,6 +180,7 @@
           "//third_party/blink/renderer/core/events/animation_playback_event_init.idl",
           "//third_party/blink/renderer/core/events/application_cache_error_event.idl",
           "//third_party/blink/renderer/core/events/application_cache_error_event_init.idl",
+          "//third_party/blink/renderer/core/events/before_create_policy_event.idl",
           "//third_party/blink/renderer/core/events/before_unload_event.idl",
           "//third_party/blink/renderer/core/events/clipboard_event.idl",
           "//third_party/blink/renderer/core/events/clipboard_event_init.idl",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 1934fb4..8eca046 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -305,6 +305,7 @@
     "events/animation_event.idl",
     "events/animation_playback_event.idl",
     "events/application_cache_error_event.idl",
+    "events/before_create_policy_event.idl",
     "events/before_unload_event.idl",
     "events/clipboard_event.idl",
     "events/composition_event.idl",
diff --git a/third_party/blink/renderer/core/accessibility/ax_object_cache.h b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
index 17582f95..4ba862b 100644
--- a/third_party/blink/renderer/core/accessibility/ax_object_cache.h
+++ b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -85,6 +85,9 @@
 
   virtual const Element* RootAXEditableElement(const Node*) = 0;
 
+  // Called when aspects of the style (e.g. color, alignment) change.
+  virtual void StyleChanged(LayoutObject*) = 0;
+
   // Called by a node when text or a text equivalent (e.g. alt) attribute is
   // changed.
   virtual void TextChanged(LayoutObject*) = 0;
diff --git a/third_party/blink/renderer/core/animation/README.md b/third_party/blink/renderer/core/animation/README.md
index 60cd133..87e4e14 100644
--- a/third_party/blink/renderer/core/animation/README.md
+++ b/third_party/blink/renderer/core/animation/README.md
@@ -55,7 +55,7 @@
 
 The labels 'from' and 'to' are aliases for '0%' and '100%', respectively.
 Keyframes may specify different property values, and the set of keyframes is not
-required to specify values at 0% or 100% (partial keyframes).  If missing
+required to specify values at 0% or 100% (partial keyframes). If missing
 starting or ending values for a property, a neutral property values is used
 based on the underlying value. In the above example, the redshift animation will
 animate from the current color to red.
@@ -84,7 +84,7 @@
 Changes to the [phase](
 https://www.w3.org/TR/web-animations-1/#animation-effect-phases-and-states)
  of a CSS animation may result in firing one or more [AnimationEvent](
-https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent)s.  Each CSS
+https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent)s. Each CSS
 animation has an associated [AnimationEventDelegate](
 https://cs.chromium.org/search?lang=cc&q=class:AnimationEventDelegate) with an
 [OnEventCondition](
@@ -95,7 +95,7 @@
 https://cs.chromium.org/search?q=file:css_animation.idl) extends the
 [Animation interface](https://cs.chromium.org/search?q=file:animation.idl) to
 include an animationName property, which indicated the name of the keyframes
-rule associated with the animation.  Note that this association may be broken
+rule associated with the animation. Note that this association may be broken
 by interacting with the animation via the web-animation API.
 
 
@@ -129,7 +129,7 @@
 [CalculateTransitionUpdateForProperty](https://cs.chromium.org/search?lang=cc&q=function:CSSAnimations::CalculateTransitionUpdateForProperty)
 for each property. If there is already an active transition for the property
 and the value of the property changes, the transition is retargeted to the new
-end point.  When retargeting an animation, the current position is used as a
+end point. When retargeting an animation, the current position is used as a
 starting point, which is calculated by applying active animations with an
 updated timestamp to the underlying style in [CalculateBeforeChangeStyle](
 https://cs.chromium.org/search?lang=cc&q=function:CSSAnimations::CalculateBeforeChangeStyle
@@ -144,7 +144,7 @@
 Changes to the [phase](
 https://www.w3.org/TR/web-animations-1/#animation-effect-phases-and-states)
 of a CSS transition may result in firing one or more [TransitionEvent](
-https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent)s.  Each CSS
+https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent)s. Each CSS
 transition has an associated [TransitionEventDelegate](
 https://cs.chromium.org/search?lang=cc&q=class:TransitionEventDelegate) with an
 [OnEventCondition](
@@ -198,7 +198,7 @@
 At a fundamental level, the web animation model converts a time value to one or
 more property values. This is true whether we are using a DocumentTimeline
 driven by an AnimationClock, or a ScrollTimeline that converts a scroll position
-to an abstract representation of time.  The same rules also apply for
+to an abstract representation of time. The same rules also apply for
 CSSAnimations and CSSTransitions, which derive from the base Animation class.
 
 The web animation model can be further broken down into two sub-models:
@@ -259,7 +259,7 @@
 pair that bounds the iteration progress. Returning to our example with an
 iteration progress of 0.6 at the 1s mark, we are iterating between the '50%'
 and 'to' keyframes. The relative progress between these frames is
-(0.6 - 0.5) / (1.0 - 0.5) = 0.2.  This value is the input to our
+(0.6 - 0.5) / (1.0 - 0.5) = 0.2. This value is the input to our
 animation-timing-function. The timing function for this keyframe pair
 is 'ease-out', which is equivalent to cubic-bezier(0, 0, 0.58, 1)). Plugging an
 input value of 0.2 into our cubic-bezier function, we get an output of roughly
@@ -273,7 +273,7 @@
 opacity = 0.31 * 0 + (1 - 0.31) * 0.5 = 0.35
 
 The interpolation procedure is less straightforward for non-scalar values
-(especially for transform lists).  Nonetheless, this example provides a good
+(especially for transform lists). Nonetheless, this example provides a good
 overview of the web animation model.
 
 Points of interest in the Blink code base:
@@ -298,10 +298,560 @@
 * [Animation::Update](
 https://cs.chromium.org/search?q=function:blink::Animation::Update):
 Called in response to ticking the animation timeline or to revalidate outdated
-animations.  In addition to applying the web animation model via
+animations. In addition to applying the web animation model via
 UpdateInheritedTime, this method determines if the animation is finished.
 
 
+## Web-animation API
+
+The Web-animation API provides a unified framework for interacting with
+animations regardless of the animation type (creation mechanism). CSS
+animations and transitions can also be manipulated via the API even though not
+created via the Element.animate method. The following sections cover each of
+the JavaScript extensions that build up the web-animation API.
+
+### Animatable
+
+Objects that may be the target of a KeyframeEffect implement the [Animatable][]
+interface. At present, this set of objects is restricted to Element and
+derived classes. Refer to the web-animation section under animation types for a
+description of Element.animate.
+
+[Animatable]: https://drafts.csswg.org/web-animations/#the-animatable-interface-mixin
+
+### Animation
+
+The [Animation interface][] contains methods and attributes for programmatically
+interacting with animations. [Animation object][]s may be created via the
+constructor or the Element.animate method covered previously.
+[Animation object][]s may be queried via a getAnimations call. The query
+retrieves all animations regardless of type and may be used to interact with CSS
+animations or transitions.
+
+The animation API consists of the following attributes and methods:
+
+* **[Animation constructor][]**: This constructor is called regardless of the
+type of animation. The constructor may also be called directly from JavaScript
+to create a web animation, which is particularly useful when a [timeline][]
+other than the [default document timeline][] is being used.
+
+   ```javascript
+   const keyframeEffect = new KeyframeEffect(...);
+   const timeline = new ScrollTimeline(...);
+   const animation = new Animation(keyframeEffect, timeline);
+   // Unlike Element.animate, an animation created directly via the constructor
+   // does not autoplay.
+   animation.play();
+   ```
+
+* **[id attribute][]**: sets or gets an id that can be used to identify the
+animation. These ids are purely informational, but may be used by the developer
+to facilitate bookkeeping or debugging.
+
+* **[effect attribute][]**: gets or sets the [AnimationEffect][] for the
+animation. The algorithm for setting the effect of an animation is outlined in
+[web-animations -- Setting the associated effect of an animation](
+https://drafts.csswg.org/web-animations/#setting-the-associated-effect). A few
+extra steps are required for CSS animations and transitions, which have an
+[AnimationEffect::EventDelegate][] that need to be reattached after the effect
+is updated. Special handling is also required if the new effect is null to
+cancel or finish the CSS animation / transition.
+
+   ```javascript
+   // Clone an animation effect.
+   const animationA = elementA.animate(...);
+   const animationB = elementB.animate(animationA.effect.getKeyframes(),
+                                       animationA.effect.getTiming());
+   ```
+
+* **[readonly timeline attribute][]**: At present Blink only supports fetching
+the associated timeline. Efforts are underway to support setting the timeline as
+well, which is useful for attaching a scroll timeline to an animation created
+via Element.animate. Refer to the [Timelines][] section of the web animation
+spec for more details.
+
+   ```javascript
+   const animation = element.animate(...);
+   assert_equals(animation.timeline, document.timeline);
+   ```
+
+* **[startTime attribute][]**: gets or sets the start time of an animation. The
+start time is unresolved when the animation is paused, idle or play-pending
+(scheduled to play but not yet acked by the client). A running (if not
+play-pending) or finished animation has a resolved start time. The current time
+of an animation is determined from the timeline time, start time and playback
+rate if the animation is not paused or finished. Setting the start time of an
+animation is applied immediately rather than waiting on an ack from the client;
+however, a resulting change in the finished state will not resolve a finished
+promise or queue an onfinish handler until the next [microtask checkpoint][]
+since the state change may be temporary. The setStartTime method is overridden
+for CSSAnimations since calling it may update the animation-play-state property
+by unpausing a CSS animation. Refer to
+[Web-animations -- Setting the start time of an animation](
+https://drafts.csswg.org/web-animations/#setting-the-start-time-of-an-animation)
+for more detail.
+
+   ```javascript
+   const animation = element.animate(...);
+   // The newly created animation is scheduled to play, but the start time is
+   // unresolved until acked by the client agent.
+   assert_true(animation.pending);
+   assert_equals(animation.playState, 'running');
+   assert_false(!!animation.startTime);
+   animation.ready.then(() => {
+     assert_false(animation.pending);
+     assert_times_equal(animation.startTime, document.timeline.currentTime);
+   });
+   ```
+
+   ```javascript
+   const animation = element.animate(...);
+   aniamtion.pause();
+   // The animation is in a pending-paused state.
+   assert_true(animation.pending);
+   assert_equals(animation.playState, 'paused');
+   assert_false(!!animation.startTime);
+   assert_equals(animation.currentTime, 0);
+   // Explicitly setting the start time aborts the pending-pause, and starts the
+   // animation.
+   animation.startTime = document.timeline.currentTime;
+   assert_false(animation.pending);
+   assert_equals(animation.playState, 'running');
+   assert_times_equal(animation.startTime, document.timeline.currentTime);
+   assert_equals(animation.currentTime, 0);
+   ```
+
+* **[currentTime attribute][]**: gets or sets the current time of an animation.
+When setting the current time, either the start time or hold time of the
+animation is updated depending on the play state. The start time is updated for
+a running or finished animation, and the hold time is updated for an idle or
+paused animation. The change is applied immediately and does not wait on an ack
+from the client. Similar to setting the start time, updating the current time
+will not resolve a finished promise or queue an onfinished event until the next
+[microtask checkpoint][] since the state change may be temporary. Refer to
+[Web-animations -- The current time of an animation](
+https://drafts.csswg.org/web-animations/#the-current-time-of-an-animation) and
+[Web-animations -- Setting the current time of an animation](
+https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation)
+for more detail.
+
+   ```javascript
+   const animation = element.animate(...);
+   // Advance to 1000ms mark in the animation. Since the animation is
+   // play-pending the hold time is updated. Once ready, the start time will
+   // be set to align with the hold time.
+   animation.currentTime = 1000;
+   assert_true(animation.pending);
+   assert_equals(animation.playState, 'running');
+   animation.ready.then(() => {
+     assert_false(animation.pending);
+     assert_times_equal(animation.startTime,
+                        document.timeline.currentTime - 1000);
+     assert_times_equals(animation.currentTime, 10000);
+   });
+   ```
+
+* **[playbackRate attribute][]**: gets or sets the playback rate of the
+animation. An animation with a negative value for the playback rate plays in the
+reverse direction. The setter is closely related to the updatePlaybackRate
+method with the difference that with this setter the change takes place
+immediately and does not require an ack from the client. The getter reports the
+active playback rate and not the pending playback rate. These values may differ
+for a brief time interval if using updatePlaybackRate to asynchronously change
+the playback rate. The algorithm for setting the playback rate is covered under
+[web animations -- setting the playback rate on an animation](
+https://drafts.csswg.org/web-animations/#setting-the-playback-rate-of-an-animation)
+in the spec. An additional step in required in Blink to ensure that a composited
+animation is kept in sync with a change to the playback rate and to prevent a
+discontinuity (jump) in the animation. Typically, using updatePlaybackRate is
+preferable to using the setter.
+
+   ```javascript
+   const animation = element.animate(...);
+   assert_equals(animation.playbackRate, 1);
+   animation.playbackRate = -1;
+   // The change to the playback rate is reflected immediately.
+   assert_equals(animation.playbackRate, -1);
+   ```
+
+* **[readonly playState attribute][]**: gets the play state of an animation,
+which may be one of the following: 'idle', 'paused', 'running', or 'finished'.
+At present, the play state in Blink has an extra state called 'pending', which
+is not used in web animations but is still externally referenced. The play state
+is forward looking insofar as a pending-play animation will report running and a
+pending-pause animation will report paused. The pending attribute can be checked
+to disambiguate whether the reported play state reflects the current or the
+scheduled state. The algorithm for determining the play state is outlined in
+[web animations -- play states](
+https://drafts.csswg.org/web-animations/#play-states).
+
+   ```javascript
+   const animation = element.animate(...);
+   // play state is updated even though the animation has not ticked.
+   assert_equals(animation.playState, 'running');
+   animation.pause();
+   assert_equals(animation.playState, 'paused');
+   ```
+
+* **[readonly replaceState attribute][]**: gets the replace state of an
+animation, which may be one of the following: 'active', 'removed', or
+'persisted'. A replaceState of 'active' indicates that the animation is in
+effect, but may be replaced if conditions are satisfied (finished and all
+affected properties are also affected by other finished animations higher in
+composite order). A 'removed' animation is an animation that is finished and
+marked for removal due to being replaceable. A persisted animation is an
+animation that has been explicitly marked for exclusion for the automated
+removal process via the persist method. The procedure for marking and removing
+animations is covered in [web animations - replacing animations](
+https://drafts.csswg.org/web-animations/#replacing-animations). In the Blink
+implementation, identifying which animations are replaceable is done in
+[Animation::IsReplaceable][]. Removal of replaced animations is done in
+[AnimationTimeline::RemoveReplacedAnimations][], which calls
+[Animation::RemoveReplacedAnimation][]. Removal is done during the timeline
+update cycle after animations have ticked and their finished states have been
+updated.
+
+   ```javascript
+   function commitPersistedAnimations() {
+     document.getAnimations().forEach((anim) => {
+       if (anim.playState == ‘finished’ &&
+           anim.replaceState == ‘persisted’) {
+         anim.commitStyles();
+         anim.cancel();
+       }
+     });
+   };
+   ```
+
+* **[readonly pending attribute][]**: gets the pending status of an animation.
+Changes to the play state via the play, pause, and reverse methods do not take
+effect immediately, but instead schedule a task to execute once the
+animation is ready (acked by the client agent). An animation in the 'running'
+playState is pending until it receives a start time. Conversely, a
+pending-pause animation may still have a start-time until the client agent is
+ready to pause the animation. As the play state of a CSS animation may also be
+changed via the animation-play-state property, a style flush is required when
+querying the play state of a CSS animation.
+
+   ```javascript
+   div.style.animation = `fade 1s linear`;
+   const animation = div.getAnimations[0];
+   assert_equals(animation.playState, 'running');
+   assert_true(animation.pending);
+   animation.ready.then(() => {
+     assert_false(animation.pending);
+     // Updating the play state via the animation-play-state property causes
+     // the aniamtion to be pause-pending.
+     div.style.animationPlayState = 'paused';
+     assert_equals(animation.playState, 'paused');
+     assert_true(animation.pending);
+     animation.ready.then(() => {
+       assert_false(animation.pending);
+     });
+   });
+   ````
+
+* **[readonly ready attribute][]**: The ready promise is resolved when
+pending play or paused operations are acked by the client agent. A change that
+requires an ack from the client agent must call
+[Animation::SetCompositorPending][]. The method name is somewhat misleading as
+it applies whether or not the animation is actually run on the compositor.
+The method updates the list of pending animations if required. In turn,
+[PendingAnimations::Update][] updates the list of animations that are waiting
+for a start time, and notifies that the animation is ready if not requiring a
+start time. If all animations needing a start time are main-thread animations,
+they are also marked as ready. If at least one animation is composited, all new
+animations created during the update cycle must wait on the compositor in order
+to properly synchronize the start times. Animations from a previous cycle are
+exempt from start synchronization to guard against plugging up of the animation
+pipeline. Composited animations call
+[PendingAnimations::NotifyCompositorAnimationStarted][] with the start time,
+which in turn calls [Animation::NotifyReady][]. If all animations for an element
+are running on the main thread, then NotifyCompositorAnimationStarted is called
+directly. Again, the method name is somewhat misleading.
+
+   ```javascript
+   const slideAnimation = element.animate(...);
+   const fadeAnimation = element.animate(...);
+   slideAnimation.ready.then(() => {
+     // Synchronize the fade animation to run 1s after the start of the slide
+     // animations.
+     fadeAnimation.startTime = slideAnimation + 1000;
+   })
+   ```
+
+* **[readonly finished attribute][]**:  The finished promise is resolved after
+an animation finishes. Since the finished state may be temporary, the resolution
+is deferred until the next [microtask checkpoint][]. This delay facilitates
+getting consistent results when the ordering of API calls is changed. For
+example, setting the current time to the end time and reversing the direction of
+the animation should not resolve the finished promise. API calls that affect
+current time or play state must update the finished state of the animation. The
+algorithm is outlined in [web animation -- updating the finished state](
+https://drafts.csswg.org/web-animations/#updating-the-finished-state). In
+Blink, updating the finished state and scheduling the microtask is performed in
+[Animation::UpdateFinishedState][]. The microtask is handled in
+[Animation::AsyncFinishMicrotask][]. The finished promise is convenient for
+chaining together animations and for applying style updates.
+
+   ```javascript
+     const animation = element.animate(keyframes,
+                                       { duration: 1000,
+                                         fill: `forwards`
+                                       });
+     animation.finished.then(() => {
+       animation.commitStyles();
+       animation.cancel();
+       // Follow up animation.
+       element.animate(...);
+     });
+   ```
+
+* **[onfinished attribute][]**: gets or sets the onfinished event handler that
+allows the web developer to attach customized JavaScript to run once an
+animation has finished.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     {
+                                       duration: 1000
+                                       fill: 'forwards'
+                                     });
+   animation`.onfinished = () => {
+     animation.commitStyles();
+     animation.cancel();
+   };
+   ```
+
+* **[oncancel attribute][]**: gets or sets the oncancel event handler that
+allows the web developer to attach customized JavaScript to run once an
+animation has been canceled.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     {
+                                       duration: 1000
+                                       fill: 'forwards'
+                                     });
+   animation.oncancel = () => {
+     myTrackedAnimations.remove(animation);
+   };
+   ```
+
+* **[onremove attribute][]**: gets or sets the onremove event handler that
+allows the web developer to attach customized JavaScript to run once an
+animation has been removed.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     {
+                                       duration: 1000
+                                       fill: 'forwards'
+                                     });
+   animation.onremove = () => {
+     animation.commitStyles();
+   };
+   ```
+
+* **[cancel nethod]**: synchronously cancels an animation. This operation will
+reject any pending read or finished promise, cancel any pending play or pause
+task, and queue a cancel event.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     { duration: 1000, fill: 'forwards' });
+   animation.finished.then(() => {
+     assert_unreached();
+   });
+   animation.ready.then(() => {
+     assert_unreached();
+   });
+   animation.currentTime = 500;
+   animation.cancel();
+   assert_equals(animation.currentTime, null);
+   assert_equals(animation.playState, 'idle');
+   assert_false(animation.pending);
+   ```
+
+* **[finish method]**: synchronously updates the current time of the animation
+to be the end time. If playing in the revsere direction, the current time will
+be set to zero. The finished promise is immediately resolved and finish event
+queued.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     { duration: 1000, fill: 'forwards' });
+   animation.finish();
+   assert_equals(animation.currentTime, 1000);
+   assert_equals(animation.playState, 'finished');
+   assert_false(animation.pending);
+   ```
+
+* **[play method]**: schedules an animation to begin playing. The animation
+will resume playing from the hold time. If the hold time is unresolved at the
+time play is called, it will be set to the start or end time depending on the
+direction of the pending playback rate. The initialization procedure is
+altered slightly if a scroll timeline is used instead of a document timeline.
+In this case, the start time is set directly. Nonetheless, an ack is still
+required from the client agent. [Animation::NotifyReady][] calls
+[Animation::CommitPendingPlay][] to run the microtask for syncing the start
+time, resetting the hold time and resolving the ready promise.
+
+   ```javascript
+   const animation = new Animation(kefyrameEffect, document.timeline);
+   animation.play();
+   ```
+
+* **[pause nethod]**: schedules an animation to pause. The pending state remains
+true until acked from the client agent. [Animation::NotifyReady][] calls
+[Animation::CommitPendingPause][] to run the microtask for updating the hold
+time, resetting the start time, and resolving the ready promise.
+
+   ```javascript
+   const animation = element.animate(keyframes,
+                                     { duration: 1000, fill: 'forwards' });
+   button.onclick = () {
+     if (animation.playState == 'running')
+       animation.pause();
+     else
+       animation.play();
+   }
+   ```
+
+* **[updatePlaybackRate nethod]**: sets a pending playback rate for the
+animation. The change does not take effect until acked by the client agent.
+[Animation::NotifyReady][] calls [Animation::CommitPendingPlay][] or
+ [Animation::CommitPendingPause][] depending on the play state. The algorithm
+ is specced in [web animations -- seamlessly updating the playback rate...](
+ https://drafts.csswg.org/web-animations/#seamlessly-updating-the-playback-rate-of-an-animation).
+
+   ```javascript
+   const animation = element.animate(...);
+   // The playback rate is updated even though the animation has not ticked.
+   assert_equals(animation.playbackRate, 1);
+   aniamtion.playbackRate = -1;
+   assert_equals(animation.playbackRate, -1);
+   animation.updatePlayback(-2);
+   // The playback rate is not updated until acked by the client agent.
+   assert_equals(animation.playbackRate, -1);
+   assert_true(animation.pending);
+   animation.ready.then(() => {
+     assert_equals(animation.playbackRate, -2);
+     assert_false(animation.pending);
+   });
+   ```
+
+* **[reverse method]**: reverses the direction of a running animation. The
+change to playback rate does not take effect until acked by the client agent.
+An animation that is not running is started in the reverse direction.
+
+   ```javascript
+   const animation = element.animate(keyframes, { duration: 1000 });
+   animation.reverse();
+   assert_true(animation.pending);
+   // Change to playback rate has not yet taken effect.
+   assert_equals(animation.playbackRate, 1);
+   animation.ready.then(() => {
+      // Snap to the end of the animation when playing in the reverse direction.
+      assert_times_equal(animation.currentTime, 1000);
+      assert_equals(aniamtion.playbackRate(1));
+      assert_false(animation.pending);
+   });
+   ```
+
+* **[persist method]**: marks an animation as persistent such that it is exempt
+from being marked and removed as a replaceable animation.
+
+   ```javascript
+   const animationA = element.animation({ transform: ['scale(1)', 'scale(2)'] },
+                                        { duration: 1000, fill: 'forwards' });
+   const animationB = element.animation({ transform: ['scale(1)', 'scale(2)'] },
+                                        { duration: 1000,
+                                          composite: 'accumulate',
+                                          fill: 'forwards' });
+   animationB.finished.then(() => {
+     // The first animation will be automatically be removed since the second
+     // animation is higher in the composite order and affects the same
+     // property. Removal of the first animation will result in a visual change
+     // since using composite mode 'accumulate' for the second animation. We
+     // can prevent the removal by persisting the first animation.
+     assert_equals(animationA.removeState, 'removed');
+     aniamtionA.persist();
+     // The first animation is once again active.
+     assert_equals(aniamtionA.removeState, 'persist');
+   });
+   ```
+
+* **[commitStyles method]**: adds an inline style to the target element based on
+the current value of the effect stack up to an including the animation.
+
+   ```javascript
+   const animationA = element.animation({ transform: ['scale(1)', 'scale(2)'] },
+                                        { duration: 1000, fill: 'forwards' });
+   const animationB = element.animation({ transform: ['scale(1)', 'scale(2)'] },
+                                        { duration: 1000,
+                                          composite: 'accumulate',
+                                          fill: 'forwards' });
+   animationA.finished.then(() => {
+     // The first animation will be automatically be removed since the second
+     // animation is higher in the composite order and affects the same
+     // property. Removal of the first animation will result in a visual change
+     // since using composite mode 'accumulate' for the second animation.
+     // Rather than persisting the first animation, we can instead call
+     // commitStyles to capture the current state of the animation effect stack
+     // in an inline style.
+     animationA.commitStyles();
+     // element.style is now set to capture the finished state of the first
+     // animation, and it can be safely removed without introducing a visual
+     // change.
+     animationA.cancel();
+   });
+   ```
+
+[Animation interface]: https://drafts.csswg.org/web-animations/#the-animation-interface
+[Animation object]: https://cs.chromium.org/search/?q=class:blink::Animation$
+[timeline]: https://drafts.csswg.org/web-animations/#timelines
+[Timelines]: https://drafts.csswg.org/web-animations/#timelines
+[default document timeline]: https://drafts.csswg.org/web-animations/#the-documents-default-timeline
+[AnimationEffect::EventDelegate]: https://cs.chromium.org/search?lang=cc&q=class:AnimationEffect::EventDelegate$
+[Animation constructor]:  https://cs.chromium.org/search/?q=function:blink::Animation::Animation$
+[id attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::(setI|i)d$
+[effect attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::(setE|e)ffect$
+[readonly timeline attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::timeline$
+[startTime attribute]: https://cs.chromium.org/search/?q=function:blink::(CSS|)Animation::(setS|s)tartTime$
+[currentTime attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::(setC|c)urrentTime$
+[playbackRate attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::(setP|p)laybackRate$
+[readonly playState attribute]:  https://cs.chromium.org/search/?q=function:blink::Animation::playState$
+[readonly replaceState attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::replaceState$
+[readonly pending attribute]: https://cs.chromium.org/search/?q=function:blink::(CSS|)Animation::pending$
+[readonly ready attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::ready$
+[readonly finished attribute]: https://cs.chromium.org/search/?q=function:blink::Animation::finished$
+[onfinished attribute]: https://cs.chromium.org/search/?q=file:animation.h+DEFINE_ATTRIBUTE_EVENT_LISTENER
+[oncancel attribute]: https://cs.chromium.org/search/?q=file:animation.h+DEFINE_ATTRIBUTE_EVENT_LISTENER
+[onremove attribute]: https://cs.chromium.org/search/?q=file:animation.h+DEFINE_ATTRIBUTE_EVENT_LISTENER
+[cancel nethod]: https://cs.chromium.org/search/?q=function:blink::Animation::cancel$
+[finish method]: https://cs.chromium.org/search/?q=function:blink::Animation::finish$
+[play method]: https://cs.chromium.org/search/?q=function:blink::Animation::play$
+[pause nethod]: https://cs.chromium.org/search/?q=function:blink::Animation::pause$
+[updatePlaybackRate nethod]: https://cs.chromium.org/search/?q=function:blink::Animation::updatePlaybackRate$
+[reverse method]: https://cs.chromium.org/search/?q=function:blink::Animation::reverse$
+[persist method]: https://cs.chromium.org/search/?q=function:blink::Animation::persist$
+[commitStyles method]: https://cs.chromium.org/search/?q=function:blink::Animation::commitStyles$
+[Animation::SetCompositorPending]: https://cs.chromium.org/search/?q=function:blink::Animation::SetCompositorPending$
+[PendingAnimations::Update]: https://cs.chromium.org/search/?q=function:blink::PendingAnimations::Update$
+[Animation::UpdateFinishedState]: https://cs.chromium.org/search/?q=function:blink::Animation::UpdateFinishedState$
+[Animation::AsyncFinishMicrotask]: https://cs.chromium.org/search/?q=function:blink::Animation::AsyncFinishMicrotask$
+[PendingAnimations::NotifyCompositorAnimationStarted]: https://cs.chromium.org/search/?q=function:blink::PendingAnimations::NotifyCompositorAnimationStarted$
+[Animation::NotifyReady]: https://cs.chromium.org/search/?q=function:blink::Animation::NotifyReady$
+[Animation::CommitPendingPlay]: https://cs.chromium.org/search/?q=function:blink::Animation::CommitPendingPlay$
+[Animation::CommitPendingPause]: https://cs.chromium.org/search/?q=function:blink::Animation::CommitPendingPause$
+[Animation::IsReplaceable]: https://cs.chromium.org/search/?q=function:blink::Animation::IsReplaceable$
+[AnimationTimeline::RemoveReplacedAnimations]: https://cs.chromium.org/search/?q=function:blink::AnimationTimeline::RemoveReplacedAnimation$
+[Animation::RemoveReplacedAnimation]: https://cs.chromium.org/search/?q=function:blink::Animation::RemoveReplacedAnimation$
+[microtask checkpoint]: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide
+
+TODO: Summarize remaining interfaces that comprise the web-animations-api.
+
 ## Integration with Chromium
 
 The Blink animation engine interacts with Blink/Chrome in the following ways:
@@ -654,10 +1204,6 @@
 
 TODO: Summarize properties and values API.
 
-### Web Animations API
-
-TODO: Summarize Web Animations API.
-
 ### [Animation Worklet](../../modules/animationworklet/README.md)
 
 AnimationWorklet is a new primitive for creating high performance procedural
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index f1b511ee..de597dd 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -146,6 +146,7 @@
                     "events/animation_event.idl",
                     "events/animation_playback_event.idl",
                     "events/application_cache_error_event.idl",
+                    "events/before_create_policy_event.idl",
                     "events/before_unload_event.idl",
                     "events/clipboard_event.idl",
                     "events/composition_event.idl",
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index 28476f5..a5136771 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -235,6 +235,10 @@
   return false;
 }
 
+bool Event::IsBeforeCreatePolicyEvent() const {
+  return false;
+}
+
 bool Event::IsBeforeUnloadEvent() const {
   return false;
 }
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index 5e8d0c99..70de593 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -227,6 +227,7 @@
   virtual bool IsClipboardEvent() const;
   virtual bool IsBeforeTextInsertedEvent() const;
 
+  virtual bool IsBeforeCreatePolicyEvent() const;
   virtual bool IsBeforeUnloadEvent() const;
   virtual bool IsErrorEvent() const;
 
diff --git a/third_party/blink/renderer/core/events/BUILD.gn b/third_party/blink/renderer/core/events/BUILD.gn
index 65e808ff..a2db4ef 100644
--- a/third_party/blink/renderer/core/events/BUILD.gn
+++ b/third_party/blink/renderer/core/events/BUILD.gn
@@ -13,6 +13,8 @@
     "animation_playback_event.h",
     "application_cache_error_event.cc",
     "application_cache_error_event.h",
+    "before_create_policy_event.cc",
+    "before_create_policy_event.h",
     "before_print_event.h",
     "before_text_inserted_event.cc",
     "before_text_inserted_event.h",
diff --git a/third_party/blink/renderer/core/events/before_create_policy_event.cc b/third_party/blink/renderer/core/events/before_create_policy_event.cc
new file mode 100644
index 0000000..2545c7c
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_create_policy_event.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "before_create_policy_event.h"
+
+#include "third_party/blink/renderer/core/event_interface_names.h"
+#include "third_party/blink/renderer/core/event_type_names.h"
+
+namespace blink {
+
+BeforeCreatePolicyEvent* BeforeCreatePolicyEvent::Create(
+    const String& policy_name) {
+  return MakeGarbageCollected<BeforeCreatePolicyEvent>(policy_name);
+}
+
+BeforeCreatePolicyEvent::BeforeCreatePolicyEvent(const String& policy_name)
+    : Event(event_type_names::kBeforecreatepolicy,
+            Bubbles::kNo,
+            Cancelable::kYes),
+      policy_name_(policy_name) {}
+
+BeforeCreatePolicyEvent::~BeforeCreatePolicyEvent() = default;
+
+bool BeforeCreatePolicyEvent::IsBeforeCreatePolicyEvent() const {
+  return true;
+}
+
+const AtomicString& BeforeCreatePolicyEvent::InterfaceName() const {
+  return event_interface_names::kBeforeCreatePolicyEvent;
+}
+
+void BeforeCreatePolicyEvent::Trace(Visitor* visitor) const {
+  Event::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/events/before_create_policy_event.h b/third_party/blink/renderer/core/events/before_create_policy_event.h
new file mode 100644
index 0000000..bb33fb3
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_create_policy_event.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_CREATE_POLICY_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_CREATE_POLICY_EVENT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class CORE_EXPORT BeforeCreatePolicyEvent final : public Event {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static BeforeCreatePolicyEvent* Create(const String&);
+  explicit BeforeCreatePolicyEvent(const String&);
+  ~BeforeCreatePolicyEvent() override;
+
+  bool IsBeforeCreatePolicyEvent() const override;
+
+  void setPolicyName(const String& policy_name) { policy_name_ = policy_name; }
+
+  String policyName() const { return policy_name_; }
+
+  const AtomicString& InterfaceName() const override;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  String policy_name_;
+};
+
+template <>
+struct DowncastTraits<BeforeCreatePolicyEvent> {
+  static bool AllowFrom(const Event& event) {
+    return event.IsBeforeCreatePolicyEvent();
+  }
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_CREATE_POLICY_EVENT_H_
diff --git a/third_party/blink/renderer/core/events/before_create_policy_event.idl b/third_party/blink/renderer/core/events/before_create_policy_event.idl
new file mode 100644
index 0000000..7923b2c
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_create_policy_event.idl
@@ -0,0 +1,10 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/w3c/webappsec-trusted-types/issues/270#issue-579152412
+
+[RuntimeEnabled=TrustedTypeBeforePolicyCreationEvent, Exposed=Window]
+interface BeforeCreatePolicyEvent : Event {
+    attribute DOMString policyName;
+};
\ No newline at end of file
diff --git a/third_party/blink/renderer/core/events/event_target_names.json5 b/third_party/blink/renderer/core/events/event_target_names.json5
index 6d2d0b5d..a462ff2c 100644
--- a/third_party/blink/renderer/core/events/event_target_names.json5
+++ b/third_party/blink/renderer/core/events/event_target_names.json5
@@ -25,6 +25,7 @@
     "TextTrack",
     "TextTrackCue",
     "TextTrackList",
+    "TrustedTypePolicyFactory",
     "VideoTrackList",
     "ApplicationCache",
     "MojoInterfaceInterceptor",
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 0bfeff2..a56c249a 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -46,6 +46,7 @@
     "backgroundfetchsuccess",
     "beforematch",
     "beforecopy",
+    "beforecreatepolicy",
     "beforecut",
     "beforeinput",
     "beforeinstallprompt",
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index ad243c57..eede419 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -769,7 +769,7 @@
   std::string content = WebFrameContentDumper::DumpWebViewAsText(
                             web_view_helper.GetWebView(), 1024)
                             .Utf8();
-  EXPECT_EQ("http://internal.test:0/" + file_name, content);
+  EXPECT_EQ("http://internal.test/" + file_name, content);
 }
 
 TEST_F(WebFrameTest, LocationSetEmptyPort) {
@@ -792,7 +792,7 @@
   std::string content = WebFrameContentDumper::DumpWebViewAsText(
                             web_view_helper.GetWebView(), 1024)
                             .Utf8();
-  EXPECT_EQ("http://internal.test:0/" + file_name, content);
+  EXPECT_EQ("http://internal.test/" + file_name, content);
 }
 
 class EvaluateOnLoadWebFrameClient
diff --git a/third_party/blink/renderer/core/frame/BUILD.gn b/third_party/blink/renderer/core/frame/BUILD.gn
index 9be3456..c59e4c4d 100644
--- a/third_party/blink/renderer/core/frame/BUILD.gn
+++ b/third_party/blink/renderer/core/frame/BUILD.gn
@@ -221,6 +221,7 @@
 
   deps = [
     "//skia",
+    "//ui/accessibility:ax_base",
     "//ui/base/cursor:cursor_base",
     "//ui/base/cursor/mojom:cursor_type_blink",
     "//ui/gfx:geometry_skia",
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 5f49317..637d570 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
@@ -667,6 +667,14 @@
   return GetFrame()->Tree().GetName();
 }
 
+ui::AXTreeID WebLocalFrameImpl::GetAXTreeID() const {
+  const base::Optional<base::UnguessableToken>& embedding_token =
+      GetEmbeddingToken();
+  if (embedding_token && !embedding_token->is_empty())
+    return ui::AXTreeID::FromToken(embedding_token.value());
+  return ui::AXTreeIDUnknown();
+}
+
 void WebLocalFrameImpl::SetName(const WebString& name) {
   GetFrame()->Tree().SetName(name, FrameTree::kReplicate);
 }
@@ -2102,7 +2110,7 @@
 }
 
 const base::Optional<base::UnguessableToken>&
-WebLocalFrameImpl::GetEmbeddingToken() {
+WebLocalFrameImpl::GetEmbeddingToken() const {
   return frame_->GetEmbeddingToken();
 }
 
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 93dacfa..59825ec 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
@@ -116,6 +116,7 @@
   WebContentCaptureClient* ContentCaptureClient() const override;
   WebDocument GetDocument() const override;
   WebString AssignedName() const override;
+  ui::AXTreeID GetAXTreeID() const override;
   void SetName(const WebString&) override;
   bool IsProvisional() const override;
   WebLocalFrameImpl* LocalRoot() override;
@@ -123,7 +124,8 @@
   WebFrame* FindFrameByName(const WebString& name) override;
   void SetEmbeddingToken(
       const base::UnguessableToken& embedding_token) override;
-  const base::Optional<base::UnguessableToken>& GetEmbeddingToken() override;
+  const base::Optional<base::UnguessableToken>& GetEmbeddingToken()
+      const override;
   void SendPings(const WebURL& destination_url) override;
   void StartReload(WebFrameLoadType) override;
   void StartNavigation(const WebURLRequest&) override;
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 65665c91..460a218 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1112,8 +1112,10 @@
   else
     style = To<CSSKeyframeRule>(rule)->style();
 
+  Document* owner_document = page_style_sheet_->OwnerDocument();
   ExecutionContext* execution_context =
-      page_style_sheet_->OwnerDocument()->GetExecutionContext();
+      owner_document ? owner_document->GetExecutionContext() : nullptr;
+
   style->setCSSText(execution_context, text, exception_state);
 
   ReplaceText(source_data->rule_body_range, text, new_range, old_text);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 6e774ae0..fdfbf54 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -2386,10 +2386,17 @@
       }
     }
 
-    if (diff.TextDecorationOrColorChanged() ||
-        style_->InsideLink() != new_style.InsideLink()) {
+    bool background_color_changed =
+        ResolveColor(GetCSSPropertyBackgroundColor()) !=
+        ResolveColor(new_style, GetCSSPropertyBackgroundColor());
+
+    if (diff.TextDecorationOrColorChanged() || background_color_changed ||
+        style_->GetFontDescription() != new_style.GetFontDescription() ||
+        style_->GetWritingDirection() != new_style.GetWritingDirection() ||
+        style_->InsideLink() != new_style.InsideLink() ||
+        style_->VerticalAlign() != new_style.VerticalAlign()) {
       if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
-        cache->TextChanged(this);
+        cache->StyleChanged(this);
     }
 
     if (diff.TransformChanged()) {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
index f0c2493..35106c338 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -400,6 +400,16 @@
     PaintRect(context, *selection_rect_, color);
   }
 
+  // Transposes selection_rect_. Called before we paint vertical selected text
+  // under a rotation transform.
+  void TransposeSelectionRect(const PhysicalOffset& origin) {
+    DCHECK(selection_rect_);
+    selection_rect_->Move(-origin);
+    std::swap(selection_rect_->offset.top, selection_rect_->offset.left);
+    std::swap(selection_rect_->size.width, selection_rect_->size.height);
+    selection_rect_->Move(origin);
+  }
+
   // Paint the selected text only.
   void PaintSelectedText(NGTextPainter& text_painter,
                          unsigned length,
@@ -588,13 +598,8 @@
   base::Optional<GraphicsContextStateSaver> state_saver;
 
   // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
-  // include selection and composition highlights.
-  // Since NGPaintFragment::ComputeLocalSelectionRectForText() returns
-  // PhysicalRect rather than LogicalRect, we should paint selection
-  // before GraphicsContext flip.
-  // TODO(yoichio): Make NGPhysicalTextFragment::LocalRect and
-  // NGPaintFragment::ComputeLocalSelectionRectForText logical so that we can
-  // paint selection in same flipped dimension as NGTextPainter.
+  // include selection and composition highlights. They use physical coordinates
+  // so are painted before GraphicsContext rotation.
   const DocumentMarkerVector& markers_to_paint =
       ComputeMarkersToPaint(node, text_item.IsEllipsis());
   if (paint_info.phase != PaintPhase::kSelectionDragImage &&
@@ -689,6 +694,8 @@
     // Paint only the text that is selected.
     if (!selection->IsSelectionRectComputed())
       selection->ComputeSelectionRect(box_rect.offset);
+    if (!is_horizontal)
+      selection->TransposeSelectionRect(box_rect.offset);
     selection->PaintSelectedText(text_painter, length, text_style, node_id);
   }
 
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc
index 94ce65b..fe9a061 100644
--- a/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -454,9 +454,10 @@
                                                 v8::Local<v8::Value> value) {
   switch (type) {
     case MessageType::kPull:
-      DCHECK(backpressure_promise_);
-      backpressure_promise_->ResolveWithUndefined(script_state_);
-      backpressure_promise_ = nullptr;
+      if (backpressure_promise_) {
+        backpressure_promise_->ResolveWithUndefined(script_state_);
+        backpressure_promise_ = nullptr;
+      }
       return;
 
     case MessageType::kCancel:
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
index 226e675..524a072e 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -9,6 +9,9 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_html.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_script.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_script_url.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/events/before_create_policy_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -17,6 +20,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
 
 namespace blink {
@@ -25,6 +29,16 @@
     const String& policy_name,
     const TrustedTypePolicyOptions* policy_options,
     ExceptionState& exception_state) {
+  if (RuntimeEnabledFeatures::TrustedTypeBeforePolicyCreationEventEnabled()) {
+    DispatchEventResult result =
+        DispatchEvent(*BeforeCreatePolicyEvent::Create(policy_name));
+    if (result != DispatchEventResult::kNotCanceled) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kNotAllowedError,
+          "The policy creation has been canceled.");
+      return nullptr;
+    }
+  }
   if (!GetExecutionContext()) {
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "The document is detached.");
@@ -308,8 +322,16 @@
   }
 }
 
+const AtomicString& TrustedTypePolicyFactory::InterfaceName() const {
+  return event_target_names::kTrustedTypePolicyFactory;
+}
+
+ExecutionContext* TrustedTypePolicyFactory::GetExecutionContext() const {
+  return ExecutionContextClient::GetExecutionContext();
+}
+
 void TrustedTypePolicyFactory::Trace(Visitor* visitor) const {
-  ScriptWrappable::Trace(visitor);
+  EventTargetWithInlineData::Trace(visitor);
   ExecutionContextClient::Trace(visitor);
   visitor->Trace(empty_html_);
   visitor->Trace(empty_script_);
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
index 1ee549d..2f68622 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_TYPE_POLICY_FACTORY_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/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
@@ -22,7 +23,7 @@
 class TrustedTypePolicyOptions;
 
 class CORE_EXPORT TrustedTypePolicyFactory final
-    : public ScriptWrappable,
+    : public EventTargetWithInlineData,
       public ExecutionContextClient {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(TrustedTypePolicyFactory);
@@ -37,6 +38,8 @@
 
   TrustedTypePolicy* defaultPolicy() const;
 
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecreatepolicy, kBeforecreatepolicy)
+
   bool isHTML(ScriptState*, const ScriptValue&);
   bool isScript(ScriptState*, const ScriptValue&);
   bool isScriptURL(ScriptState*, const ScriptValue&);
@@ -68,6 +71,8 @@
   //  relate it to the total number of TT enabled documents.)
   void CountTrustedTypeAssignmentError();
 
+  const AtomicString& InterfaceName() const override;
+  ExecutionContext* GetExecutionContext() const override;
   void Trace(Visitor*) const override;
 
  private:
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
index 5a9cdc3..22c0268 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.idl
@@ -7,7 +7,7 @@
 [
     Exposed=(Window, Worker),
     RuntimeEnabled=TrustedDOMTypes
-] interface TrustedTypePolicyFactory {
+] interface TrustedTypePolicyFactory : EventTarget {
     [RaisesException] TrustedTypePolicy createPolicy(DOMString policyName, TrustedTypePolicyOptions policyOptions);
     readonly attribute TrustedTypePolicy defaultPolicy;
     // All the policy object names that have been created
@@ -24,4 +24,6 @@
     DOMString? getAttributeType(DOMString tagName, DOMString attribute,
         optional DOMString elementNS, optional DOMString attrNs);
     [CallWith=ScriptState] object? getTypeMapping(optional DOMString ns);
+
+    [RuntimeEnabled=TrustedTypeBeforePolicyCreationEvent] attribute EventHandler onbeforecreatepolicy;
 };
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 8082ef3..f00dcd0 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -8,7 +8,6 @@
 
 #include "base/feature_list.h"
 #include "base/optional.h"
-#include "base/unguessable_token.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
@@ -93,8 +92,7 @@
       factory_client_(
           Platform::Current()->CreateDedicatedWorkerHostFactoryClient(
               this,
-              GetExecutionContext()->GetBrowserInterfaceBroker())),
-      token_(base::UnguessableToken::Create()) {
+              GetExecutionContext()->GetBrowserInterfaceBroker())) {
   DCHECK(context->IsContextThread());
   DCHECK(script_request_url_.IsValid());
   DCHECK(context_proxy_);
@@ -195,7 +193,7 @@
     }
 
     factory_client_->CreateWorkerHost(
-        token_.value, script_request_url_, credentials_mode,
+        script_request_url_, credentials_mode,
         WebFetchClientSettingsObject(*outside_fetch_client_settings_object_),
         std::move(blob_url_token));
     // Continue in OnScriptLoadStarted() or OnScriptLoadStartFailed().
@@ -216,7 +214,6 @@
     // asynchronous OnHostCreated call, so we call it directly here.
     // See https://crbug.com/1101603#c8.
     factory_client_->CreateWorkerHostDeprecated(
-        token_.value,
         WTF::Bind([](const network::CrossOriginEmbedderPolicy&) {}));
     OnHostCreated(std::move(blob_url_loader_factory),
                   network::CrossOriginEmbedderPolicy());
@@ -224,7 +221,6 @@
   }
 
   factory_client_->CreateWorkerHostDeprecated(
-      token_.value,
       WTF::Bind(&DedicatedWorker::OnHostCreated, WrapWeakPersistent(this),
                 std::move(blob_url_loader_factory)));
 }
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.h b/third_party/blink/renderer/core/workers/dedicated_worker.h
index 37735a4..8d2f746 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.h
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -11,7 +11,6 @@
 #include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
 #include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h"
 #include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/tokens/worker_tokens.mojom-blink.h"
 #include "third_party/blink/public/platform/web_dedicated_worker.h"
 #include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -96,12 +95,6 @@
 
   void DispatchErrorEventForScriptFetchFailure();
 
-  // Returns a unique identifier for this worker, shared between the browser
-  // process and this renderer. This is generated in the renderer process when
-  // the worker is created, and it is subsequently communicated to the browser
-  // process.
-  const mojom::blink::DedicatedWorkerToken& GetToken() const { return token_; }
-
   DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage)
 
   void ContextLifecycleStateChanged(mojom::FrameLifecycleState state) override;
@@ -157,10 +150,6 @@
 
   // Whether the worker is frozen due to a call from this context.
   bool requested_frozen_ = false;
-
-  // The unique identifier for this DedicatedWorker. This is created in the
-  // renderer process, and passed to the browser.
-  mojom::blink::DedicatedWorkerToken token_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index b7a85b1..9bb28ed 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -957,6 +957,30 @@
   relation_cache_->UpdateReverseRelations(relation_source, target_ids);
 }
 
+void AXObjectCacheImpl::StyleChanged(LayoutObject* layout_object) {
+  // There is a ton of style change notifications coming from newly-opened
+  // calendar popups for pickers. Solving that problem is what inspired the
+  // approach below, which is likely true for all elements.
+  //
+  // If we don't know about an object, then its style did not change as far as
+  // we (and ATs) are concerned. For this reason, don't call GetOrCreate.
+  AXObject* obj = Get(layout_object);
+  if (!obj)
+    return;
+
+  DCHECK(!obj->IsDetached());
+
+  // If the foreground or background color on an item inside a container which
+  // supports selection changes, it can be the result of the selection changing
+  // as well as the container losing focus. We handle these notifications via
+  // their state changes, so no need to mark them dirty here.
+  AXObject* parent = obj->ParentObjectUnignored();
+  if (parent && ui::IsContainerWithSelectableChildren(parent->RoleValue()))
+    return;
+
+  MarkAXObjectDirty(obj, false);
+}
+
 void AXObjectCacheImpl::TextChanged(Node* node) {
   if (!node)
     return;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index 0d3b2503..b98c791 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -107,6 +107,9 @@
 
   const Element* RootAXEditableElement(const Node*) override;
 
+  // Called when aspects of the style (e.g. color, alignment) change.
+  void StyleChanged(LayoutObject*) override;
+
   // Called by a node when text or a text equivalent (e.g. alt) attribute is
   // changed.
   void TextChanged(LayoutObject*) override;
diff --git a/third_party/blink/renderer/modules/peerconnection/DEPS b/third_party/blink/renderer/modules/peerconnection/DEPS
index 5b414fb5..7e95dd6 100644
--- a/third_party/blink/renderer/modules/peerconnection/DEPS
+++ b/third_party/blink/renderer/modules/peerconnection/DEPS
@@ -11,13 +11,13 @@
 
     "+base/hash/md5.h",
     "+base/lazy_instance.h",
-    # TODO(crbug.com/787254): Remove the use of base::MessageLoopCurrent.
-    "+base/message_loop/message_loop_current.h",
     "+base/power_monitor/power_observer.h",
     # TODO(crbug.com/787254): Replace base::SequenceChecker by base::ThreadChecker.
     "+base/sequence_checker.h",
     # TODO(crbug.com/787254): Replace StringPrintf uses here.
     "+base/strings/stringprintf.h",
+    # TODO(crbug.com/787254): Remove the use of base::CurrentThread.
+    "+base/task/current_thread.h",
     "+base/threading/thread.h",
     "+base/values.h",
     "+crypto/openssl_util.h",
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
index a6c08432..ea3c51fe 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -180,7 +180,7 @@
   webrtc::DisableRtcUseH264();
 #endif  // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
 
-  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+  base::CurrentThread::Get()->AddDestructionObserver(this);
   // To allow sending to the signaling/worker threads.
   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
   jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
index 3029b4a..7092f910 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
@@ -6,8 +6,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -45,7 +45,7 @@
 
 // Object factory for RTC PeerConnections.
 class MODULES_EXPORT PeerConnectionDependencyFactory
-    : base::MessageLoopCurrent::DestructionObserver {
+    : base::CurrentThread::DestructionObserver {
  public:
   ~PeerConnectionDependencyFactory() override;
 
@@ -131,7 +131,7 @@
   void EnsureWebRtcAudioDeviceImpl();
 
  private:
-  // Implement base::MessageLoopCurrent::DestructionObserver.
+  // Implement base::CurrentThread::DestructionObserver.
   // This makes sure the libjingle PeerConnectionFactory is released before
   // the renderer message loop is destroyed.
   void WillDestroyCurrentMessageLoop() override;
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.cc b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
index 1fcb529..ff2c4bb 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis.cc
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -58,7 +58,7 @@
     // TODO(crbug/811929): Consider moving this logic into the Android-
     // specific backend implementation.
 #else
-    synthesis->InitializeMojomSynthesis();
+    ignore_result(synthesis->TryEnsureMojomSynthesis());
 #endif
   }
   return synthesis;
@@ -90,7 +90,7 @@
 
 const HeapVector<Member<SpeechSynthesisVoice>>& SpeechSynthesis::getVoices() {
   // Kick off initialization here to ensure voice list gets populated.
-  InitializeMojomSynthesisIfNeeded();
+  ignore_result(TryEnsureMojomSynthesis());
   return voice_list_;
 }
 
@@ -143,24 +143,27 @@
   // fire events on them asynchronously.
   utterance_queue_.clear();
 
-  InitializeMojomSynthesisIfNeeded();
-  mojom_synthesis_->Cancel();
+  if (mojom::blink::SpeechSynthesis* mojom_synthesis =
+          TryEnsureMojomSynthesis())
+    mojom_synthesis->Cancel();
 }
 
 void SpeechSynthesis::pause() {
   if (is_paused_)
     return;
 
-  InitializeMojomSynthesisIfNeeded();
-  mojom_synthesis_->Pause();
+  if (mojom::blink::SpeechSynthesis* mojom_synthesis =
+          TryEnsureMojomSynthesis())
+    mojom_synthesis->Pause();
 }
 
 void SpeechSynthesis::resume() {
   if (!CurrentSpeechUtterance())
     return;
 
-  InitializeMojomSynthesisIfNeeded();
-  mojom_synthesis_->Resume();
+  if (mojom::blink::SpeechSynthesis* mojom_synthesis =
+          TryEnsureMojomSynthesis())
+    mojom_synthesis->Resume();
 }
 
 void SpeechSynthesis::DidStartSpeaking(SpeechSynthesisUtterance* utterance) {
@@ -220,8 +223,8 @@
   utterance->SetStartTime(millis / 1000.0);
   is_paused_ = false;
 
-  InitializeMojomSynthesisIfNeeded();
-  utterance->Start(this);
+  if (TryEnsureMojomSynthesis())
+    utterance->Start(this);
 }
 
 void SpeechSynthesis::HandleSpeakingCompleted(
@@ -339,21 +342,17 @@
       GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
 }
 
-void SpeechSynthesis::InitializeMojomSynthesis() {
-  DCHECK(!mojom_synthesis_.is_bound());
+mojom::blink::SpeechSynthesis* SpeechSynthesis::TryEnsureMojomSynthesis() {
+  if (mojom_synthesis_.is_bound())
+    return mojom_synthesis_.get();
 
   // The frame could be detached. In that case, calls on mojom_synthesis_ will
   // just get dropped. That's okay and is simpler than having to null-check
   // mojom_synthesis_ before each use.
   ExecutionContext* context = GetExecutionContext();
 
-  if (!context) {
-    // Mimic the LocalDOMWindow::GetTaskRunner code that uses the current
-    // task runner when frames are detached.
-    ignore_result(mojom_synthesis_.BindNewPipeAndPassReceiver(
-        Thread::Current()->GetTaskRunner()));
-    return;
-  }
+  if (!context)
+    return nullptr;
 
   auto receiver = mojom_synthesis_.BindNewPipeAndPassReceiver(
       context->GetTaskRunner(TaskType::kMiscPlatformAPI));
@@ -362,11 +361,7 @@
 
   mojom_synthesis_->AddVoiceListObserver(receiver_.BindNewPipeAndPassRemote(
       context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
-}
-
-void SpeechSynthesis::InitializeMojomSynthesisIfNeeded() {
-  if (!mojom_synthesis_.is_bound())
-    InitializeMojomSynthesis();
+  return mojom_synthesis_.get();
 }
 
 const AtomicString& SpeechSynthesis::InterfaceName() const {
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.h b/third_party/blink/renderer/modules/speech/speech_synthesis.h
index 2a14b0c..685acfd3 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis.h
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -125,8 +125,7 @@
 
   void SetMojomSynthesisForTesting(
       mojo::PendingRemote<mojom::blink::SpeechSynthesis>);
-  void InitializeMojomSynthesis();
-  void InitializeMojomSynthesisIfNeeded();
+  mojom::blink::SpeechSynthesis* TryEnsureMojomSynthesis();
 
   HeapMojoReceiver<mojom::blink::SpeechSynthesisVoiceListObserver,
                    SpeechSynthesis>
diff --git a/third_party/blink/renderer/platform/mojo/DEPS b/third_party/blink/renderer/platform/mojo/DEPS
index 771f0eb..2748153 100644
--- a/third_party/blink/renderer/platform/mojo/DEPS
+++ b/third_party/blink/renderer/platform/mojo/DEPS
@@ -7,10 +7,10 @@
 
     # Dependencies.
     "+base/containers/span.h",
-    "+base/message_loop/message_loop_current.h",
     "+base/observer_list.h",
     "+base/strings/latin1_string_conversions.h",
     "+base/strings/string16.h",
+    "+base/task/current_thread.h",
     "+mojo/public/cpp/base/time_mojom_traits.h",
     "+mojo/public/mojom/base/string16.mojom-blink.h",
     "+skia/public/mojom/bitmap_skbitmap_mojom_traits.h",
diff --git a/third_party/blink/renderer/platform/mojo/mojo_helper.h b/third_party/blink/renderer/platform/mojo/mojo_helper.h
index 826e6769..cf9b36b 100644
--- a/third_party/blink/renderer/platform/mojo/mojo_helper.h
+++ b/third_party/blink/renderer/platform/mojo/mojo_helper.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_MOJO_HELPER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_MOJO_HELPER_H_
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 
 namespace blink {
 
@@ -14,7 +14,7 @@
 // TODO(leonhsl): http://crbug.com/660274 Remove this API by ensuring
 // a message loop before calling blink::initialize().
 inline bool CanInitializeMojo() {
-  return base::MessageLoopCurrent::IsSet();
+  return base::CurrentThread::IsSet();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index a7c53b9..c4dccfb 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1841,6 +1841,10 @@
       status: "stable",
     },
     {
+      name: "TrustedTypeBeforePolicyCreationEvent",
+      status: "experimental",
+    },
+    {
       name: "TrustTokens",
       origin_trial_feature_name: "TrustTokens",
       origin_trial_allows_third_party: true,
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.cc b/third_party/blink/renderer/platform/weborigin/kurl.cc
index 4065b75..154e4e18 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -471,11 +471,6 @@
   while (value[port_start] == '0' && port_start < port_end - 1)
     ++port_start;
 
-  // Required for backwards compat.
-  // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23463
-  if (port_start == port_end)
-    return "0";
-
   return value.Substring(port_start, port_end - port_start);
 }
 
@@ -518,8 +513,9 @@
   url::Replacements<char> replacements;
   replacements.SetHost(CharactersOrEmpty(host_utf8),
                        url::Component(0, host_utf8.size()));
-  replacements.SetPort(CharactersOrEmpty(port_utf8),
-                       url::Component(0, port_utf8.size()));
+  if (port_utf8.size())
+    replacements.SetPort(CharactersOrEmpty(port_utf8),
+                         url::Component(0, port_utf8.size()));
   ReplaceComponents(replacements);
 }
 
@@ -533,7 +529,8 @@
 
 void KURL::SetPort(const String& port) {
   String parsed_port = ParsePortFromStringPosition(port, 0);
-  SetPort(parsed_port.ToUInt());
+  if (!parsed_port.IsEmpty())
+    SetPort(parsed_port.ToUInt());
 }
 
 void KURL::SetPort(uint16_t port) {
diff --git a/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
index f1d7bcf8..0f646a66 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl_test.cc
+++ b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -979,14 +979,14 @@
     {"0", 0, 0, PortIsValid::kAlways},
     {"1", 1, 1, PortIsValid::kAlways},
     {"00000000000000000000000000000000000443", 443, 443, PortIsValid::kAlways},
-    {"+80", 0, 0, PortIsValid::kInSetHostAndPort},
-    {"-80", 0, 0, PortIsValid::kInSetHostAndPort},
+    {"+80", 0, 8888, PortIsValid::kInSetHostAndPort},
+    {"-80", 0, 8888, PortIsValid::kInSetHostAndPort},
     {"443e0", 0, 443, PortIsValid::kInSetHostAndPort},
     {"0x80", 0, 0, PortIsValid::kInSetHostAndPort},
     {"8%30", 0, 8, PortIsValid::kInSetHostAndPort},
-    {" 443", 0, 0, PortIsValid::kInSetHostAndPort},
+    {" 443", 0, 8888, PortIsValid::kInSetHostAndPort},
     {"443 ", 0, 443, PortIsValid::kInSetHostAndPort},
-    {":443", 0, 0, PortIsValid::kInSetHostAndPort},
+    {":443", 0, 8888, PortIsValid::kInSetHostAndPort},
     {"65535", 65535, 65535, PortIsValid::kAlways},
     {"65534", 65534, 65534, PortIsValid::kAlways},
     {"65536", 0, 0, PortIsValid::kInSetPort},
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index d917228..5bf12d3 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -462,6 +462,7 @@
             'ui::AXEventIntent',
             'ui::AXNodeData',
             'ui::IsDialog',
+            'ui::IsContainerWithSelectableChildren',
             'ax::mojom::BoolAttribute',
             'ax::mojom::HasPopup',
             'ax::mojom::State',
@@ -629,6 +630,21 @@
     },
     {
         'paths':
+        ['third_party/blink/renderer/core/frame/web_local_frame_impl.cc'],
+        'allowed': [
+            'ui::AXTreeID',
+            'ui::AXTreeIDUnknown',
+        ],
+    },
+    {
+        'paths':
+        ['third_party/blink/renderer/core/frame/web_local_frame_impl.h'],
+        'allowed': [
+            'ui::AXTreeID',
+        ],
+    },
+    {
+        'paths':
         ['third_party/blink/renderer/core/fileapi/file_reader_loader.cc'],
         'allowed': [
             'net::ERR_FILE_NOT_FOUND',
@@ -1046,14 +1062,14 @@
             'base::LazyInstance',
             'base::Lock',
             # TODO(crbug.com/787254): Remove base::BindOnce, base::Unretained,
-            # base::Passed, base::Closure, base::MessageLoopCurrent,
+            # base::Passed, base::Closure, base::CurrentThread,
             # base::RetainedRef, base::EndsWith and base::CompareCase.
             'base::Bind.*',
             'base::Closure',
             'base::CompareCase',
             'base::EndsWith',
             'base::MD5.*',
-            'base::MessageLoopCurrent',
+            'base::CurrentThread',
             'base::Passed',
             'base::PowerObserver',
             'base::RetainedRef',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5ec7e1d..8ac0122 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -205,6 +205,7 @@
 
 crbug.com/1011060 virtual/gpu/fast/canvas/bug382588.html [ Pass Failure ]
 crbug.com/1011060 virtual/gpu/fast/canvas/canvas-lost-gpu-context.html [ Pass Failure Crash ]
+crbug.com/1106590 virtual/gpu/fast/canvas/canvas-path-non-invertible-transform.html [ Pass Crash ]
 
 crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform-2.html [ Pass Crash ]
 crbug.com/974720 [ Mac10.13 ] virtual/text-antialias/firstline/capitalize-transform.html [ Pass Crash ]
@@ -6351,7 +6352,7 @@
 crbug.com/1046784 http/tests/devtools/file-system-project.js [ Pass Timeout ]
 crbug.com/1046784 http/tests/devtools/bindings/navigator-frame-attach-detach.js [ Pass Timeout ]
 crbug.com/1046784 http/tests/devtools/forced-layout-in-microtask.js [ Pass Timeout ]
-crbug.com/1046784 http/tests/devtools/application-panel/resources-panel-iframe-idb.js [ Pass Failure Timeout ]
+crbug.com/1046784 http/tests/devtools/application-panel/resources-panel-iframe-idb.js [ Pass Timeout ]
 crbug.com/1046784 http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js [ Pass Timeout ]
 crbug.com/1046784 http/tests/inspector-protocol/service-worker/target-reloaded-after-crash.js [ Pass Timeout ]
 crbug.com/1046784 http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Pass Timeout ]
@@ -6824,7 +6825,6 @@
 crbug.com/1010170 media/video-played-reset.html [ Pass Failure ]
 
 #Sheriff 2020-06-30
-crbug.com/1099657 [ Mac10.13 ] virtual/threaded-no-composited-antialiasing/animations/svg-attribute-interpolation/svg-d-interpolation.html [ Pass Failure ]
 crbug.com/1100786 [ Mac10.10 ] fast/scroll-snap/snaps-after-touchpad-scrolling.html [ Failure ]
 crbug.com/1100786 [ Mac10.10 ] storage/indexeddb/transaction-active-flag.html [ Timeout ]
 
@@ -6872,16 +6872,8 @@
 
 crbug.com/1104381 fast/hidpi/image-srcset-change-resource-dpr.html [ Pass Failure ]
 
-# Temporarily disable to land DevTools changes
-crbug.com/1101262 http/tests/devtools/application-panel/resources-panel-on-navigation.js [ Pass Failure ]
-crbug.com/1101262 http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Pass Failure ]
-crbug.com/1101262 http/tests/devtools/application-panel/resources-panel-selection-on-reload.js [ Pass Failure ]
-crbug.com/1101262 http/tests/devtools/application-panel/resources-panel-websql.js [ Pass Failure ]
-crbug.com/1101262 http/tests/devtools/resource-tree/resource-tree-non-unique-url.js [ Pass Failure ]
-
 # Temporarily disable tests to allow fixing of devtools path escaping
 crbug.com/1094436 http/tests/devtools/overrides/project-added-with-existing-files-bind.js [ Pass Timeout ]
 crbug.com/1094436 http/tests/devtools/persistence/automapping-urlencoded-paths.js [ Pass Failure ]
 crbug.com/1094436 http/tests/devtools/sources/debugger-ui/snippet-edit-breakpoint.js [ Pass Timeout ]
 crbug.com/1094436 http/tests/devtools/sources/debugger/navigator-view.js [ Pass Failure Crash ]
-
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/trusted-types.tentative.idl b/third_party/blink/web_tests/external/wpt/interfaces/trusted-types.tentative.idl
index f2318d6..4e469c1 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/trusted-types.tentative.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/trusted-types.tentative.idl
@@ -28,7 +28,7 @@
 [
   Exposed=(Window, Worker),
   SecureContext
-] interface TrustedTypePolicyFactory {
+] interface TrustedTypePolicyFactory : EventTarget {
     TrustedTypePolicy createPolicy(DOMString policyName, optional TrustedTypePolicyOptions policyOptions = {});
     // All the policy object names that have been created
 };
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-blocking.html b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-blocking.html
new file mode 100644
index 0000000..6ae71b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-blocking.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types *">
+
+<body>
+<script>
+
+  test(t => {
+    event_listener = (e) => {
+      assert_equals(e.policyName, "default");
+      e.preventDefault(); // don't let this policy be created.
+    };
+    trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+    assert_throws_dom("NotAllowedError", () => trustedTypes.createPolicy("default", {}));
+  }, 'Block Trusted Type policy creation by event listener.');
+
+  test(t => {
+    let flag = false;
+    event_listener = (e) => {
+      assert_equals(e.policyName, "myPolicy");
+      flag = true;
+    };
+    trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+    trustedTypes.createPolicy("myPolicy", {});
+    assert_equals(flag, true);
+  }, 'Trusted Type policy creation.');
+
+  test(t => {
+    event_listener = (e) => {
+      if (e.policyName === "default")
+        e.preventDefault();
+    };
+    trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+    assert_throws_dom("NotAllowedError", () => trustedTypes.createPolicy("default", {}));
+    trustedTypes.createPolicy("newPolicy", {});
+  }, 'Block only default Trusted Type policy creation.');
+
+  test(t => {
+    event_listener = (e) => {
+      assert_unreached();
+    };
+    trustedTypes.createPolicy("test", {});
+    trustedTypes.addEventListener('beforecreatepolicy', event_listener, {once:true});
+  }, 'Policy creation called before addEventListener function will not reached the listener.');
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
index c29cdee3..392c091 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 260 tests; 69 PASS, 191 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 260 tests; 71 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setting protocol with leading U+0000 (https:)
 PASS Setting protocol with U+0000 before inserted colon (https:)
 PASS Setting username with leading U+0000 (https:)
@@ -14,7 +14,7 @@
 FAIL Setting hostname with middle U+0000 (https:) assert_equals: property expected "host" but got ""
 FAIL Setting host with trailing U+0000 (https:) assert_equals: property expected "host:8000" but got ":0"
 FAIL Setting hostname with trailing U+0000 (https:) assert_equals: property expected "host" but got ""
-FAIL Setting port with leading U+0000 (https:) assert_equals: property expected "8000" but got "0"
+PASS Setting port with leading U+0000 (https:)
 PASS Setting port with middle U+0000 (https:)
 PASS Setting port with trailing U+0000 (https:)
 FAIL Setting pathname with leading U+0000 (https:) assert_equals: property expected "/%00test" but got ""
@@ -40,7 +40,7 @@
 FAIL Setting hostname with middle U+0009 (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+0009 (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+0009 (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+0009 (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+0009 (https:)
 FAIL Setting pathname with leading U+0009 (https:) assert_equals: property expected "/test" but got "/%09test"
@@ -66,7 +66,7 @@
 FAIL Setting hostname with middle U+000A (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+000A (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+000A (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+000A (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+000A (https:)
 FAIL Setting pathname with leading U+000A (https:) assert_equals: property expected "/test" but got "/%0Atest"
@@ -92,7 +92,7 @@
 FAIL Setting hostname with middle U+000D (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+000D (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+000D (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+000D (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+000D (https:)
 FAIL Setting pathname with leading U+000D (https:) assert_equals: property expected "/test" but got "/%0Dtest"
@@ -118,7 +118,7 @@
 FAIL Setting hostname with middle U+001F (https:) assert_equals: property expected "te\x1fst" but got ""
 FAIL Setting host with trailing U+001F (https:) assert_equals: property expected "test\x1f:8000" but got ":0"
 FAIL Setting hostname with trailing U+001F (https:) assert_equals: property expected "test\x1f" but got ""
-FAIL Setting port with leading U+001F (https:) assert_equals: property expected "8000" but got "0"
+PASS Setting port with leading U+001F (https:)
 PASS Setting port with middle U+001F (https:)
 PASS Setting port with trailing U+001F (https:)
 PASS Setting pathname with leading U+001F (https:)
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
index c29cdee3..392c091 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 260 tests; 69 PASS, 191 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 260 tests; 71 PASS, 189 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setting protocol with leading U+0000 (https:)
 PASS Setting protocol with U+0000 before inserted colon (https:)
 PASS Setting username with leading U+0000 (https:)
@@ -14,7 +14,7 @@
 FAIL Setting hostname with middle U+0000 (https:) assert_equals: property expected "host" but got ""
 FAIL Setting host with trailing U+0000 (https:) assert_equals: property expected "host:8000" but got ":0"
 FAIL Setting hostname with trailing U+0000 (https:) assert_equals: property expected "host" but got ""
-FAIL Setting port with leading U+0000 (https:) assert_equals: property expected "8000" but got "0"
+PASS Setting port with leading U+0000 (https:)
 PASS Setting port with middle U+0000 (https:)
 PASS Setting port with trailing U+0000 (https:)
 FAIL Setting pathname with leading U+0000 (https:) assert_equals: property expected "/%00test" but got ""
@@ -40,7 +40,7 @@
 FAIL Setting hostname with middle U+0009 (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+0009 (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+0009 (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+0009 (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+0009 (https:)
 FAIL Setting pathname with leading U+0009 (https:) assert_equals: property expected "/test" but got "/%09test"
@@ -66,7 +66,7 @@
 FAIL Setting hostname with middle U+000A (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+000A (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+000A (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+000A (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+000A (https:)
 FAIL Setting pathname with leading U+000A (https:) assert_equals: property expected "/test" but got "/%0Atest"
@@ -92,7 +92,7 @@
 FAIL Setting hostname with middle U+000D (https:) assert_equals: property expected "test" but got ""
 FAIL Setting host with trailing U+000D (https:) assert_equals: property expected "test:8000" but got ":0"
 FAIL Setting hostname with trailing U+000D (https:) assert_equals: property expected "test" but got ""
-FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "0"
+FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "8000"
 FAIL Setting port with middle U+000D (https:) assert_equals: property expected "9000" but got "90"
 PASS Setting port with trailing U+000D (https:)
 FAIL Setting pathname with leading U+000D (https:) assert_equals: property expected "/test" but got "/%0Dtest"
@@ -118,7 +118,7 @@
 FAIL Setting hostname with middle U+001F (https:) assert_equals: property expected "te\x1fst" but got ""
 FAIL Setting host with trailing U+001F (https:) assert_equals: property expected "test\x1f:8000" but got ":0"
 FAIL Setting hostname with trailing U+001F (https:) assert_equals: property expected "test\x1f" but got ""
-FAIL Setting port with leading U+001F (https:) assert_equals: property expected "8000" but got "0"
+PASS Setting port with leading U+001F (https:)
 PASS Setting port with middle U+001F (https:)
 PASS Setting port with trailing U+001F (https:)
 PASS Setting pathname with leading U+001F (https:)
diff --git a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host-expected.txt b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host-expected.txt
index ce26d28e..d5c484144 100644
--- a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host-expected.txt
@@ -13,13 +13,13 @@
 Set default port
 PASS a.href is 'https://www.otherdomain.com/path/'
 Set host with invalid port
-PASS a.href is 'https://www.otherdomain.com:0/path/'
+PASS a.href is 'https://www.otherdomain.com:8080/path/'
 Set host with letters in port number
 PASS a.href is 'https://www.otherdomain.com:44/path/'
 Leading space in port number
-PASS a.href is 'https://www.otherdomain.com:0/path/'
+PASS a.href is 'https://www.otherdomain.com:8080/path/'
 Colon without port number
-PASS a.href is 'https://www.otherdomain.com:0/path/'
+PASS a.href is 'https://www.otherdomain.com:8080/path/'
 Set host to null
 PASS a.href is 'https://null:8080/path/'
 Set host to empty string
diff --git a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host.html b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host.html
index b6b923f99..1442181 100644
--- a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host.html
+++ b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-host.html
@@ -42,7 +42,7 @@
 debug("Set host with invalid port");
 a.href = "https://www.mydomain.com:8080/path/";
 a.host = "www.otherdomain.com:invalid";
-shouldBe("a.href", "'https://www.otherdomain.com:0/path/'");
+shouldBe("a.href", "'https://www.otherdomain.com:8080/path/'");
 
 // Firefox 3.5.2 rejects a port that contains non-digits.
 debug("Set host with letters in port number");
@@ -54,13 +54,13 @@
 debug("Leading space in port number");
 a.href = "https://www.mydomain.com:8080/path/";
 a.host = "www.otherdomain.com: 443";
-shouldBe("a.href", "'https://www.otherdomain.com:0/path/'");
+shouldBe("a.href", "'https://www.otherdomain.com:8080/path/'");
 
 // Firefox 3.5.2 removed the port, clearly against the spec .
 debug("Colon without port number");
 a.href = "https://www.mydomain.com:8080/path/";
 a.host = "www.otherdomain.com:";
-shouldBe("a.href", "'https://www.otherdomain.com:0/path/'");
+shouldBe("a.href", "'https://www.otherdomain.com:8080/path/'");
 
 debug("Set host to null");
 a.href = "https://www.mydomain.com:8080/path/";
diff --git a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port-expected.txt b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port-expected.txt
index 1ccd6b4..e084f9b 100644
--- a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port-expected.txt
@@ -11,11 +11,11 @@
 Set port to non-number
 PASS a.href is 'https://www.mydomain.com:4/path/testurl.html?key=value'
 Set port to null
-PASS a.href is 'https://www.mydomain.com:0/path/testurl.html?key=value'
+PASS a.href is 'https://www.mydomain.com:8080/path/testurl.html?key=value'
 Set port to empty string
 PASS a.href is 'https://www.mydomain.com/path/testurl.html?key=value'
 Set port to undefined
-PASS a.href is 'https://www.mydomain.com:0/path/testurl.html?key=value'
+PASS a.href is 'https://www.mydomain.com:8080/path/testurl.html?key=value'
 Set port to URL with foo: protocol
 FAIL a.href should be foo://bar:50/. Was foo://bar/.
 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port.html b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port.html
index 6149ddc5..c18dfc54 100644
--- a/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port.html
+++ b/third_party/blink/web_tests/fast/dom/HTMLAnchorElement/set-href-attribute-port.html
@@ -34,7 +34,7 @@
 debug("Set port to null");
 a.href = "https://www.mydomain.com:8080/path/testurl.html?key=value";
 a.port = null;
-shouldBe("a.href", "'https://www.mydomain.com:0/path/testurl.html?key=value'");
+shouldBe("a.href", "'https://www.mydomain.com:8080/path/testurl.html?key=value'");
 
 // Firefox 3.5.2 does not accept the port if it is null.
 debug("Set port to empty string");
@@ -45,7 +45,7 @@
 debug("Set port to undefined");
 a.href = "https://www.mydomain.com:8080/path/testurl.html?key=value";
 a.port = undefined;
-shouldBe("a.href", "'https://www.mydomain.com:0/path/testurl.html?key=value'");
+shouldBe("a.href", "'https://www.mydomain.com:8080/path/testurl.html?key=value'");
 
 // Firefox 3.5.2 does not allow setting the port on a URL with protocol foo: .
 debug("Set port to URL with foo: protocol");
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
index 1eeaa13..76ac7571 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -116,6 +116,7 @@
 PASS window.cached_styleMedia.type is ''
 PASS window.cached_toolbar.visible is false
 PASS window.cached_trustedTypes.defaultPolicy is null
+PASS window.cached_trustedTypes.onbeforecreatepolicy is null
 PASS window.cached_visualViewport.height is 0
 PASS window.cached_visualViewport.offsetLeft is 0
 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
index bb682a4..fc6db281 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -116,6 +116,7 @@
 PASS window.cached_styleMedia.type is ''
 PASS window.cached_toolbar.visible is false
 PASS window.cached_trustedTypes.defaultPolicy is null
+PASS window.cached_trustedTypes.onbeforecreatepolicy is null
 PASS window.cached_visualViewport.height is 0
 PASS window.cached_visualViewport.offsetLeft is 0
 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
index 2f78387..4f8c062 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -116,6 +116,7 @@
 PASS window.cached_styleMedia.type is ''
 PASS window.cached_toolbar.visible is false
 PASS window.cached_trustedTypes.defaultPolicy is null
+PASS window.cached_trustedTypes.onbeforecreatepolicy is null
 PASS window.cached_visualViewport.height is 0
 PASS window.cached_visualViewport.offsetLeft is 0
 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index fe27a995..e009471 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -254,6 +254,7 @@
 PASS oldChildWindow.styleMedia.type is newChildWindow.styleMedia.type
 PASS oldChildWindow.toolbar.visible is newChildWindow.toolbar.visible
 PASS oldChildWindow.trustedTypes.defaultPolicy is newChildWindow.trustedTypes.defaultPolicy
+PASS oldChildWindow.trustedTypes.onbeforecreatepolicy is newChildWindow.trustedTypes.onbeforecreatepolicy
 PASS oldChildWindow.visualViewport.height is newChildWindow.visualViewport.height
 PASS oldChildWindow.visualViewport.offsetLeft is newChildWindow.visualViewport.offsetLeft
 PASS oldChildWindow.visualViewport.offsetTop is newChildWindow.visualViewport.offsetTop
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index 9d8cd87..bd9309f27 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -195,6 +195,7 @@
 PASS childWindow.styleMedia.type is ''
 PASS childWindow.toolbar.visible is false
 PASS childWindow.trustedTypes.defaultPolicy is null
+PASS childWindow.trustedTypes.onbeforecreatepolicy is null
 PASS childWindow.visualViewport.height is 0
 PASS childWindow.visualViewport.offsetLeft is 0
 PASS childWindow.visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index 0fdddbd..74def1f 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -195,6 +195,7 @@
 PASS childWindow.styleMedia.type is ''
 PASS childWindow.toolbar.visible is false
 PASS childWindow.trustedTypes.defaultPolicy is null
+PASS childWindow.trustedTypes.onbeforecreatepolicy is null
 PASS childWindow.visualViewport.height is 0
 PASS childWindow.visualViewport.offsetLeft is 0
 PASS childWindow.visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/fast/domurl/url-host.html b/third_party/blink/web_tests/fast/domurl/url-host.html
index 1193969b..06cb4ba 100644
--- a/third_party/blink/web_tests/fast/domurl/url-host.html
+++ b/third_party/blink/web_tests/fast/domurl/url-host.html
@@ -38,13 +38,13 @@
 test(function() {
     var url = new URL('https://www.mydomain.com:8080/path/');
     url.host = 'www.otherdomain.com: 443';
-    assert_equals(url.href, 'https://www.otherdomain.com:0/path/');
+    assert_equals(url.href, 'https://www.otherdomain.com:8080/path/');
 }, 'Leading space in port number');
 
 test(function() {
     var url = new URL('https://www.mydomain.com:8080/path/');
     url.host = 'www.otherdomain.com:';
-    assert_equals(url.href, 'https://www.otherdomain.com:0/path/');
+    assert_equals(url.href, 'https://www.otherdomain.com:8080/path/');
 }, 'Colon without port number');
 
 test(function() {
diff --git a/third_party/blink/web_tests/fast/domurl/url-port.html b/third_party/blink/web_tests/fast/domurl/url-port.html
index 77ac3c1..88c3aff 100644
--- a/third_party/blink/web_tests/fast/domurl/url-port.html
+++ b/third_party/blink/web_tests/fast/domurl/url-port.html
@@ -26,6 +26,8 @@
     url.port = '8080junk';
     assert_equals(url.port, '8080');
 
+    url.port = 0;
+
     url.port = 'junk8080';
     assert_equals(url.port, '0');
 }, 'Basic port');
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html b/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html
index 764938ba..f45389b 100644
--- a/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html
+++ b/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html
@@ -40,7 +40,7 @@
           markDirtyCounter++;
         }
 
-        if (focusCounter == 5 && markDirtyCounter == 6) {
+        if (focusCounter == 5 && markDirtyCounter == 10) {
           assert_equals(date1.value, "2000-02-03", "Submitting month switcher should have udpated control value");
           resolve();
         }
diff --git a/third_party/blink/web_tests/fast/forms/month/month-picker-ax.html b/third_party/blink/web_tests/fast/forms/month/month-picker-ax.html
index 3e6ac60..c6972f4 100644
--- a/third_party/blink/web_tests/fast/forms/month/month-picker-ax.html
+++ b/third_party/blink/web_tests/fast/forms/month/month-picker-ax.html
@@ -27,7 +27,7 @@
           markDirtyCounter++;
         }
 
-        if (focusCounter == 1 && markDirtyCounter == 1) {
+        if (focusCounter == 1 && markDirtyCounter == 2) {
             assert_equals(month1.value, "2000-05", "Arrow key in month picker should have changed value");
             t.done();
         }
diff --git a/third_party/blink/web_tests/fast/forms/week/week-picker-ax.html b/third_party/blink/web_tests/fast/forms/week/week-picker-ax.html
index 53fe6a21..b3638edb 100644
--- a/third_party/blink/web_tests/fast/forms/week/week-picker-ax.html
+++ b/third_party/blink/web_tests/fast/forms/week/week-picker-ax.html
@@ -27,7 +27,7 @@
           markDirtyCounter++;
         }
 
-        if (focusCounter == 1 && markDirtyCounter == 1) {
+        if (focusCounter == 1 && markDirtyCounter == 3) {
           resolve();
         }
       });
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
index 0e5ceb9..b1cca07 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb-expected.txt
@@ -9,18 +9,18 @@
 Storage
  Local Storage
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
  Session Storage
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
  IndexedDB
-  Database-iframe - http://localhost:8000
+  Database-iframe - http://devtools.oopif.test:8000
    Database-iframe
   Database-main-frame - http://127.0.0.1:8000
  Web SQL
  Cookies
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
 Cache
  Cache Storage
  Application Cache
@@ -33,6 +33,9 @@
  Push Messaging
 Frames
  top
+  indexeddb-in-iframe.html
+   indexeddb-in-iframe.html
+  inspected-page.html
 
 Remove iframe from page...
 
@@ -50,7 +53,7 @@
  Web SQL
  Cookies
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
 Cache
  Cache Storage
  Application Cache
@@ -63,6 +66,7 @@
  Push Messaging
 Frames
  top
+  inspected-page.html
 
 Add iframe to page again...
 
@@ -73,18 +77,18 @@
 Storage
  Local Storage
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
  Session Storage
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
  IndexedDB
   Database-main-frame - http://127.0.0.1:8000
-  Database-iframe - http://localhost:8000
+  Database-iframe - http://devtools.oopif.test:8000
    Database-iframe
  Web SQL
  Cookies
   http://127.0.0.1:8000
-  http://localhost:8000
+  http://devtools.oopif.test:8000
 Cache
  Cache Storage
  Application Cache
@@ -97,4 +101,7 @@
  Push Messaging
 Frames
  top
+  indexeddb-in-iframe.html
+   indexeddb-in-iframe.html
+  inspected-page.html
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb.js b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb.js
index d03bcaf..f0efadd0 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb.js
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-iframe-idb.js
@@ -31,7 +31,11 @@
   }
 
   // create IndexedDB in iframe
-  await TestRunner.addIframe('http://localhost:8000/devtools/application-panel/resources/indexeddb-in-iframe.html', {'id': 'indexeddb_page'});
+  // We are enforcing OOPIFs here, so that we are sure that the bots on all platforms create an OOPIF.
+  // This would not be guaranteed otherwise and could potentially result in a different display name
+  // for the iframe in the frame tree.
+  await TestRunner.addIframe('http://devtools.oopif.test:8000/devtools/application-panel/resources/indexeddb-in-iframe.html', {'id': 'indexeddb_page'});
+
   await TestRunner.addSnifferPromise(UI.panels.resources._sidebar.indexedDBListTreeElement, '_indexedDBLoadedForTest');
 
   // create IndexedDB in main frame
@@ -55,7 +59,7 @@
   dumpTree(view._sidebar._sidebarTree.rootElement(), 0);
 
   TestRunner.addResult('\nAdd iframe to page again...\n');
-  await TestRunner.addIframe('http://localhost:8000/devtools/application-panel/resources/indexeddb-in-iframe.html', {'id': 'indexeddb_page'});
+  await TestRunner.addIframe('http://devtools.oopif.test:8000/devtools/application-panel/resources/indexeddb-in-iframe.html', {'id': 'indexeddb_page'});
   await TestRunner.addSnifferPromise(UI.panels.resources._sidebar.indexedDBListTreeElement, '_indexedDBLoadedForTest');
 
   dumpTree(view._sidebar._sidebarTree.rootElement(), 0);
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
index e751a88..20d93aff 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
@@ -28,6 +28,7 @@
   Push Messaging
 Frames
   top
+    inspected-page.html
 Visible view is a query view: true
 Page reloaded.
 After navigation:
@@ -57,5 +58,6 @@
   Push Messaging
 Frames
   top
+    inspected-page.html
 Visible view is a query view: false
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
index 9b7f6ee..150960e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
@@ -26,6 +26,11 @@
   Push Messaging
 Frames
   top
+    Images
+      image.png
+    Scripts
+      json-value.js
+    inspected-page.html
 log: visible view: unknown
 Revealed json-value.js:
 Application
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
index 8b922f4..bc20911e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
@@ -28,6 +28,7 @@
   Push Messaging
 Frames
   top
+    inspected-page.html
 Selection: ["cookies://http://127.0.0.1:8000","category://Cookies"]
 Visible view is a cookie view: true
 Page reloaded.
@@ -58,6 +59,7 @@
   Push Messaging
 Frames
   top
+    inspected-page.html
 Selection: ["cookies://http://127.0.0.1:8000","category://Cookies"]
 Visible view is a cookie view: true
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
index 1cdfce40..285cc877 100644
--- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
@@ -26,6 +26,9 @@
   Push Messaging
 Frames
   top
+    Scripts
+      json-value.js
+    inspected-page.html
 Found: true
 Database created state:
 Application
@@ -54,6 +57,9 @@
   Push Messaging
 Frames
   top
+    Scripts
+      json-value.js
+    inspected-page.html
 Table added:
 Application
   Manifest
@@ -82,4 +88,7 @@
   Push Messaging
 Frames
   top
+    Scripts
+      json-value.js
+    inspected-page.html
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
index 547456b..e5eef21 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
@@ -6,6 +6,8 @@
         resource-tree-non-unique-url-iframe.html
             Images
                 styles-non-unique-url.css
+            Stylesheets
+                styles-non-unique-url.css
             resource-tree-non-unique-url-iframe.html
         inspected-page.html
 Sources:
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 2f372ec..9921575 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1495,11 +1495,12 @@
     getter readable
     getter writable
     method constructor
-interface TrustedTypePolicyFactory
+interface TrustedTypePolicyFactory : EventTarget
     attribute @@toStringTag
     getter defaultPolicy
     getter emptyHTML
     getter emptyScript
+    getter onbeforecreatepolicy
     method constructor
     method createPolicy
     method getAttributeType
@@ -1508,6 +1509,7 @@
     method isHTML
     method isScript
     method isScriptURL
+    setter onbeforecreatepolicy
 interface URL
     attribute @@toStringTag
     getter hash
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text-expected.txt
new file mode 100644
index 0000000..90cf70b
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text-expected.txt
@@ -0,0 +1,17 @@
+The test verifies functionality of protocol method CSS.setStyleTexts and DOM.undo.
+==== Initial style sheet text ====
+
+#test { color: green; }
+
+==== Style sheet text ====
+
+#test {color: blue;}
+
+Dumping matched rules: 
+*#test* {    regular
+    color: blue;
+}
+Dumping inherited rules: 
+==== Style sheet text after clearing the stylesheet and DOM.Undo ====
+<empty>
+
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text.js b/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text.js
new file mode 100644
index 0000000..d6aad0e
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-set-inline-style-tag-text.js
@@ -0,0 +1,48 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startHTML(`
+<style>
+#test { color: green; }
+</style>
+<article id='test'></article>
+`, 'The test verifies functionality of protocol method CSS.setStyleTexts and DOM.undo.');
+
+  const CSSHelper = await testRunner.loadScript('../resources/css-helper.js');
+  const cssHelper = new CSSHelper(testRunner, dp);
+
+  let eventPromise = dp.CSS.onceStyleSheetAdded();
+
+  await dp.DOM.enable();
+  await dp.CSS.enable();
+
+  let event = await eventPromise;
+  let styleSheetId = event.params.header.styleSheetId;
+
+  const setStyleTexts = cssHelper.setStyleTexts.bind(cssHelper, styleSheetId, false);
+  const documentNodeId = await cssHelper.requestDocumentNodeId();
+
+  let response = await dp.CSS.getStyleSheetText({styleSheetId});
+  testRunner.log('==== Initial style sheet text ====');
+  testRunner.log(response.result.text);
+
+  await setStyleTexts([{
+    styleSheetId: styleSheetId,
+    range: { startLine: 1, startColumn: 7, endLine: 1, endColumn: 22 },
+    text: "color: blue;",
+  }]);
+  await cssHelper.loadAndDumpMatchingRules(documentNodeId, '#test');
+
+  eventPromise = dp.CSS.onceStyleSheetAdded();
+  // Clear the style content.
+  await session.evaluate(fontURL => {
+    const style = document.querySelector('style');
+    style.textContent = '';
+  });
+  await dp.DOM.undo();
+
+  event = await eventPromise;
+  styleSheetId = event.params.header.styleSheetId;
+  response = await dp.CSS.getStyleSheetText({styleSheetId});
+  testRunner.log('==== Style sheet text after clearing the stylesheet and DOM.Undo ====');
+  testRunner.log(response.result.text || '<empty>');
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
index 2dcfea2b..88fffba 100644
--- a/third_party/blink/web_tests/platform/linux/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
+++ b/third_party/blink/web_tests/platform/linux/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
index 53161bf..64230c1 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 601 tests; 308 PASS, 293 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 601 tests; 311 PASS, 290 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
 PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
@@ -217,9 +217,9 @@
 PASS URL: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <a>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <area>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
-FAIL URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
+PASS URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
 PASS URL: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <a>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <area>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
new file mode 100644
index 0000000..17b1ab4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
new file mode 100644
index 0000000..137b7a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
new file mode 100644
index 0000000..28f5f678
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
new file mode 100644
index 0000000..e47b7521
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
new file mode 100644
index 0000000..fbed8a935
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
new file mode 100644
index 0000000..e2756e8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
index 53161bf..64230c1 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 601 tests; 308 PASS, 293 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 601 tests; 311 PASS, 290 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
 PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
@@ -217,9 +217,9 @@
 PASS URL: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <a>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <area>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
-FAIL URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
+PASS URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
 PASS URL: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <a>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <area>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
new file mode 100644
index 0000000..a2a3477
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
new file mode 100644
index 0000000..65e93a2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
new file mode 100644
index 0000000..e7c8125
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
index 0825be0..3f43f5e 100644
--- a/third_party/blink/web_tests/platform/win/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
+++ b/third_party/blink/web_tests/platform/win/editing/selection/selection-linebreaks-rtl-writing-modes-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
index d2f63321..42628966 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 601 tests; 281 PASS, 320 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 601 tests; 284 PASS, 317 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Loading data…
 FAIL URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net"
 FAIL <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net"
@@ -217,9 +217,9 @@
 PASS URL: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <a>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
 PASS <area>: Setting <http://example.net:8080>.host = 'example.com' Port number is unchanged if not specified in the new value
-FAIL URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
-FAIL <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified assert_equals: expected "http://example.com:8080/" but got "http://example.com:0/"
+PASS URL: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <a>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
+PASS <area>: Setting <http://example.net:8080>.host = 'example.com:' Port number is unchanged if not specified
 PASS URL: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <a>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
 PASS <area>: Setting <http://example.net>.host = '' The empty host is not valid for special schemes
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
new file mode 100644
index 0000000..d57cb83f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
new file mode 100644
index 0000000..d22f769
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
new file mode 100644
index 0000000..c7f8a69
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
new file mode 100644
index 0000000..c4ce10696
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
new file mode 100644
index 0000000..c2cba0e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
new file mode 100644
index 0000000..a936299
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/selection/select-ligature-vertical-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index e2d7833..b755161 100644
--- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1233,7 +1233,7 @@
     getter readable
     getter writable
     method constructor
-interface TrustedTypePolicyFactory
+interface TrustedTypePolicyFactory : EventTarget
     attribute @@toStringTag
     getter defaultPolicy
     getter emptyHTML
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index b3ff03e..a7572c7 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1141,7 +1141,7 @@
 [Worker]     getter readable
 [Worker]     getter writable
 [Worker]     method constructor
-[Worker] interface TrustedTypePolicyFactory
+[Worker] interface TrustedTypePolicyFactory : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter defaultPolicy
 [Worker]     getter emptyHTML
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index c89dcd3..0774167 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7322,7 +7322,7 @@
     method createHTML
     method createScript
     method createScriptURL
-interface TrustedTypePolicyFactory
+interface TrustedTypePolicyFactory : EventTarget
     attribute @@toStringTag
     getter defaultPolicy
     getter emptyHTML
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index 2378673..5a973019 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1141,7 +1141,7 @@
 [Worker]     getter readable
 [Worker]     getter writable
 [Worker]     method constructor
-[Worker] interface TrustedTypePolicyFactory
+[Worker] interface TrustedTypePolicyFactory : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter defaultPolicy
 [Worker]     getter emptyHTML
diff --git a/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-1.html b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-1.html
new file mode 100644
index 0000000..a9cdc70
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-family: Times;
+  font-size: 100px;
+  line-height: 1;
+  font-variant-ligatures: discretionary-ligatures;
+  width: 300px;
+  writing-mode: vertical-rl;
+}
+div::selection {
+  color: white;
+  background: blue;
+}
+.small { font-size: 10%; }
+</style>
+<body>
+  <div id="target"><span class="small">x </span>ffi f ff fi ffi ffi</div>
+<script>
+select(0, 1);
+function select(start_offset, end_offset) {
+  let target = document.getElementById('target');
+  let textNode = target.lastChild;
+  let range = document.createRange();
+  range.setStart(textNode, start_offset);
+  range.setEnd(textNode, end_offset);
+  getSelection().addRange(range);
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-2.html b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-2.html
new file mode 100644
index 0000000..4d86288
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-family: Times;
+  font-size: 100px;
+  line-height: 1;
+  font-variant-ligatures: discretionary-ligatures;
+  width: 300px;
+  writing-mode: vertical-rl;
+}
+div::selection {
+  color: white;
+  background: blue;
+}
+.small { font-size: 10%; }
+</style>
+<body>
+  <div id="target"><span class="small">x </span>ffi f ff fi ffi ffi</div>
+<script>
+select(13, 14);
+function select(start_offset, end_offset) {
+  let target = document.getElementById('target');
+  let textNode = target.lastChild;
+  let range = document.createRange();
+  range.setStart(textNode, start_offset);
+  range.setEnd(textNode, end_offset);
+  getSelection().addRange(range);
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-3.html b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-3.html
new file mode 100644
index 0000000..fc1f4ca
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/text-antialias/selection/select-ligature-vertical-3.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<style>
+div {
+  font-family: Times;
+  font-size: 100px;
+  line-height: 1;
+  font-variant-ligatures: discretionary-ligatures;
+  width: 300px;
+  writing-mode: vertical-rl;
+}
+div::selection {
+  color: white;
+  background: blue;
+}
+.small { font-size: 10%; }
+</style>
+<body>
+  <div id="target"><span class="small">x </span>ffi f ff fi ffi ffi</div>
+<script>
+select(18, 19);
+function select(start_offset, end_offset) {
+  let target = document.getElementById('target');
+  let textNode = target.lastChild;
+  let range = document.createRange();
+  range.setStart(textNode, start_offset);
+  range.setEnd(textNode, end_offset);
+  getSelection().addRange(range);
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 5b8f6dce..d163e792 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1473,11 +1473,12 @@
 [Worker]     getter readable
 [Worker]     getter writable
 [Worker]     method constructor
-[Worker] interface TrustedTypePolicyFactory
+[Worker] interface TrustedTypePolicyFactory : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter defaultPolicy
 [Worker]     getter emptyHTML
 [Worker]     getter emptyScript
+[Worker]     getter onbeforecreatepolicy
 [Worker]     method constructor
 [Worker]     method createPolicy
 [Worker]     method getAttributeType
@@ -1486,6 +1487,7 @@
 [Worker]     method isHTML
 [Worker]     method isScript
 [Worker]     method isScriptURL
+[Worker]     setter onbeforecreatepolicy
 [Worker] interface URL
 [Worker]     static method createObjectURL
 [Worker]     static method revokeObjectURL
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 855f636..e2328dd 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
@@ -487,6 +487,11 @@
     setter onchargingtimechange
     setter ondischargingtimechange
     setter onlevelchange
+interface BeforeCreatePolicyEvent : Event
+    attribute @@toStringTag
+    getter policyName
+    method constructor
+    setter policyName
 interface BeforeInstallPromptEvent : Event
     attribute @@toStringTag
     getter platforms
@@ -8522,11 +8527,12 @@
     method createHTML
     method createScript
     method createScriptURL
-interface TrustedTypePolicyFactory
+interface TrustedTypePolicyFactory : EventTarget
     attribute @@toStringTag
     getter defaultPolicy
     getter emptyHTML
     getter emptyScript
+    getter onbeforecreatepolicy
     method constructor
     method createPolicy
     method getAttributeType
@@ -8535,6 +8541,7 @@
     method isHTML
     method isScript
     method isScriptURL
+    setter onbeforecreatepolicy
 interface UIEvent : Event
     attribute @@toStringTag
     getter detail
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index f12f3fcc..e977d5d 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1372,11 +1372,12 @@
 [Worker]     getter readable
 [Worker]     getter writable
 [Worker]     method constructor
-[Worker] interface TrustedTypePolicyFactory
+[Worker] interface TrustedTypePolicyFactory : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter defaultPolicy
 [Worker]     getter emptyHTML
 [Worker]     getter emptyScript
+[Worker]     getter onbeforecreatepolicy
 [Worker]     method constructor
 [Worker]     method createPolicy
 [Worker]     method getAttributeType
@@ -1385,6 +1386,7 @@
 [Worker]     method isHTML
 [Worker]     method isScript
 [Worker]     method isScriptURL
+[Worker]     setter onbeforecreatepolicy
 [Worker] interface URL
 [Worker]     static method createObjectURL
 [Worker]     static method revokeObjectURL
diff --git a/third_party/wuffs/BUILD.gn b/third_party/wuffs/BUILD.gn
index daa9564..387d08d 100644
--- a/third_party/wuffs/BUILD.gn
+++ b/third_party/wuffs/BUILD.gn
@@ -28,6 +28,8 @@
 # targets' configuration or visibility, require consulting ENG_REVIEW_OWNERS,
 # as per the "adding_to_third_party.md" link above.
 
+import("//third_party/wuffs/config.gni")
+
 static_library("wuffs") {
   defines = [
     # Copy/pasting from "src/release/c/wuffs-*.c":
@@ -65,12 +67,17 @@
     # ENG_REVIEW_OWNERS" comment at the top of this file.
     "WUFFS_CONFIG__MODULES",
     "WUFFS_CONFIG__MODULE__BASE__CORE",
-    "WUFFS_CONFIG__MODULE__BASE__INTERFACES",
-    "WUFFS_CONFIG__MODULE__BASE__PIXCONV",
-    "WUFFS_CONFIG__MODULE__GIF",
-    "WUFFS_CONFIG__MODULE__LZW",
   ]
 
+  if (use_wuffs_gif_parser) {
+    defines += [
+      "WUFFS_CONFIG__MODULE__BASE__INTERFACES",
+      "WUFFS_CONFIG__MODULE__BASE__PIXCONV",
+      "WUFFS_CONFIG__MODULE__GIF",
+      "WUFFS_CONFIG__MODULE__LZW",
+    ]
+  }
+
   # Do not modify this list without considering the "consult ENG_REVIEW_OWNERS"
   # comment at the top of this file.
   visibility = [ "//skia" ]
diff --git a/third_party/wuffs/config.gni b/third_party/wuffs/config.gni
new file mode 100644
index 0000000..05680920
--- /dev/null
+++ b/third_party/wuffs/config.gni
@@ -0,0 +1,7 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+  use_wuffs_gif_parser = false
+}
diff --git a/tools/binary_size/libsupersize/testdata/mock_source_directory/base/DIR_METADATA b/tools/binary_size/libsupersize/testdata/mock_source_directory/base/DIR_METADATA
index d115303c..47187d6 100644
--- a/tools/binary_size/libsupersize/testdata/mock_source_directory/base/DIR_METADATA
+++ b/tools/binary_size/libsupersize/testdata/mock_source_directory/base/DIR_METADATA
@@ -3,4 +3,4 @@
   component: "Blink>Internal"
 }
 team_email: "team@chromium.org"
-os: OS_LINUX
+os: LINUX
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl
index b2598b2b..cffd11d0 100644
--- a/tools/gritsettings/translation_expectations.pyl
+++ b/tools/gritsettings/translation_expectations.pyl
@@ -38,6 +38,7 @@
       "chrome/app/google_chrome_strings.grd",
       "chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd",
       "chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd",
+      "chrome/browser/password_check/android/internal/java/strings/android_password_check_strings.grd",
       "chrome/browser/ui/android/strings/android_chrome_strings.grd",
       "chrome/credential_provider/gaiacp/gaia_resources.grd",
       "chromeos/chromeos_strings.grd",
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index bc40fcf..8fb5fc1 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -24,7 +24,6 @@
       # they monitor binary size growth, which may be affected by the tables.
       'linux-chrome': 'official_goma',
       'linux-chromeos-chrome': 'official_goma_chromeos',
-      'linux-lacros': 'lacros_on_linux_release_bot',
       'mac-chrome': 'official_goma',
       'mac-chrome-beta': 'official_goma',
       'mac-chrome-stable': 'official_goma',
@@ -879,6 +878,7 @@
       'linux-clang-tidy-rel': 'release_trybot',
       'linux-dcheck-off-rel': 'release_trybot_dcheck_off',
       'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
+      'linux-lacros-rel': 'lacros_on_linux_release_bot',
       'linux-libfuzzer-asan-rel': 'libfuzzer_asan_release_trybot',
       'linux-ozone-rel': 'ozone_linux_release_trybot',
       'linux-perfetto-rel': 'perfetto_release_trybot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b49e0f5..55fe4c2 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13924,6 +13924,13 @@
   <int value="2" label="UnsupportedIME"/>
 </enum>
 
+<enum name="CrostiniUpgradeAvailableNotificationClosed">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="By User"/>
+  <int value="2" label="Upgrade Clicked"/>
+  <int value="3" label="Notification Body Clicked"/>
+</enum>
+
 <enum name="CrostiniUpgradeDialogEvent">
   <int value="0" label="Dialog Shown"/>
   <int value="1" label="Upgrade Succeeded"/>
@@ -56036,6 +56043,7 @@
   <int value="0" label="Add preferred app"/>
   <int value="1" label="Delete preferred app"/>
   <int value="2" label="Delete preferred app for an app id"/>
+  <int value="3" label="Upgrade preferred app to newer version"/>
 </enum>
 
 <enum name="PrefetchRedirect">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index bb1e7155..74937cc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -34049,6 +34049,17 @@
   </summary>
 </histogram>
 
+<histogram name="Crostini.UpgradeAvailable"
+    enum="CrostiniUpgradeAvailableNotificationClosed"
+    expires_after="2021-07-15">
+  <owner>clumptini@google.com</owner>
+  <owner>tbuckley@chromium.org</owner>
+  <summary>
+    Recorded each time the user sees the Crostini upgrade Notifiation, recording
+    the action that closded the notification.
+  </summary>
+</histogram>
+
 <histogram name="Crostini.UpgradeDialogEvent" enum="CrostiniUpgradeDialogEvent"
     expires_after="2021-03-06">
   <owner>clumptini@google.com</owner>
@@ -157660,6 +157671,10 @@
 
 <histogram name="ServiceWorker.UpdateCheck.Result"
     enum="ServiceWorkerStatusCode" expires_after="2020-07-17">
+  <obsolete>
+    Removed 2020-07 because we could confirm byte-for-byte update checking for
+    imported scripts works.
+  </obsolete>
   <owner>shimazu@chromium.org</owner>
   <summary>
     Records the result of byte-for-byte update checking. If it's not OK, it
@@ -157670,6 +157685,10 @@
 
 <histogram name="ServiceWorker.UpdateCheck.UpdateFound" enum="BooleanFound"
     expires_after="2020-07-17">
+  <obsolete>
+    Removed 2020-07 because we could confirm byte-for-byte update checking for
+    imported scripts works.
+  </obsolete>
   <owner>shimazu@chromium.org</owner>
   <summary>
     Records the result of byte-for-byte update checking. Recorded only when
@@ -201959,9 +201978,17 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="EventLatencyScrollBreakdowns" separator=".">
-  <suffix name="TotalLatencyToSwapEnd"
+  <suffix name="TotalLatencyToSwapBegin"
       label="Total latency from when the event is generated until the
-             gpu-swap is completed."/>
+             gpu-swap is started."/>
+  <suffix name="TotalLatencyToSwapEnd"
+      label="Total latency from when the event is generated until the gpu-swap
+             is completed.">
+    <obsolete>
+      Deprecated as of 07/2020. Replaced with TotalLatencyToSwapBegin suffix
+      which measures what we actually intended to measure.
+    </obsolete>
+  </suffix>
   <affected-histogram name="EventLatency.GestureScrollBegin.Autoscroll"/>
   <affected-histogram name="EventLatency.GestureScrollBegin.Scrollbar"/>
   <affected-histogram name="EventLatency.GestureScrollBegin.Touchscreen"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 0eb1e73..3b3d27c 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -4143,10 +4143,10 @@
       </history>
     </aggregation>
   </metric>
-  <metric name="TotalLatencyToSwapEnd">
+  <metric name="TotalLatencyToSwapBegin">
     <summary>
       The time from when the event is created in the browser to when the
-      gpu-swap is completed, for scroll and pinch events.
+      gpu-swap is started, for scroll events.
     </summary>
     <aggregation>
       <history>
@@ -4157,6 +4157,16 @@
       </history>
     </aggregation>
   </metric>
+  <metric name="TotalLatencyToSwapEnd">
+    <obsolete>
+      Deprecated as of 07/2020. Replaced with TotalLatencyToSwapBegin which
+      measures what we actually intended to measure.
+    </obsolete>
+    <summary>
+      The time from when the event is created in the browser to when the
+      gpu-swap is completed, for scroll events.
+    </summary>
+  </metric>
 </event>
 
 <event name="Graphics.Smoothness.Latency">
diff --git a/tools/perf/benchmarks/rendering.py b/tools/perf/benchmarks/rendering.py
index 81e1a84..400b30e7 100644
--- a/tools/perf/benchmarks/rendering.py
+++ b/tools/perf/benchmarks/rendering.py
@@ -15,6 +15,7 @@
 
 RENDERING_BENCHMARK_UMA = [
     'Compositing.Display.DrawToSwapUs',
+    'CompositorLatency.TotalLatency',
     'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
     'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
     'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 6bf98a1..1259786 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "9422fbaca127b736c7c04ceadaeec1ecb5435396",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/c4c3be736312e3ea8f454f323a98d3f14707bd72/trace_processor_shell.exe"
+            "hash": "eabadb18c9b973545e0c496332e868019f16ca0c",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/d9b254b474d3ad65d26ece05b51eb6c7a0ff5f35/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "ee514396d2e9a5059923db3926ac0a74ab0b9e12",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c4c3be736312e3ea8f454f323a98d3f14707bd72/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/df50009d3edec39cee9a7f5a59851701848fa32d/trace_processor_shell"
         },
         "linux": {
-            "hash": "44a12287f9221a9a14a18507955ef53fa31f06f2",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/c4c3be736312e3ea8f454f323a98d3f14707bd72/trace_processor_shell"
+            "hash": "e8747f4901f0211546d40c9aac0bfb3e69b97a8b",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/d9b254b474d3ad65d26ece05b51eb6c7a0ff5f35/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 32fd046..8f196f5 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -169,6 +169,7 @@
  <item id="mojo_context_state" hash_code="93232258" type="0" deprecated="2017-10-20" content_hash_code="124821232" file_path=""/>
  <item id="navigation_predictor_srp_prefetch" hash_code="57773453" type="0" content_hash_code="38811322" os_list="linux,windows" file_path="chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc"/>
  <item id="navigation_url_loader" hash_code="63171670" type="0" content_hash_code="129352907" os_list="linux,windows" file_path="content/browser/loader/navigation_url_loader_impl.cc"/>
+ <item id="nearby_webrtc_connection" hash_code="37994740" type="0" content_hash_code="118366066" os_list="linux,windows" file_path="chrome/services/sharing/nearby/platform_v2/webrtc.cc"/>
  <item id="net_error_helper" hash_code="60071001" type="0" deprecated="2020-07-10" content_hash_code="68322861" file_path=""/>
  <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="services/device/geolocation/network_location_provider.cc"/>
  <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="80741011" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="services/device/geolocation/network_location_request.cc"/>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index f299b5f..72e7d2a 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -64,6 +64,8 @@
     "ax_relative_bounds.h",
     "ax_role_properties.cc",
     "ax_role_properties.h",
+    "ax_tree_id.cc",
+    "ax_tree_id.h",
   ]
 
   public_deps = [
@@ -71,6 +73,7 @@
     ":ax_enums_mojo",
     "//base",
     "//base:i18n",
+    "//base/util/values:values_util",
     "//ui/base",
     "//ui/gfx",
     "//ui/gfx/geometry",
@@ -129,8 +132,6 @@
     "ax_tree_combiner.h",
     "ax_tree_data.cc",
     "ax_tree_data.h",
-    "ax_tree_id.cc",
-    "ax_tree_id.h",
     "ax_tree_id_registry.cc",
     "ax_tree_id_registry.h",
     "ax_tree_manager.h",
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index 3901589..a75f4270 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -284,6 +284,9 @@
       // The image annotation is reported as part of the accessible name.
       AddEvent(node, Event::IMAGE_ANNOTATION_CHANGED);
       break;
+    case ax::mojom::StringAttribute::kFontFamily:
+      AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED);
+      break;
     default:
       AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
       break;
@@ -365,6 +368,16 @@
     case ax::mojom::IntAttribute::kSetSize:
       AddEvent(node, Event::SET_SIZE_CHANGED);
       break;
+    case ax::mojom::IntAttribute::kBackgroundColor:
+    case ax::mojom::IntAttribute::kColor:
+    case ax::mojom::IntAttribute::kTextDirection:
+    case ax::mojom::IntAttribute::kTextPosition:
+    case ax::mojom::IntAttribute::kTextStyle:
+    case ax::mojom::IntAttribute::kTextOverlineStyle:
+    case ax::mojom::IntAttribute::kTextStrikethroughStyle:
+    case ax::mojom::IntAttribute::kTextUnderlineStyle:
+      AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED);
+      break;
     default:
       AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
       break;
@@ -391,6 +404,10 @@
     case ax::mojom::FloatAttribute::kValueForRange:
       AddEvent(node, Event::VALUE_CHANGED);
       break;
+    case ax::mojom::FloatAttribute::kFontSize:
+    case ax::mojom::FloatAttribute::kFontWeight:
+      AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED);
+      break;
     default:
       AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
       break;
@@ -462,6 +479,17 @@
     case ax::mojom::IntListAttribute::kLabelledbyIds:
       AddEvent(node, Event::LABELED_BY_CHANGED);
       break;
+    case ax::mojom::IntListAttribute::kMarkerEnds:
+    case ax::mojom::IntListAttribute::kMarkerStarts:
+    case ax::mojom::IntListAttribute::kMarkerTypes:
+      // On a native text field, the spelling- and grammar-error markers are
+      // associated with children not exposed on any platform. Therefore, we
+      // adjust the node we fire that event on here.
+      if (AXNode* text_field = node->GetTextFieldAncestor())
+        AddEvent(text_field, Event::TEXT_ATTRIBUTE_CHANGED);
+      else
+        AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED);
+      break;
     default:
       AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
       break;
@@ -635,11 +663,10 @@
 }
 
 void AXEventGenerator::PostprocessEvents() {
-  std::vector<AXNode*> nodes_to_remove_subtree_created;
-
-  for (auto& iter : tree_events_) {
-    AXNode* node = iter.first;
-    std::set<EventParams>& node_events = iter.second;
+  auto iter = tree_events_.begin();
+  while (iter != tree_events_.end()) {
+    AXNode* node = iter->first;
+    std::set<EventParams>& node_events = iter->second;
 
     // A newly created live region or alert should not *also* fire a
     // live region changed event.
@@ -648,32 +675,55 @@
       RemoveEvent(&node_events, Event::LIVE_REGION_CHANGED);
     }
 
-    // If a node toggled its ignored state, we shouldn't also fire
-    // children changed events on it.
-    if (HasEvent(node_events, Event::IGNORED_CHANGED))
+    // If a node toggled its ignored state, don't also fire children-changed
+    // because platforms likely will do that in response to ignored-changed.
+    // Suppress name- and description-changed because those can be emitted
+    // as a side effect of calculating alternative text values for a newly-
+    // displayed object. Ditto for text attributes such as foreground and
+    // background colors.
+    if (HasEvent(node_events, Event::IGNORED_CHANGED)) {
       RemoveEvent(&node_events, Event::CHILDREN_CHANGED);
-
-    // We shouldn't fire subtree created if the parent also has subtree
-    // created on it.
-    AXNode* parent = node->GetUnignoredParent();
-    if (parent && HasEvent(node_events, Event::SUBTREE_CREATED)) {
-      if (tree_events_.find(parent) != tree_events_.end()) {
-        std::set<EventParams>& parent_events = tree_events_[parent];
-        if (HasEvent(parent_events, Event::SUBTREE_CREATED))
-          nodes_to_remove_subtree_created.push_back(node);
-      }
+      RemoveEvent(&node_events, Event::DESCRIPTION_CHANGED);
+      RemoveEvent(&node_events, Event::NAME_CHANGED);
+      RemoveEvent(&node_events, Event::TEXT_ATTRIBUTE_CHANGED);
     }
-  }
 
-  for (AXNode* node : nodes_to_remove_subtree_created) {
-    std::set<EventParams>& node_events = tree_events_[node];
-    RemoveEvent(&node_events, Event::SUBTREE_CREATED);
+    // When the selected option in an expanded select element changes, the
+    // foreground and background colors change. But we don't want to treat
+    // those as text attribute changes. This can also happen when a widget
+    // such as a button becomes enabled/disabled.
+    if (HasEvent(node_events, Event::SELECTED_CHANGED) ||
+        HasEvent(node_events, Event::ENABLED_CHANGED)) {
+      RemoveEvent(&node_events, Event::TEXT_ATTRIBUTE_CHANGED);
+    }
+
+    AXNode* parent = node->GetUnignoredParent();
+
+    // Don't fire text attribute changed on this node if its immediate parent
+    // also has text attribute changed.
+    if (parent && HasEvent(node_events, Event::TEXT_ATTRIBUTE_CHANGED) &&
+        tree_events_.find(parent) != tree_events_.end() &&
+        HasEvent(tree_events_[parent], Event::TEXT_ATTRIBUTE_CHANGED)) {
+      RemoveEvent(&node_events, Event::TEXT_ATTRIBUTE_CHANGED);
+    }
+
+    // Don't fire subtree created on this node if any of its ancestors also has
+    // subtree created.
+    while (parent && HasEvent(node_events, Event::SUBTREE_CREATED) &&
+           tree_events_.find(parent) != tree_events_.end()) {
+      if (HasEvent(tree_events_[parent], Event::SUBTREE_CREATED)) {
+        RemoveEvent(&node_events, Event::SUBTREE_CREATED);
+        break;
+      }
+      parent = parent->GetUnignoredParent();
+    }
+
     // If this was the only event, remove the node entirely from the
-    // tree events. Note that this can't happen with any of the other logic
-    // above since it's all dealing with one event superseding another in
-    // the same node.
+    // tree events.
     if (node_events.size() == 0)
-      tree_events_.erase(node);
+      iter = tree_events_.erase(iter);
+    else
+      ++iter;
   }
 }
 
@@ -829,6 +879,8 @@
       return "STATE_CHANGED";
     case AXEventGenerator::Event::SUBTREE_CREATED:
       return "SUBTREE_CREATED";
+    case AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
+      return "TEXT_ATTRIBUTE_CHANGED";
     case AXEventGenerator::Event::VALUE_CHANGED:
       return "VALUE_CHANGED";
     case AXEventGenerator::Event::VALUE_MAX_CHANGED:
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index 0819741..d6824c7 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -84,6 +84,7 @@
     SORT_CHANGED,
     STATE_CHANGED,
     SUBTREE_CREATED,
+    TEXT_ATTRIBUTE_CHANGED,
     VALUE_CHANGED,
     VALUE_MAX_CHANGED,
     VALUE_MIN_CHANGED,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc
index 792aa6b..9387a99 100644
--- a/ui/accessibility/ax_event_generator_unittest.cc
+++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -687,6 +687,106 @@
           AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED, 1)));
 }
 
+TEST(AXEventGeneratorTest, TextAttributeChanged) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(17);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2,  3,  4,  5,  6,  7,  8,  9,
+                                      10, 11, 12, 13, 14, 15, 16, 17};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[2].id = 3;
+  initial_state.nodes[3].id = 4;
+  initial_state.nodes[4].id = 5;
+  initial_state.nodes[5].id = 6;
+  initial_state.nodes[6].id = 7;
+  initial_state.nodes[7].id = 8;
+  initial_state.nodes[8].id = 9;
+  initial_state.nodes[9].id = 10;
+  initial_state.nodes[10].id = 11;
+  initial_state.nodes[11].id = 12;
+  initial_state.nodes[12].id = 13;
+  initial_state.nodes[13].id = 14;
+  initial_state.nodes[14].id = 15;
+  initial_state.nodes[15].id = 16;
+  initial_state.nodes[16].id = 17;
+
+  // To test changing the start and end of existing markers.
+  initial_state.nodes[11].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kTextMatch)});
+  initial_state.nodes[11].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerStarts, {5});
+  initial_state.nodes[11].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerEnds, {10});
+
+  AXTree tree(initial_state);
+
+  AXEventGenerator event_generator(&tree);
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntAttribute(ax::mojom::IntAttribute::kColor, 0);
+  update.nodes[2].AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor, 0);
+  update.nodes[3].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextDirection,
+      static_cast<int32_t>(ax::mojom::TextDirection::kRtl));
+  update.nodes[4].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextPosition,
+      static_cast<int32_t>(ax::mojom::TextPosition::kSuperscript));
+  update.nodes[5].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextStyle,
+      static_cast<int32_t>(ax::mojom::TextStyle::kBold));
+  update.nodes[6].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextOverlineStyle,
+      static_cast<int32_t>(ax::mojom::TextDecorationStyle::kSolid));
+  update.nodes[7].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextStrikethroughStyle,
+      static_cast<int32_t>(ax::mojom::TextDecorationStyle::kWavy));
+  update.nodes[8].AddIntAttribute(
+      ax::mojom::IntAttribute::kTextUnderlineStyle,
+      static_cast<int32_t>(ax::mojom::TextDecorationStyle::kDotted));
+  update.nodes[9].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  update.nodes[10].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)});
+  update.nodes[11].AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerEnds,
+                                       {11});
+  update.nodes[12].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kActiveSuggestion)});
+  update.nodes[13].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSuggestion)});
+  update.nodes[14].AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize,
+                                     12.0f);
+  update.nodes[15].AddFloatAttribute(ax::mojom::FloatAttribute::kFontWeight,
+                                     600.0f);
+  update.nodes[16].AddStringAttribute(ax::mojom::StringAttribute::kFontFamily,
+                                      "sans");
+
+  ASSERT_TRUE(tree.Unserialize(update));
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 3),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 4),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 5),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 6),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 7),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 8),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 9),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 10),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 11),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 12),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 13),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 14),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 15),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 16),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 17)));
+}
+
 TEST(AXEventGeneratorTest, OtherAttributeChanged) {
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
@@ -723,7 +823,7 @@
           HasEventAtNode(AXEventGenerator::Event::CONTROLS_CHANGED, 6),
           HasEventAtNode(AXEventGenerator::Event::LANGUAGE_CHANGED, 2),
           HasEventAtNode(AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED, 3),
-          HasEventAtNode(AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED, 4),
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 4),
           HasEventAtNode(AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED, 5),
           HasEventAtNode(AXEventGenerator::Event::RELATED_NODE_CHANGED, 6)));
 }
diff --git a/ui/accessibility/ax_tree_id.h b/ui/accessibility/ax_tree_id.h
index f2387214..354ef7c 100644
--- a/ui/accessibility/ax_tree_id.h
+++ b/ui/accessibility/ax_tree_id.h
@@ -9,8 +9,8 @@
 
 #include "base/no_destructor.h"
 #include "base/unguessable_token.h"
+#include "ui/accessibility/ax_base_export.h"
 #include "ui/accessibility/ax_enums.mojom-forward.h"
-#include "ui/accessibility/ax_export.h"
 
 namespace mojo {
 template <typename DataViewType, typename T>
@@ -26,7 +26,7 @@
 namespace ui {
 
 // A unique ID representing an accessibility tree.
-class AX_EXPORT AXTreeID {
+class AX_BASE_EXPORT AXTreeID {
  public:
   // Create an Unknown AXTreeID.
   AXTreeID();
@@ -73,14 +73,15 @@
 };
 
 // For use in std::unordered_map.
-struct AXTreeIDHash {
+struct AX_BASE_EXPORT AXTreeIDHash {
   size_t operator()(const ui::AXTreeID& tree_id) const;
 };
 
-AX_EXPORT std::ostream& operator<<(std::ostream& stream, const AXTreeID& value);
+AX_BASE_EXPORT std::ostream& operator<<(std::ostream& stream,
+                                        const AXTreeID& value);
 
 // The value to use when an AXTreeID is unknown.
-AX_EXPORT extern const AXTreeID& AXTreeIDUnknown();
+AX_BASE_EXPORT extern const AXTreeID& AXTreeIDUnknown();
 
 }  // namespace ui
 
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index f71a9d3..033b310 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -3345,6 +3345,16 @@
       GetData().GetCheckedState() != ax::mojom::CheckedState::kFalse);
 }
 
+void AXPlatformNodeAuraLinux::OnEnabledChanged() {
+  AtkObject* obj = GetOrCreateAtkObject();
+  if (!obj)
+    return;
+
+  atk_object_notify_state_change(
+      obj, ATK_STATE_ENABLED,
+      GetData().GetRestriction() != ax::mojom::Restriction::kDisabled);
+}
+
 void AXPlatformNodeAuraLinux::OnExpandedStateChanged(bool is_expanded) {
   // When a list box is expanded, it becomes visible. This means that it might
   // now have a different role (the role for hidden Views is kUnknown).  We
@@ -3737,6 +3747,21 @@
                         UTF16ToUnicodeOffsetInText(selection.second));
 }
 
+void AXPlatformNodeAuraLinux::OnTextAttributesChanged() {
+  if (!EmitsAtkTextEvents()) {
+    if (auto* parent = FromAtkObject(GetParent()))
+      parent->OnTextAttributesChanged();
+    return;
+  }
+
+  AtkObject* atk_object = GetOrCreateAtkObject();
+  if (!atk_object)
+    return;
+
+  DCHECK(ATK_IS_TEXT(atk_object));
+  g_signal_emit_by_name(atk_object, "text-attributes-changed");
+}
+
 void AXPlatformNodeAuraLinux::OnTextSelectionChanged() {
   int32_t anchor_node_id, focus_node_id;
   int anchor_offset, focus_offset;
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h
index 74d60fae..0d0cbdb 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -201,6 +201,7 @@
   // Event helpers
   void OnActiveDescendantChanged();
   void OnCheckedStateChanged();
+  void OnEnabledChanged();
   void OnExpandedStateChanged(bool is_expanded);
   void OnFocused();
   void OnWindowActivated();
@@ -210,6 +211,7 @@
   void OnAllMenusEnded();
   void OnSelected();
   void OnSelectedChildrenChanged();
+  void OnTextAttributesChanged();
   void OnTextSelectionChanged();
   void OnValueChanged();
   void OnNameChanged();
diff --git a/ui/base/clipboard/clipboard_data.cc b/ui/base/clipboard/clipboard_data.cc
index 4eac6f65..e9cb983 100644
--- a/ui/base/clipboard/clipboard_data.cc
+++ b/ui/base/clipboard/clipboard_data.cc
@@ -45,7 +45,9 @@
          custom_data_format_ == that.custom_data_format() &&
          custom_data_data_ == that.custom_data_data() &&
          web_smart_paste_ == that.web_smart_paste() &&
-         gfx::BitmapsAreEqual(bitmap_, that.bitmap());
+         gfx::BitmapsAreEqual(bitmap_, that.bitmap()) &&
+         (src_.get() ? (that.source() && *src_.get() == *that.source())
+                     : !that.source());
 }
 
 void ClipboardData::SetBitmapData(const SkBitmap& bitmap) {
diff --git a/ui/base/clipboard/clipboard_data_endpoint.cc b/ui/base/clipboard/clipboard_data_endpoint.cc
index e10baf6..46ee0c5 100644
--- a/ui/base/clipboard/clipboard_data_endpoint.cc
+++ b/ui/base/clipboard/clipboard_data_endpoint.cc
@@ -22,6 +22,11 @@
 ClipboardDataEndpoint& ClipboardDataEndpoint::operator=(
     ClipboardDataEndpoint&& other) = default;
 
+bool ClipboardDataEndpoint::operator==(
+    const ClipboardDataEndpoint& other) const {
+  return url_ == other.url_;
+}
+
 ClipboardDataEndpoint::~ClipboardDataEndpoint() = default;
 
 }  // namespace ui
diff --git a/ui/base/clipboard/clipboard_data_endpoint.h b/ui/base/clipboard/clipboard_data_endpoint.h
index 55de3de..0dfb546c 100644
--- a/ui/base/clipboard/clipboard_data_endpoint.h
+++ b/ui/base/clipboard/clipboard_data_endpoint.h
@@ -22,6 +22,8 @@
   ClipboardDataEndpoint& operator=(const ClipboardDataEndpoint& other);
   ClipboardDataEndpoint& operator=(ClipboardDataEndpoint&& other);
 
+  bool operator==(const ClipboardDataEndpoint& other) const;
+
   ~ClipboardDataEndpoint();
 
  private:
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index d21aa94b..b422119 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -15,7 +15,6 @@
 #include "base/files/file_path.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
@@ -23,6 +22,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_offset_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/win/message_window.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/scoped_hdc.h"
@@ -232,7 +232,7 @@
 
 // ClipboardWin implementation.
 ClipboardWin::ClipboardWin() {
-  if (base::MessageLoopCurrentForUI::IsSet())
+  if (base::CurrentUIThread::IsSet())
     clipboard_owner_ = std::make_unique<base::win::MessageWindow>();
 }
 
diff --git a/ui/base/ime/win/tsf_bridge.cc b/ui/base/ime/win/tsf_bridge.cc
index 659d9038..2f5171e0 100644
--- a/ui/base/ime/win/tsf_bridge.cc
+++ b/ui/base/ime/win/tsf_bridge.cc
@@ -8,9 +8,9 @@
 
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_local_storage.h"
 #include "base/win/scoped_variant.h"
 #include "ui/base/ime/input_method_delegate.h"
@@ -140,7 +140,7 @@
 TSFBridgeImpl::TSFBridgeImpl() = default;
 
 TSFBridgeImpl::~TSFBridgeImpl() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (!IsInitialized())
     return;
 
@@ -167,7 +167,7 @@
 }
 
 bool TSFBridgeImpl::Initialize() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (client_id_ != TF_CLIENTID_NULL) {
     DVLOG(1) << "Already initialized.";
     return false;
@@ -217,7 +217,7 @@
 }
 
 void TSFBridgeImpl::OnTextInputTypeChanged(const TextInputClient* client) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(IsInitialized());
 
   if (client != client_) {
@@ -259,7 +259,7 @@
 }
 
 bool TSFBridgeImpl::CancelComposition() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(IsInitialized());
 
   TSFDocument* document = GetAssociatedDocument();
@@ -272,7 +272,7 @@
 }
 
 bool TSFBridgeImpl::ConfirmComposition() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(IsInitialized());
 
   TSFDocument* document = GetAssociatedDocument();
@@ -286,7 +286,7 @@
 
 void TSFBridgeImpl::SetFocusedClient(HWND focused_window,
                                      TextInputClient* client) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(client);
   DCHECK(IsInitialized());
   if (attached_window_handle_ != focused_window)
@@ -306,7 +306,7 @@
 }
 
 void TSFBridgeImpl::RemoveFocusedClient(TextInputClient* client) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   if (!IsInitialized())
     return;
   if (client_ != client)
@@ -324,7 +324,7 @@
 
 void TSFBridgeImpl::SetInputMethodDelegate(
     internal::InputMethodDelegate* delegate) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(delegate);
   DCHECK(IsInitialized());
 
@@ -337,7 +337,7 @@
 }
 
 void TSFBridgeImpl::RemoveInputMethodDelegate() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(IsInitialized());
 
   for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
@@ -362,7 +362,7 @@
 }
 
 Microsoft::WRL::ComPtr<ITfThreadMgr> TSFBridgeImpl::GetThreadManager() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(IsInitialized());
   return thread_manager_;
 }
@@ -584,7 +584,7 @@
 
 // static
 void TSFBridge::Initialize() {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     DVLOG(1) << "Do not use TSFBridge without UI thread.";
     return;
   }
@@ -601,7 +601,7 @@
 
 // static
 TSFBridge* TSFBridge::ReplaceForTesting(TSFBridge* bridge) {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     DVLOG(1) << "Do not use TSFBridge without UI thread.";
     return nullptr;
   }
@@ -612,7 +612,7 @@
 
 // static
 void TSFBridge::Shutdown() {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     DVLOG(1) << "Do not use TSFBridge without UI thread.";
   }
   TSFBridgeImpl* delegate = static_cast<TSFBridgeImpl*>(TSFBridgeTLS().Get());
@@ -622,7 +622,7 @@
 
 // static
 TSFBridge* TSFBridge::GetInstance() {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     DVLOG(1) << "Do not use TSFBridge without UI thread.";
     return nullptr;
   }
diff --git a/ui/base/ime/win/tsf_input_scope.cc b/ui/base/ime/win/tsf_input_scope.cc
index 9db8c86..d60126e 100644
--- a/ui/base/ime/win/tsf_input_scope.cc
+++ b/ui/base/ime/win/tsf_input_scope.cc
@@ -9,8 +9,8 @@
 #include "base/check.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/win/windows_version.h"
 
 namespace ui {
@@ -155,7 +155,7 @@
 }  // namespace
 
 void InitializeTsfForInputScopes() {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   // Thread safety is not required because this function is under UI thread.
   if (!g_get_proc_done) {
     g_get_proc_done = true;
diff --git a/ui/base/pointer/touch_ui_controller.cc b/ui/base/pointer/touch_ui_controller.cc
index 326da1d..d91151b4 100644
--- a/ui/base/pointer/touch_ui_controller.cc
+++ b/ui/base/pointer/touch_ui_controller.cc
@@ -9,9 +9,9 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/user_metrics.h"
 #include "base/no_destructor.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/base/ui_base_switches.h"
 
@@ -78,7 +78,7 @@
 TouchUiController::TouchUiController(TouchUiState touch_ui_state)
     : touch_ui_state_(touch_ui_state) {
 #if defined(OS_WIN)
-  if (base::MessageLoopCurrentForUI::IsSet() &&
+  if (base::CurrentUIThread::IsSet() &&
       (base::win::GetVersion() >= base::win::Version::WIN10)) {
     singleton_hwnd_observer_ =
         std::make_unique<gfx::SingletonHwndObserver>(base::BindRepeating(
diff --git a/ui/base/test/scoped_fake_nswindow_fullscreen.mm b/ui/base/test/scoped_fake_nswindow_fullscreen.mm
index 56453e6f..87f65b41 100644
--- a/ui/base/test/scoped_fake_nswindow_fullscreen.mm
+++ b/ui/base/test/scoped_fake_nswindow_fullscreen.mm
@@ -12,8 +12,8 @@
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 
 // Donates a testing implementation of [NSWindow toggleFullScreen:].
@@ -105,7 +105,7 @@
     [[NSNotificationCenter defaultCenter]
         postNotificationName:NSWindowWillStartLiveResizeNotification
                       object:window];
-    DCHECK(base::MessageLoopCurrentForUI::IsSet());
+    DCHECK(base::CurrentUIThread::IsSet());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(&Impl::FinishEnterFullscreen, base::Unretained(this),
@@ -145,7 +145,7 @@
         postNotificationName:NSWindowWillExitFullScreenNotification
                       object:window_];
 
-    DCHECK(base::MessageLoopCurrentForUI::IsSet());
+    DCHECK(base::CurrentUIThread::IsSet());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(&Impl::FinishExitFullscreen, base::Unretained(this)));
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm
index cdffb90..979aca2 100644
--- a/ui/base/test/ui_controls_mac.mm
+++ b/ui/base/test/ui_controls_mac.mm
@@ -11,8 +11,8 @@
 #include "base/callback.h"
 #import "base/mac/foundation_util.h"
 #import "base/mac/scoped_objc_class_swizzler.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #include "ui/events/keycodes/keyboard_code_conversion_mac.h"
@@ -266,7 +266,7 @@
                                 bool command,
                                 base::OnceClosure task) {
   CHECK(g_ui_controls_enabled);
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   std::vector<NSEvent*> events;
   SynthesizeKeyEventsSequence(window.GetNativeNSWindow(), key, control, shift,
diff --git a/ui/base/x/x11_error_handler.cc b/ui/base/x/x11_error_handler.cc
index a45282f4..e63bb8f 100644
--- a/ui/base/x/x11_error_handler.cc
+++ b/ui/base/x/x11_error_handler.cc
@@ -8,8 +8,8 @@
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/sequenced_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/gfx/x/xproto_util.h"
@@ -45,7 +45,7 @@
 }
 
 int BrowserX11IOErrorHandler(Display* d) {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     // Wait for the UI thread (which has a different connection to the X server)
     // to get the error. We can't call shutdown from this thread without
     // tripping an error. Doing it through a function so that we'll be able
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 58e6b5a3..837cc1f 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -27,7 +27,6 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/singleton.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
@@ -37,6 +36,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_byteorder.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_local_storage.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -97,7 +97,7 @@
   if (TLSDestructionCheckerForX11::HasBeenDestroyed())
     return 0;
 
-  if (base::MessageLoopCurrent::Get()) {
+  if (base::CurrentThread::Get()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&x11::LogErrorEventDescription, *e));
   } else {
diff --git a/ui/base/x/x11_whole_screen_move_loop.cc b/ui/base/x/x11_whole_screen_move_loop.cc
index c1bdce6..b3e1a282 100644
--- a/ui/base/x/x11_whole_screen_move_loop.cc
+++ b/ui/base/x/x11_whole_screen_move_loop.cc
@@ -11,10 +11,10 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/base/x/x11_pointer_grab.h"
 #include "ui/base/x/x11_util.h"
@@ -89,7 +89,7 @@
 }
 
 uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   // This method processes all events while the move loop is active.
   if (!in_move_loop_)
diff --git a/ui/events/ozone/device/udev/device_manager_udev.cc b/ui/events/ozone/device/udev/device_manager_udev.cc
index 9bd6ddd..9473353 100644
--- a/ui/events/ozone/device/udev/device_manager_udev.cc
+++ b/ui/events/ozone/device/udev/device_manager_udev.cc
@@ -7,9 +7,9 @@
 #include <stddef.h>
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/events/ozone/device/device_event.h"
 #include "ui/events/ozone/device/device_event_observer.h"
@@ -95,7 +95,7 @@
   if (monitor_) {
     int fd = device::udev_monitor_get_fd(monitor_.get());
     CHECK_GT(fd, 0);
-    base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+    base::CurrentUIThread::Get()->WatchFileDescriptor(
         fd, true, base::MessagePumpForUI::WATCH_READ, &controller_, this);
   }
 }
diff --git a/ui/events/ozone/evdev/event_converter_evdev.cc b/ui/events/ozone/evdev/event_converter_evdev.cc
index fe6e641c..ff00d8a1 100644
--- a/ui/events/ozone/evdev/event_converter_evdev.cc
+++ b/ui/events/ozone/evdev/event_converter_evdev.cc
@@ -10,7 +10,7 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/devices/device_util_linux.h"
@@ -51,7 +51,7 @@
 }
 
 void EventConverterEvdev::Start() {
-  base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+  base::CurrentUIThread::Get()->WatchFileDescriptor(
       fd_, true, base::MessagePumpForUI::WATCH_READ, &controller_, this);
   watching_ = true;
 }
diff --git a/ui/events/ozone/evdev/event_converter_evdev.h b/ui/events/ozone/evdev/event_converter_evdev.h
index 717410f2..3c12fd8 100644
--- a/ui/events/ozone/evdev/event_converter_evdev.h
+++ b/ui/events/ozone/evdev/event_converter_evdev.h
@@ -14,7 +14,7 @@
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "ui/events/devices/gamepad_device.h"
 #include "ui/events/devices/input_device.h"
 #include "ui/events/ozone/evdev/event_dispatch_callback.h"
diff --git a/ui/events/platform/x11/x11_event_watcher_fdwatch.cc b/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
index 27f70c0..b71d1ca8 100644
--- a/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
+++ b/ui/events/platform/x11/x11_event_watcher_fdwatch.cc
@@ -4,7 +4,7 @@
 
 #include "ui/events/platform/x11/x11_event_watcher_fdwatch.h"
 
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "ui/gfx/x/x11.h"
 
 namespace ui {
@@ -17,13 +17,13 @@
 }
 
 void X11EventWatcherFdWatch::StartWatching() {
-  if (started_ || !base::MessageLoopCurrent::Get())
+  if (started_ || !base::CurrentThread::Get())
     return;
 
   DCHECK(event_source_->connection()) << "Unable to get connection to X server";
 
   int fd = ConnectionNumber(event_source_->connection()->display());
-  base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+  base::CurrentUIThread::Get()->WatchFileDescriptor(
       fd, true, base::MessagePumpForUI::WATCH_READ, &watcher_controller_, this);
   started_ = true;
 }
diff --git a/ui/file_manager/base/js/filtered_volume_manager.js b/ui/file_manager/base/js/filtered_volume_manager.js
index 0cfffe80..ebee03e0 100644
--- a/ui/file_manager/base/js/filtered_volume_manager.js
+++ b/ui/file_manager/base/js/filtered_volume_manager.js
@@ -170,7 +170,7 @@
 
     // Cache volumeInfoList.
     const volumeInfoList = [];
-    for (var i = 0; i < this.volumeManager_.volumeInfoList.length; i++) {
+    for (let i = 0; i < this.volumeManager_.volumeInfoList.length; i++) {
       const volumeInfo = this.volumeManager_.volumeInfoList.item(i);
       // TODO(hidehiko): Filter mounted volumes located on Drive File System.
       if (!this.isAllowedVolume_(volumeInfo)) {
@@ -244,24 +244,24 @@
   onVolumeInfoListUpdated_(event) {
     // Filters some volumes.
     let index = event.index;
-    for (var i = 0; i < event.index; i++) {
-      var volumeInfo = this.volumeManager_.volumeInfoList.item(i);
+    for (let i = 0; i < event.index; i++) {
+      const volumeInfo = this.volumeManager_.volumeInfoList.item(i);
       if (!this.isAllowedVolume_(volumeInfo)) {
         index--;
       }
     }
 
     let numRemovedVolumes = 0;
-    for (var i = 0; i < event.removed.length; i++) {
-      var volumeInfo = event.removed[i];
+    for (let i = 0; i < event.removed.length; i++) {
+      const volumeInfo = event.removed[i];
       if (this.isAllowedVolume_(volumeInfo)) {
         numRemovedVolumes++;
       }
     }
 
     const addedVolumes = [];
-    for (var i = 0; i < event.added.length; i++) {
-      var volumeInfo = event.added[i];
+    for (let i = 0; i < event.added.length; i++) {
+      const volumeInfo = event.added[i];
       if (this.isAllowedVolume_(volumeInfo)) {
         addedVolumes.push(volumeInfo);
       }
diff --git a/ui/file_manager/file_manager/background/js/mock_volume_manager.js b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
index b5acc79..49702bb 100644
--- a/ui/file_manager/file_manager/background/js/mock_volume_manager.js
+++ b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
@@ -104,9 +104,9 @@
     }
 
     if (entry.filesystem.name === VolumeManagerCommon.VolumeType.DRIVE) {
-      var volumeInfo = this.volumeInfoList.item(0);
-      var rootType = VolumeManagerCommon.RootType.DRIVE;
-      var isRootEntry = entry.fullPath === '/root';
+      const volumeInfo = this.volumeInfoList.item(0);
+      let rootType = VolumeManagerCommon.RootType.DRIVE;
+      let isRootEntry = entry.fullPath === '/root';
       if (entry.fullPath.startsWith('/team_drives')) {
         if (entry.fullPath === '/team_drives') {
           rootType = VolumeManagerCommon.RootType.SHARED_DRIVES_GRAND_ROOT;
@@ -127,10 +127,10 @@
       return new EntryLocationImpl(volumeInfo, rootType, isRootEntry, true);
     }
 
-    volumeInfo = this.getVolumeInfo(entry);
-    rootType =
+    const volumeInfo = this.getVolumeInfo(entry);
+    const rootType =
         VolumeManagerCommon.getRootTypeFromVolumeType(volumeInfo.volumeType);
-    isRootEntry = util.isSameEntry(entry, volumeInfo.fileSystem.root);
+    const isRootEntry = util.isSameEntry(entry, volumeInfo.fileSystem.root);
     return new EntryLocationImpl(volumeInfo, rootType, isRootEntry, false);
   }
 
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index 0c2b974..45aaa22a 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -3392,20 +3392,6 @@
   margin-top: 2px;
 }
 
-/*
- * TODO(files-ng): remove these rules and do them in the multi-menu JS because
- * #tasks-menu is distinguished here: it is used as a menu and a submenu, thus
- * gets 8px margin-top in all cases.  It should only have this 8px gap when it
- * is shown as a menu; it should have no margin-top when it is a submenu (just
- * like every other submenu in files app - none of them have margin-top).
- */
-body.files-ng #gear-menu,
-body.files-ng #share-menu,
-body.files-ng #sort-menu,
-body.files-ng #tasks-menu {
-  margin-top: 8px;
-}
-
 #gear-menu > cr-menu-item:not(.menuitem-button),
 #sort-menu > cr-menu-item {
   margin-inline-end: 50px;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_button.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_button.js
index c6e99d7..567c3eb7 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_button.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_button.js
@@ -393,6 +393,11 @@
      */
     positionMenu_() {
       const style = this.menu.style;
+
+      if (util.isFilesNg()) {
+        style.marginTop = '8px';  // crbug.com/1066727
+      }
+
       // Clear any maxHeight we've set from previous calls into here.
       style.maxHeight = 'none';
       const invertLeftRight = false;
diff --git a/ui/gfx/animation/animation_mac.mm b/ui/gfx/animation/animation_mac.mm
index 11db9646..175ceff 100644
--- a/ui/gfx/animation/animation_mac.mm
+++ b/ui/gfx/animation/animation_mac.mm
@@ -7,7 +7,7 @@
 #import <Cocoa/Cocoa.h>
 
 #include "base/mac/mac_util.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 
 // Only available since 10.12.
 @interface NSWorkspace (AvailableSinceSierra)
@@ -25,8 +25,7 @@
 bool Animation::ScrollAnimationsEnabledBySystem() {
   // Because of sandboxing, OS settings should only be queried from the browser
   // process.
-  DCHECK(base::MessageLoopCurrentForUI::IsSet() ||
-         base::MessageLoopCurrentForIO::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet() || base::CurrentIOThread::IsSet());
 
   bool enabled = false;
   id value = nil;
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc
index 3b598746..9b00c712 100644
--- a/ui/gfx/font_fallback_win.cc
+++ b/ui/gfx/font_fallback_win.cc
@@ -9,12 +9,12 @@
 
 #include "base/macros.h"
 #include "base/memory/singleton.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "base/win/registry.h"
 #include "ui/gfx/font.h"
@@ -238,7 +238,7 @@
   // browser process because we can use the shared system fallback, but in the
   // renderer this can cause hangs. Code that needs font fallback in the
   // renderer should instead use the font proxy.
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   // The text passed must be at least length 1.
   if (text.empty())
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 649ade3..532623e 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -18,7 +18,6 @@
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
@@ -28,6 +27,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "third_party/icu/source/common/unicode/ubidi.h"
@@ -2153,7 +2153,7 @@
   std::vector<internal::TextRunHarfBuzz*> runs_with_missing_glyphs;
   for (internal::TextRunHarfBuzz*& run : *in_out_runs) {
     // First do a cache lookup.
-    bool can_use_cache = base::MessageLoopCurrentForUI::IsSet() &&
+    bool can_use_cache = base::CurrentUIThread::IsSet() &&
                          run->range.length() <= kMaxRunLengthToCache;
     bool found_in_cache = false;
     const internal::ShapeRunWithFontInput cache_key(
diff --git a/ui/gfx/win/singleton_hwnd.cc b/ui/gfx/win/singleton_hwnd.cc
index a024453..1476b11 100644
--- a/ui/gfx/win/singleton_hwnd.cc
+++ b/ui/gfx/win/singleton_hwnd.cc
@@ -5,7 +5,7 @@
 #include "ui/gfx/win/singleton_hwnd.h"
 
 #include "base/memory/singleton.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "ui/gfx/win/singleton_hwnd_observer.h"
 
 namespace gfx {
@@ -21,7 +21,7 @@
                                          LPARAM lparam,
                                          LRESULT& result,
                                          DWORD msg_map_id) {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     // If there is no MessageLoop and SingletonHwnd is receiving messages, this
     // means it is receiving messages via an external message pump such as COM
     // uninitialization.
@@ -37,7 +37,7 @@
 }
 
 SingletonHwnd::SingletonHwnd() {
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     // Creating this window in (e.g.) a renderer inhibits shutdown on
     // Windows. See http://crbug.com/230122 and http://crbug.com/236039.
     return;
diff --git a/ui/gtk/x/gtk_ui_delegate_x11.cc b/ui/gtk/x/gtk_ui_delegate_x11.cc
index da59fe7..2675f3d 100644
--- a/ui/gtk/x/gtk_ui_delegate_x11.cc
+++ b/ui/gtk/x/gtk_ui_delegate_x11.cc
@@ -63,7 +63,9 @@
 void GtkUiDelegateX11::ClearTransientFor(gfx::AcceleratedWidget parent) {
   ui::X11Window* parent_window =
       ui::X11WindowManager::GetInstance()->GetWindow(parent);
-  parent_window->SetTransientWindow(x11::Window::None);
+  // parent_window might be dead if there was a top-down window close
+  if (parent_window)
+    parent_window->SetTransientWindow(x11::Window::None);
 }
 
 GdkDisplay* GtkUiDelegateX11::GetGdkDisplay() {
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc
index 757a5e7..4d37841 100644
--- a/ui/message_center/message_center_impl_unittest.cc
+++ b/ui/message_center/message_center_impl_unittest.cc
@@ -10,11 +10,11 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -415,7 +415,7 @@
   scoped_refptr<base::TestMockTimeTaskRunner> task_runner(
       new base::TestMockTimeTaskRunner(base::Time::Now(),
                                        base::TimeTicks::Now()));
-  base::MessageLoopCurrent::Get()->SetTaskRunner(task_runner);
+  base::CurrentThread::Get()->SetTaskRunner(task_runner);
 
   NotifierId notifier_id(GURL("https://example.com"));
 
@@ -456,7 +456,7 @@
   task_runner->FastForwardBy(base::TimeDelta::FromSeconds(2));
   ASSERT_EQ(popup_timers_controller->timer_finished(), 1);
 
-  base::MessageLoopCurrent::Get()->SetTaskRunner(old_task_runner);
+  base::CurrentThread::Get()->SetTaskRunner(old_task_runner);
 }
 
 TEST_F(MessageCenterImplTest, Renotify) {
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc
index 943816d..cc5e8c5 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -16,8 +16,8 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/free_deleter.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
+#include "base/task/current_thread.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
@@ -206,19 +206,19 @@
 
  private:
   void Register() {
-    DCHECK(base::MessageLoopCurrentForIO::IsSet());
-    base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
+    DCHECK(base::CurrentIOThread::IsSet());
+    base::CurrentIOThread::Get()->WatchFileDescriptor(
         fd_, true, base::MessagePumpForIO::WATCH_READ, &controller_, this);
   }
 
   void Unregister() {
-    DCHECK(base::MessageLoopCurrentForIO::IsSet());
+    DCHECK(base::CurrentIOThread::IsSet());
     controller_.StopWatchingFileDescriptor();
   }
 
   // base::MessagePumpLibevent::FdWatcher overrides:
   void OnFileCanReadWithoutBlocking(int fd) override {
-    DCHECK(base::MessageLoopCurrentForIO::IsSet());
+    DCHECK(base::CurrentIOThread::IsSet());
     TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd);
 
     if (!ProcessDrmEvent(
diff --git a/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
index fcd5d1c..47b89267 100644
--- a/ui/ozone/platform/scenic/ozone_platform_scenic.cc
+++ b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -11,9 +11,9 @@
 #include "base/check.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/notreached.h"
+#include "base/task/current_thread.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "ui/base/cursor/cursor_factory.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
@@ -61,9 +61,8 @@
 };
 
 // OzonePlatform for Scenic.
-class OzonePlatformScenic
-    : public OzonePlatform,
-      public base::MessageLoopCurrent::DestructionObserver {
+class OzonePlatformScenic : public OzonePlatform,
+                            public base::CurrentThread::DestructionObserver {
  public:
   OzonePlatformScenic() = default;
   ~OzonePlatformScenic() override = default;
@@ -188,7 +187,7 @@
     surface_factory_->Initialize(std::move(gpu_host_remote));
     bound_in_main_process_ = true;
 
-    base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+    base::CurrentThread::Get()->AddDestructionObserver(this);
   }
 
   void ShutdownInMainProcess() {
@@ -199,7 +198,7 @@
     bound_in_main_process_ = false;
   }
 
-  // base::MessageLoopCurrent::DestructionObserver implementation.
+  // base::CurrentThread::DestructionObserver implementation.
   void WillDestroyCurrentMessageLoop() override { ShutdownInMainProcess(); }
 
   std::unique_ptr<ScenicWindowManager> window_manager_;
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
index 734e8b2..07934f5 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -114,7 +114,7 @@
 
   if (!use_egl_fence_sync_ || !frame->schedule_planes_succeeded) {
     frame->ready = true;
-    SubmitFrame();
+    MaybeSubmitFrames();
     return;
   }
 
@@ -216,33 +216,32 @@
     overlay.Flush();
 }
 
-void GbmSurfacelessWayland::SubmitFrame() {
-  DCHECK(!unsubmitted_frames_.empty());
-
-  if (unsubmitted_frames_.front()->ready && !submitted_frame_) {
-    submitted_frame_ = std::move(unsubmitted_frames_.front());
+void GbmSurfacelessWayland::MaybeSubmitFrames() {
+  while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) {
+    auto submitted_frame = std::move(unsubmitted_frames_.front());
     unsubmitted_frames_.erase(unsubmitted_frames_.begin());
 
-    if (!submitted_frame_->schedule_planes_succeeded) {
+    if (!submitted_frame->schedule_planes_succeeded) {
       last_swap_buffers_result_ = false;
 
-      std::move(submitted_frame_->completion_callback)
+      std::move(submitted_frame->completion_callback)
           .Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_FAILED));
       // Notify the caller, the buffer is never presented on a screen.
-      std::move(submitted_frame_->presentation_callback)
+      std::move(submitted_frame->presentation_callback)
           .Run(gfx::PresentationFeedback::Failure());
 
-      submitted_frame_.reset();
+      submitted_frame.reset();
       return;
     }
 
-    DCHECK_EQ(submitted_frame_->planes.size(), 1u);
-    submitted_frame_->buffer_id = submitted_frame_->planes.back().buffer_id;
+    DCHECK_EQ(submitted_frame->planes.size(), 1u);
+    submitted_frame->buffer_id = submitted_frame->planes.back().buffer_id;
     buffer_manager_->CommitBuffer(widget_,
-                                  submitted_frame_->planes.back().buffer_id,
-                                  submitted_frame_->damage_region_);
+                                  submitted_frame->planes.back().buffer_id,
+                                  submitted_frame->damage_region_);
+    submitted_frame->planes.clear();
 
-    submitted_frame_->planes.clear();
+    submitted_frames_.push_back(std::move(submitted_frame));
   }
 }
 
@@ -256,7 +255,7 @@
 
 void GbmSurfacelessWayland::FenceRetired(PendingFrame* frame) {
   frame->ready = true;
-  SubmitFrame();
+  MaybeSubmitFrames();
 }
 
 void GbmSurfacelessWayland::SetNoGLFlushForTests() {
@@ -265,26 +264,33 @@
 
 void GbmSurfacelessWayland::OnSubmission(uint32_t buffer_id,
                                          const gfx::SwapResult& swap_result) {
-  submitted_frame_->overlays.clear();
+  // submitted_frames_ may temporarily have more than one buffer in it if
+  // buffers are released out of order by the Wayland server.
+  DCHECK(!submitted_frames_.empty());
 
-  DCHECK_EQ(submitted_frame_->buffer_id, buffer_id);
-  std::move(submitted_frame_->completion_callback)
+  auto submitted_frame = std::move(submitted_frames_.front());
+  submitted_frames_.erase(submitted_frames_.begin());
+  submitted_frame->overlays.clear();
+
+  DCHECK_EQ(submitted_frame->buffer_id, buffer_id);
+  std::move(submitted_frame->completion_callback)
       .Run(gfx::SwapCompletionResult(swap_result));
 
-  pending_presentation_frames_.push_back(std::move(submitted_frame_));
+  pending_presentation_frames_.push_back(std::move(submitted_frame));
 
   if (swap_result != gfx::SwapResult::SWAP_ACK) {
     last_swap_buffers_result_ = false;
     return;
   }
 
-  SubmitFrame();
+  MaybeSubmitFrames();
 }
 
 void GbmSurfacelessWayland::OnPresentation(
     uint32_t buffer_id,
     const gfx::PresentationFeedback& feedback) {
   DCHECK(!pending_presentation_frames_.empty());
+
   auto* frame = pending_presentation_frames_.front().get();
   DCHECK_EQ(frame->buffer_id, buffer_id);
   std::move(frame->presentation_callback).Run(feedback);
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
index 137bea2..cfc5377 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
+++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -103,7 +103,7 @@
     std::vector<PlaneData> planes;
   };
 
-  void SubmitFrame();
+  void MaybeSubmitFrames();
 
   EGLSyncKHR InsertFence(bool implicit);
   void FenceRetired(PendingFrame* frame);
@@ -116,8 +116,8 @@
   // The native surface. Deleting this is allowed to free the EGLNativeWindow.
   gfx::AcceleratedWidget widget_;
   std::vector<std::unique_ptr<PendingFrame>> unsubmitted_frames_;
+  std::vector<std::unique_ptr<PendingFrame>> submitted_frames_;
   std::vector<std::unique_ptr<PendingFrame>> pending_presentation_frames_;
-  std::unique_ptr<PendingFrame> submitted_frame_;
   bool has_implicit_external_sync_;
   bool last_swap_buffers_result_ = true;
   bool use_egl_fence_sync_ = true;
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
index 20e8736b..9e3a869 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/process/process.h"
+#include "base/task/current_thread.h"
 #include "ui/gfx/linux/drm_util_linux.h"
 #include "ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h"
 
@@ -38,9 +38,11 @@
 void WaylandBufferManagerGpu::OnSubmission(gfx::AcceleratedWidget widget,
                                            uint32_t buffer_id,
                                            gfx::SwapResult swap_result) {
+  base::AutoLock scoped_lock(lock_);
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
+  DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
   // Return back to the same thread where the commit request came from.
-  commit_thread_runner_->PostTask(
+  commit_thread_runners_.find(widget)->second->PostTask(
       FROM_HERE,
       base::BindOnce(&WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread,
                      base::Unretained(this), widget, buffer_id, swap_result));
@@ -50,24 +52,28 @@
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
     const gfx::PresentationFeedback& feedback) {
+  base::AutoLock scoped_lock(lock_);
   DCHECK(io_thread_runner_->BelongsToCurrentThread());
+  DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
   // Return back to the same thread where the commit request came from.
-  commit_thread_runner_->PostTask(
+  commit_thread_runners_.find(widget)->second->PostTask(
       FROM_HERE,
-      base::BindOnce(
-          &WaylandBufferManagerGpu::SubmitPresentationtOnOriginThread,
-          base::Unretained(this), widget, buffer_id, feedback));
+      base::BindOnce(&WaylandBufferManagerGpu::SubmitPresentationOnOriginThread,
+                     base::Unretained(this), widget, buffer_id, feedback));
 }
 
 void WaylandBufferManagerGpu::RegisterSurface(gfx::AcceleratedWidget widget,
                                               WaylandSurfaceGpu* surface) {
   base::AutoLock scoped_lock(lock_);
   widget_to_surface_map_.emplace(widget, surface);
+  commit_thread_runners_.insert(
+      std::make_pair(widget, base::ThreadTaskRunnerHandle::Get()));
 }
 
 void WaylandBufferManagerGpu::UnregisterSurface(gfx::AcceleratedWidget widget) {
   base::AutoLock scoped_lock(lock_);
   widget_to_surface_map_.erase(widget);
+  commit_thread_runners_.erase(widget);
 }
 
 WaylandSurfaceGpu* WaylandBufferManagerGpu::GetSurface(
@@ -133,9 +139,6 @@
     return;
   }
 
-  if (!commit_thread_runner_)
-    commit_thread_runner_ = base::ThreadTaskRunnerHandle::Get();
-
   // Do the mojo call on the IO child thread.
   io_thread_runner_->PostTask(
       FROM_HERE,
@@ -233,25 +236,37 @@
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
     gfx::SwapResult swap_result) {
-  DCHECK(commit_thread_runner_->BelongsToCurrentThread());
   DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
   auto* surface = GetSurface(widget);
   // The surface might be destroyed by the time the swap result is provided.
-  if (surface)
+  if (surface) {
+#if DCHECK_IS_ON()
+    base::AutoLock scoped_lock(lock_);
+    DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
+    DCHECK(
+        commit_thread_runners_.find(widget)->second->BelongsToCurrentThread());
+#endif
     surface->OnSubmission(buffer_id, swap_result);
+  }
 }
 
-void WaylandBufferManagerGpu::SubmitPresentationtOnOriginThread(
+void WaylandBufferManagerGpu::SubmitPresentationOnOriginThread(
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
     const gfx::PresentationFeedback& feedback) {
-  DCHECK(commit_thread_runner_->BelongsToCurrentThread());
   DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
   auto* surface = GetSurface(widget);
   // The surface might be destroyed by the time the presentation feedback is
   // provided.
-  if (surface)
+  if (surface) {
+#if DCHECK_IS_ON()
+    base::AutoLock scoped_lock(lock_);
+    DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
+    DCHECK(
+        commit_thread_runners_.find(widget)->second->BelongsToCurrentThread());
+#endif
     surface->OnPresentation(buffer_id, feedback);
+  }
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
index 819d64a9..f30fcf9 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
@@ -5,6 +5,7 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_
 #define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_
 
+#include <map>
 #include <memory>
 
 #include "base/macros.h"
@@ -152,7 +153,7 @@
   void SubmitSwapResultOnOriginThread(gfx::AcceleratedWidget widget,
                                       uint32_t buffer_id,
                                       gfx::SwapResult swap_result);
-  void SubmitPresentationtOnOriginThread(
+  void SubmitPresentationOnOriginThread(
       gfx::AcceleratedWidget widget,
       uint32_t buffer_id,
       const gfx::PresentationFeedback& feedback);
@@ -181,19 +182,22 @@
       supported_buffer_formats_with_modifiers_;
 
   // This task runner can be used to pass messages back to the same thread,
-  // where the commit buffer request came from. For example, swap requests come
-  // from the GpuMainThread, but rerouted to the IOChildThread and then mojo
-  // calls happen. However, when the manager receives mojo calls, it has to
+  // where the commit buffer request came from. For example, swap requests can
+  // come from the GpuMainThread, but rerouted are to the IOChildThread and then
+  // mojo calls happen. However, when the manager receives mojo calls, it has to
   // reroute calls back to the same thread where the calls came from to ensure
-  // correct sequence.
-  scoped_refptr<base::SingleThreadTaskRunner> commit_thread_runner_;
+  // correct sequence. Note that not all calls come from the GpuMainThread, e.g.
+  // WaylandCanvasSurface calls from the VizCompositorThread.
+  base::small_map<std::map<gfx::AcceleratedWidget,
+                           scoped_refptr<base::SingleThreadTaskRunner>>>
+      commit_thread_runners_;  // Guarded by |lock_|.
 
   // A task runner, which is initialized in a multi-process mode. It is used to
   // ensure all the methods of this class are run on IOChildThread. This is
   // needed to ensure mojo calls happen on a right sequence.
   scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner_;
 
-  // Protects access to |widget_to_surface_map_|.
+  // Protects access to |widget_to_surface_map_| and |commit_thread_runners_|.
   base::Lock lock_;
 
   // Keeps track of the next unique buffer ID.
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index aa64925..350b75c 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -318,7 +318,7 @@
 
   // This will result in Wayland server releasing previously attached buffer for
   // swap id=0u and calling OnSubmission for buffer with swap id=1u.
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -368,7 +368,7 @@
 
   // This will result in Wayland server releasing previously attached buffer for
   // swap id=1u and calling OnSubmission for buffer with swap id=2u.
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
index 8320574..6e2f2d7 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -8,9 +8,9 @@
 #include <memory>
 
 #include "base/i18n/number_formatting.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/linux/drm_util_linux.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -65,8 +65,6 @@
   ~Surface() = default;
 
   bool CommitBuffer(uint32_t buffer_id, const gfx::Rect& damage_region) {
-    DCHECK(!pending_buffer_);
-
     // The window has already been destroyed.
     if (!wayland_surface_)
       return true;
@@ -96,7 +94,7 @@
     if (buffer->attached && !buffer->wl_buffer)
       return false;
 
-    pending_buffer_ = buffer;
+    pending_buffers_.push_back(buffer);
     MaybeProcessPendingBuffer();
     return true;
   }
@@ -109,35 +107,16 @@
 
   size_t DestroyBuffer(uint32_t buffer_id) {
     auto* buffer = GetBuffer(buffer_id);
-    // We ack the submission of a front buffer whenever a previous front back
-    // becomes the back one and receives a buffer release callback. But the
-    // following can happen:
-    //
-    // Imagine the order:
-    // the front buffer is buffer 2, then
-    // Commit[1]
-    // Destroy[2]
-    // Commit[3]
-    // Release[1]
-    // Ack[3] <= this results in a wrong order of the callbacks. In reality,
-    // the buffer [1] must have been acked, because the buffer 2 was
-    // released.
-    // But if the buffer 2 is destroyed, the buffer release callback never
-    // comes for that buffer. Thus, if there is a submitted buffer, notify
-    // the client about successful swap.
-    // If the window has already been destroyed, no need to complete the
-    // submission.
-    if (buffer && !buffer->released && submitted_buffer_ && wayland_surface_)
-      CompleteSubmission();
 
-    if (prev_submitted_buffer_ == buffer)
-      prev_submitted_buffer_ = nullptr;
+    // Treat destroying a buffer as a release, and make sure to call any
+    // OnSubmission callbacks that would be sent as a result of that.
+    if (buffer) {
+      buffer->released = true;
+      MaybeProcessSubmittedBuffers();
+      base::Erase(pending_buffers_, buffer);
+    }
 
-    if (pending_buffer_ == buffer)
-      pending_buffer_ = nullptr;
-
-    auto result = buffers_.erase(buffer_id);
-    return result;
+    return buffers_.erase(buffer_id);
   }
 
   void AttachWlBuffer(uint32_t buffer_id, wl::Object<wl_buffer> new_buffer) {
@@ -154,8 +133,7 @@
     if (buffer->wl_buffer)
       SetupBufferReleaseListener(buffer);
 
-    if (pending_buffer_ == buffer)
-      MaybeProcessPendingBuffer();
+    MaybeProcessPendingBuffer();
   }
 
   void ClearState() {
@@ -165,9 +143,8 @@
 
     ResetSurfaceContents();
 
-    prev_submitted_buffer_ = nullptr;
-    submitted_buffer_ = nullptr;
-    pending_buffer_ = nullptr;
+    submitted_buffers_.clear();
+    pending_buffers_.clear();
 
     connection_->ScheduleFlush();
   }
@@ -179,13 +156,8 @@
     wl_surface_attach(wayland_surface_->surface(), nullptr, 0, 0);
     wl_surface_commit(wayland_surface_->surface());
 
-    // We cannot reset |prev_submitted_buffer_| here as long as the surface
-    // might have attached a new buffer and is about to receive a release
-    // callback. Check more comments below where the variable is declared.
-    contents_reset_ = true;
-
     // ResetSurfaceContents happens upon WaylandWindow::Hide call, which
-    // destroyes xdg_surface, xdg_popup, etc. They are going to be reinitialized
+    // destroys xdg_surface, xdg_popup, etc. They are going to be reinitialized
     // once WaylandWindow::Show is called. Thus, they will have to be configured
     // once again before buffers can be attached.
     configured_ = false;
@@ -226,50 +198,44 @@
 
   using PresentationFeedbackQueue = std::vector<FeedbackInfo>;
 
+  // Holds information about a submitted buffer.
+  struct SubmissionInfo {
+    // ID of the submitted buffer. Buffers may be destroyed after they have been
+    // submitted but before we send OnSubmission for them, e.g. if the same
+    // buffer is submitted twice in a row. Keep the ID so we send OnSubmission
+    // even if a buffer is destroyed.
+    uint32_t buffer_id;
+    // Whether this buffer has had OnSubmission sent for it.
+    bool acked;
+  };
+
   bool CommitBufferInternal(WaylandBuffer* buffer) {
     DCHECK(buffer && wayland_surface_);
-    DCHECK(!pending_buffer_);
 
-    DCHECK(!submitted_buffer_);
-    submitted_buffer_ = buffer;
-
-    // if the same buffer has been submitted again right after the client
+    // If the same buffer has been submitted again right after the client
     // received OnSubmission for that buffer, just damage the buffer and
     // commit the surface again.
-    if (prev_submitted_buffer_ != submitted_buffer_) {
+    if (submitted_buffers_.empty() ||
+        submitted_buffers_.back().buffer_id != buffer->buffer_id) {
       // Once the BufferRelease is called, the buffer will be released.
       DCHECK(buffer->released);
       buffer->released = false;
       AttachBuffer(buffer);
     }
 
+    // If the client submits the same buffer twice, we need to store it twice,
+    // because the client will expect two acks for it.
+    submitted_buffers_.push_back(
+        SubmissionInfo{buffer->buffer_id, /*acked=*/false});
+
     DamageBuffer(buffer);
 
     SetupFrameCallback();
     SetupPresentationFeedback(buffer->buffer_id);
 
     CommitSurface();
-
     connection_->ScheduleFlush();
-
-    // If the contents were reset, there is no buffer attached. It means we have
-    // to behave the same way as if it was the very first frame. Check the
-    // comment below where the |contents_reset_| is declared.
-    if (contents_reset_) {
-      prev_submitted_buffer_ = nullptr;
-      contents_reset_ = false;
-    }
-
-    // If it was the very first frame, the surface has not had a back buffer
-    // before, and Wayland won't release the front buffer until next buffer is
-    // attached. Thus, notify about successful submission immediately.
-    //
-    // As said above, if the client submits the same buffer again, we must
-    // notify the client about the submission immediately as Wayland compositor
-    // is not going to send a release callback for a buffer committed more than
-    // once.
-    if (!prev_submitted_buffer_ || prev_submitted_buffer_ == submitted_buffer_)
-      CompleteSubmission();
+    MaybeProcessSubmittedBuffers();
 
     return true;
   }
@@ -277,7 +243,7 @@
   void DamageBuffer(WaylandBuffer* buffer) {
     DCHECK(wayland_surface_);
 
-    gfx::Rect pending_damage_region = std::move(buffer->damage_region);
+    gfx::Rect pending_damage_region = buffer->damage_region;
     // If the size of the damage region is empty, wl_surface_damage must be
     // supplied with the actual size of the buffer, which is going to be
     // committed.
@@ -390,42 +356,23 @@
   void OnRelease(struct wl_buffer* wl_buffer) {
     DCHECK(wl_buffer);
 
+    // Releases may not necessarily come in order, so search the submitted
+    // buffers.
     WaylandBuffer* buffer = nullptr;
-    // The Wayland compositor may release the buffer immediately after it has
-    // been submitted. Thus, check that wl_buffer belongs to either the
-    // submitted buffer or the previously submitted buffer.
-    if (submitted_buffer_ && submitted_buffer_->wl_buffer.get() == wl_buffer) {
-      buffer = submitted_buffer_;
-      DCHECK(buffer->wl_buffer.get() == wl_buffer);
-    } else {
-      buffer = prev_submitted_buffer_;
-      DCHECK(buffer && buffer->wl_buffer.get() == wl_buffer);
+    for (const auto& b : submitted_buffers_) {
+      auto* submitted_buffer = GetBuffer(b.buffer_id);
+      if (submitted_buffer && wl_buffer == submitted_buffer->wl_buffer.get()) {
+        buffer = submitted_buffer;
+        break;
+      }
     }
-
+    DCHECK(buffer);
     DCHECK(!buffer->released);
     buffer->released = true;
 
-    // It may happen that the client has attached only one buffer and then
-    // destroyed the window. That means that we manually called OnRelease on
-    // that very first buffer attach as long as the surface has not had any
-    // buffers attached before. However, the |submitted_buffer_| can be null in
-    // the OnRelease and hit the DCHECK when the client does not continue
-    // attaching new buffers (only one has been attached) and destroyes the
-    // surface. In this case, the Wayland compositor releases the buffer and the
-    // DCHECK is hit, because we have already run the OnRelease call manually.
-    // Please note that the |prev_submitted_buffer_| is the buffer we have
-    // released manually, and when the Wayland compositor sends OnRelease, the
-    // validation of the wl_buffers succeeds because of that previous manual
-    // OnRelease call.
-    if (!submitted_buffer_)
-      return;
-
-    // Although, the Wayland compositor has just released the previously
-    // attached buffer, which became a back buffer, we have to notify the client
-    // that next buffer has been attach and become the front one. Thus, mark the
-    // back buffer as released to ensure the DCHECK is not hit, and notify about
-    // successful submission of the front buffer.
-    CompleteSubmission();
+    // A release means we may be able to send OnSubmission for previously
+    // submitted buffers.
+    MaybeProcessSubmittedBuffers();
   }
 
   // wl_buffer_listener
@@ -435,19 +382,49 @@
     self->OnRelease(wl_buffer);
   }
 
-  void CompleteSubmission() {
-    DCHECK(submitted_buffer_);
-    auto id = submitted_buffer_->buffer_id;
-    prev_submitted_buffer_ = submitted_buffer_;
-    submitted_buffer_ = nullptr;
-
+  void MaybeProcessSubmittedBuffers() {
     if (!wayland_surface_)
       return;
 
+    // We force an OnSubmission call for the very first buffer submitted,
+    // otherwise buffers are not acked in a quiescent state. We keep track of
+    // whether it has already been acked. A buffer may have already been acked
+    // if it is the first buffer submitted and it is destroyed before being
+    // explicitly released. In that case, don't send an OnSubmission.
+    if (submitted_buffers_.size() == 1u && !submitted_buffers_[0].acked)
+      ProcessOldestSubmittedBuffer();
+
+    // Buffers may be released out of order, but we need to provide the
+    // guarantee that OnSubmission will be called in order of buffer submission.
+    while (submitted_buffers_.size() >= 2) {
+      auto* buffer0 = GetBuffer(submitted_buffers_[0].buffer_id);
+      // Treat a buffer as released if it has been explicitly released or
+      // destroyed.
+      bool buffer0_released = !buffer0 || buffer0->released;
+      // We can send OnSubmission for the 2nd oldest buffer if the oldest buffer
+      // is released, or it's the same buffer.
+      if (!buffer0_released &&
+          submitted_buffers_[0].buffer_id != submitted_buffers_[1].buffer_id)
+        break;
+
+      DCHECK(submitted_buffers_[0].acked);
+      DCHECK(!submitted_buffers_[1].acked);
+      submitted_buffers_.erase(submitted_buffers_.begin());
+      ProcessOldestSubmittedBuffer();
+    }
+  }
+
+  void ProcessOldestSubmittedBuffer() {
+    DCHECK(wayland_surface_);
+    DCHECK(!submitted_buffers_.empty());
+
+    submitted_buffers_.front().acked = true;
+    auto buffer_id = submitted_buffers_.front().buffer_id;
+
     // We can now complete the latest submission. We had to wait for this
     // release because SwapCompletionCallback indicates to the client that the
     // previous buffer is available for reuse.
-    buffer_manager_->OnSubmission(wayland_surface_->GetRootWidget(), id,
+    buffer_manager_->OnSubmission(wayland_surface_->GetWidget(), buffer_id,
                                   gfx::SwapResult::SWAP_ACK);
 
     // If presentation feedback is not supported, use a fake feedback. This
@@ -455,18 +432,19 @@
     if (!connection_->presentation()) {
       DCHECK(feedback_queue_.empty());
       buffer_manager_->OnPresentation(
-          wayland_surface_->GetWidget(), id,
+          wayland_surface_->GetWidget(), buffer_id,
           gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(),
                                     GetPresentationKindFlags(0)));
     } else {
       for (auto& info : feedback_queue_) {
-        if (info.buffer_id == id && !info.submission_completed) {
+        if (info.buffer_id == buffer_id && !info.submission_completed) {
           info.submission_completed = true;
           ProcessPresentationFeedbacks();
           return;
         }
       }
-      NOTREACHED() << "Did not find matching feedback for buffer_id=" << id;
+      NOTREACHED() << "Did not find matching feedback for buffer_id="
+                   << buffer_id;
     }
   }
 
@@ -563,7 +541,7 @@
   void MaybeProcessPendingBuffer() {
     // There is nothing to process if there is no pending buffer or the window
     // has been destroyed.
-    if (!pending_buffer_ || !wayland_surface_)
+    if (pending_buffers_.empty() || !wayland_surface_)
       return;
 
     // This request may come earlier than the Wayland compositor has imported a
@@ -580,12 +558,12 @@
     //
     // The third case happens if the window hasn't been configured until a
     // request to attach a buffer to its surface is sent.
-    if (!pending_buffer_->wl_buffer || wl_frame_callback_ || !configured_)
+    auto* pending_buffer = pending_buffers_.front();
+    if (!pending_buffer->wl_buffer || wl_frame_callback_ || !configured_)
       return;
 
-    auto* buffer = pending_buffer_;
-    pending_buffer_ = nullptr;
-    CommitBufferInternal(buffer);
+    pending_buffers_.erase(pending_buffers_.begin());
+    CommitBufferInternal(pending_buffer);
   }
 
   // Widget this helper surface backs and has 1:1 relationship with the
@@ -608,26 +586,18 @@
   // operation.
   wl::Object<wl_callback> wl_frame_callback_;
 
-  // A presentation feedback provided by the Wayland server once frame is
-  // shown.
+  // Queue of buffers which are pending to be submitted (look the comment
+  // in the CommitBuffer method).
+  std::vector<WaylandBuffer*> pending_buffers_;
+
+  // Queue of buffers which have been submitted and are waiting to be
+  // acked (send OnSubmission)
+  std::vector<SubmissionInfo> submitted_buffers_;
+
+  // Queue of buffers which have been acked and are waiting to have
+  // OnPresentation sent.
   PresentationFeedbackQueue feedback_queue_;
 
-  // A buffer, which is pending to be submitted (look the comment in the
-  // CommitBuffer method).
-  WaylandBuffer* pending_buffer_ = nullptr;
-  // Current submitted buffer.
-  WaylandBuffer* submitted_buffer_ = nullptr;
-  // Previous submitted buffer.
-  WaylandBuffer* prev_submitted_buffer_ = nullptr;
-
-  // If WaylandWindow becomes hidden, it may need to attach a null buffer to the
-  // surface it backed to avoid its contents shown on screen. However, it
-  // means that the Wayland compositor no longer sends new buffer release events
-  // as long as there has not been buffer attached and no submission callback is
-  // sent. To avoid this, |contents_reset_| can be used as an identification of
-  // a need to call submission callback manually.
-  bool contents_reset_ = false;
-
   // If WaylandWindow has never been configured, do not try to attach
   // buffers to its surface. Otherwise, Wayland server will drop the connection
   // and send an error - "The surface has never been configured.".
@@ -731,7 +701,7 @@
     uint32_t format,
     uint32_t planes_count,
     uint32_t buffer_id) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(error_message_.empty());
 
   TRACE_EVENT2("wayland", "WaylandBufferManagerHost::CreateDmabufBasedBuffer",
@@ -771,7 +741,7 @@
                                                     uint64_t length,
                                                     const gfx::Size& size,
                                                     uint32_t buffer_id) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   DCHECK(error_message_.empty());
 
   TRACE_EVENT1("wayland", "WaylandBufferManagerHost::CreateShmBasedBuffer",
@@ -795,7 +765,7 @@
 void WaylandBufferManagerHost::CommitBuffer(gfx::AcceleratedWidget widget,
                                             uint32_t buffer_id,
                                             const gfx::Rect& damage_region) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   TRACE_EVENT1("wayland", "WaylandBufferManagerHost::CommitBuffer", "Buffer id",
                buffer_id);
@@ -822,7 +792,7 @@
 
 void WaylandBufferManagerHost::DestroyBuffer(gfx::AcceleratedWidget widget,
                                              uint32_t buffer_id) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   TRACE_EVENT1("wayland", "WaylandBufferManagerHost::DestroyBuffer",
                "Buffer id", buffer_id);
@@ -1013,7 +983,7 @@
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
     const gfx::SwapResult& swap_result) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   DCHECK(buffer_manager_gpu_associated_);
   buffer_manager_gpu_associated_->OnSubmission(widget, buffer_id, swap_result);
@@ -1023,7 +993,7 @@
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
     const gfx::PresentationFeedback& feedback) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   DCHECK(buffer_manager_gpu_associated_);
   buffer_manager_gpu_associated_->OnPresentation(widget, buffer_id, feedback);
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 7342402b..31bff53 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -14,8 +14,8 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/string_util.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/gfx/geometry/point.h"
@@ -117,7 +117,7 @@
   // When we are in tests, the message loop is set later when the
   // initialization of the OzonePlatform complete. Thus, just
   // flush directly. This doesn't happen in normal run.
-  if (!base::MessageLoopCurrentForUI::IsSet()) {
+  if (!base::CurrentUIThread::IsSet()) {
     Flush();
   } else if (!scheduled_flush_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/ui/ozone/platform/wayland/host/wayland_event_watcher.cc b/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
index 30325c4..52f5eb0 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
+++ b/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
@@ -9,7 +9,7 @@
 
 #include "base/bind.h"
 #include "base/check.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "ui/events/event.h"
 
 namespace ui {
@@ -38,7 +38,7 @@
   if (!watching_)
     return false;
 
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   watching_ = false;
   return controller_.StopWatchingFileDescriptor();
 }
@@ -85,9 +85,9 @@
     DCHECK(!watching_);
   }
 
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   int display_fd = wl_display_get_fd(display_);
-  watching_ = base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
+  watching_ = base::CurrentUIThread::Get()->WatchFileDescriptor(
       display_fd, true, mode, &controller_, this);
   return watching_;
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
index adcd51e..17c6a7ab 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -12,9 +12,9 @@
 #include "base/callback.h"
 #include "base/check.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/notreached.h"
 #include "base/run_loop.h"
+#include "base/task/current_thread.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
@@ -231,7 +231,7 @@
 uint32_t WaylandWindowDragController::DispatchEvent(
     const PlatformEvent& event) {
   DCHECK_EQ(state_, State::kDetached);
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
   VLOG(2) << "Dispatch. event=" << event->GetName();
 
diff --git a/ui/ozone/platform/wayland/test/mock_surface.cc b/ui/ozone/platform/wayland/test/mock_surface.cc
index 2055751..524b4f4 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.cc
+++ b/ui/ozone/platform/wayland/test/mock_surface.cc
@@ -99,10 +99,8 @@
 void MockSurface::AttachNewBuffer(wl_resource* buffer_resource,
                                   int32_t x,
                                   int32_t y) {
-  if (attached_buffer_) {
-    DCHECK(!prev_attached_buffer_);
+  if (attached_buffer_)
     prev_attached_buffer_ = attached_buffer_;
-  }
   attached_buffer_ = buffer_resource;
 
   Attach(buffer_resource, x, y);
@@ -113,13 +111,14 @@
   prev_attached_buffer_ = nullptr;
 }
 
-void MockSurface::ReleasePrevAttachedBuffer() {
-  if (!prev_attached_buffer_)
-    return;
-
-  wl_buffer_send_release(prev_attached_buffer_);
-  wl_client_flush(wl_resource_get_client(prev_attached_buffer_));
-  prev_attached_buffer_ = nullptr;
+void MockSurface::ReleaseBuffer(wl_resource* buffer) {
+  DCHECK(buffer);
+  wl_buffer_send_release(buffer);
+  wl_client_flush(wl_resource_get_client(buffer));
+  if (buffer == prev_attached_buffer_)
+    prev_attached_buffer_ = nullptr;
+  if (buffer == attached_buffer_)
+    attached_buffer_ = nullptr;
 }
 
 void MockSurface::SendFrameCallback() {
diff --git a/ui/ozone/platform/wayland/test/mock_surface.h b/ui/ozone/platform/wayland/test/mock_surface.h
index 412d838..e562a20 100644
--- a/ui/ozone/platform/wayland/test/mock_surface.h
+++ b/ui/ozone/platform/wayland/test/mock_surface.h
@@ -57,11 +57,14 @@
     frame_callback_ = callback_resource;
   }
 
+  wl_resource* attached_buffer() const { return attached_buffer_; }
+  wl_resource* prev_attached_buffer() const { return prev_attached_buffer_; }
+
   bool has_role() const { return !!xdg_surface_ || !!sub_surface_; }
 
   void AttachNewBuffer(wl_resource* buffer_resource, int32_t x, int32_t y);
   void DestroyPrevAttachedBuffer();
-  void ReleasePrevAttachedBuffer();
+  void ReleaseBuffer(wl_resource* buffer);
   void SendFrameCallback();
 
  private:
diff --git a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
index 6c262a84..cb05683 100644
--- a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+++ b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
@@ -50,6 +50,7 @@
   MockSurfaceGpu(WaylandBufferManagerGpu* buffer_manager,
                  gfx::AcceleratedWidget widget)
       : buffer_manager_(buffer_manager), widget_(widget) {
+    LOG(ERROR) << "MOCKSURFACEGPU: " << widget_;
     buffer_manager_->RegisterSurface(widget_, this);
   }
   ~MockSurfaceGpu() { buffer_manager_->UnregisterSurface(widget_); }
@@ -493,7 +494,7 @@
       .Times(1);
   EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
   mock_surface->SendFrameCallback();
 
   Sync();
@@ -534,7 +535,7 @@
 
   // Now, send the release callback. The host manager must send the submission
   // and presentation callbacks in correct order.
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -727,7 +728,7 @@
       mock_wp_presentation->ReleasePresentationCallback();
 
   // Release previous buffer and commit third buffer.
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
   mock_surface->SendFrameCallback();
 
   Sync();
@@ -742,7 +743,7 @@
 
   Sync();
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -805,6 +806,7 @@
 
   const gfx::AcceleratedWidget widget = window_->GetWidget();
   auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
+  MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget_);
 
   auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
   EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(1);
@@ -902,6 +904,7 @@
     Sync();
 
     auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
+    MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
 
     auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
     EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(1);
@@ -1011,7 +1014,7 @@
 
   Sync();
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -1047,7 +1050,7 @@
 
   Sync();
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -1164,7 +1167,7 @@
 
   Sync();
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
 
   Sync();
 
@@ -1180,10 +1183,214 @@
   DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
 }
 
+// Tests that OnSubmission and OnPresentation are properly triggered if a buffer
+// is committed twice in a row and those buffers are destroyed.
+TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
+  constexpr uint32_t kBufferId1 = 1;
+  constexpr uint32_t kBufferId2 = 2;
+
+  const gfx::AcceleratedWidget widget = window_->GetWidget();
+  const gfx::Rect bounds = window_->GetBounds();
+  auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
+
+  MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
+
+  auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
+  EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(2);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId2);
+
+  Sync();
+
+  ProcessCreatedBufferResourcesWithExpectation(2u /* expected size */,
+                                               false /* fail */);
+
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Can't call OnSubmission until there is a release.
+  EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Destroying buffer2 should do nothing yet.
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Destroying buffer1 should give us two acks for buffer2.
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+      .Times(2);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(2);
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+}
+
+// Tests that OnSubmission and OnPresentation are properly triggered if a buffer
+// is committed twice in a row and then released.
+TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
+  constexpr uint32_t kBufferId1 = 1;
+  constexpr uint32_t kBufferId2 = 2;
+
+  const gfx::AcceleratedWidget widget = window_->GetWidget();
+  const gfx::Rect bounds = window_->GetBounds();
+  auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
+
+  MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
+
+  auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
+  EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(2);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId2);
+
+  Sync();
+
+  ProcessCreatedBufferResourcesWithExpectation(2u /* expected size */,
+                                               false /* fail */);
+
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+  auto* wl_buffer1 = mock_surface->attached_buffer();
+
+  // Can't call OnSubmission until there is a release.
+  EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Releasing buffer1 should trigger two acks for buffer2.
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+      .Times(2);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(2);
+  mock_surface->ReleaseBuffer(wl_buffer1);
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+}
+
+// Tests that OnSubmission and OnPresentation callbacks are properly called
+// even if buffers are not released in the same order they were committed.
+TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
+  constexpr uint32_t kBufferId1 = 1;
+  constexpr uint32_t kBufferId2 = 2;
+  constexpr uint32_t kBufferId3 = 3;
+
+  const gfx::AcceleratedWidget widget = window_->GetWidget();
+  const gfx::Rect bounds = window_->GetBounds();
+  auto* mock_surface = server_.GetObject<wl::MockSurface>(widget);
+
+  MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
+
+  auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
+  EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(3);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId2);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId3);
+
+  Sync();
+
+  ProcessCreatedBufferResourcesWithExpectation(3u /* expected size */,
+                                               false /* fail */);
+
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
+  EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+  auto* wl_buffer1 = mock_surface->attached_buffer();
+
+  // Can't call OnSubmission until there is a release.
+  EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
+  EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(2);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+  auto* wl_buffer2 = mock_surface->attached_buffer();
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds);
+  mock_surface->SendFrameCallback();
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Releasing buffer2 can't trigger OnSubmission for buffer3, because
+  // OnSubmission for buffer2 has not been sent yet.
+  EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _)).Times(0);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
+  mock_surface->ReleaseBuffer(wl_buffer2);
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  // Releasing buffer1 should trigger acks for both.
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
+
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId3, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(1);
+  mock_surface->ReleaseBuffer(wl_buffer1);
+  Sync();
+
+  testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
+
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+}
+
 // This test verifies that submitting the buffer more than once results in
 // OnSubmission callback as Wayland compositor is not supposed to release the
 // buffer committed twice.
-TEST_P(WaylandBufferManagerTest, SubmitSameBufferMultipleTimes) {
+TEST_P(WaylandBufferManagerTest,
+       OnSubmissionCalledForBufferCommitedTwiceInARow) {
   constexpr uint32_t kBufferId1 = 1;
   constexpr uint32_t kBufferId2 = 2;
 
@@ -1254,7 +1461,7 @@
   EXPECT_CALL(*mock_surface, DamageBuffer(_, _, _, _)).Times(0);
   EXPECT_CALL(*mock_surface, Commit()).Times(0);
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
   mock_surface->SendFrameCallback();
 
   Sync();
@@ -1294,9 +1501,6 @@
   EXPECT_CALL(*mock_surface, DamageBuffer(_, _, _, _)).Times(0);
   EXPECT_CALL(*mock_surface, Commit()).Times(0);
 
-  // It must be ok if Wayland compositor decides to release the buffer at some
-  // point.
-  mock_surface->ReleasePrevAttachedBuffer();
   mock_surface->SendFrameCallback();
 
   Sync();
@@ -1329,7 +1533,7 @@
       .Times(1);
   EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
 
-  mock_surface->ReleasePrevAttachedBuffer();
+  mock_surface->ReleaseBuffer(mock_surface->prev_attached_buffer());
   mock_surface->SendFrameCallback();
 
   Sync();
@@ -1340,6 +1544,37 @@
   DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
 }
 
+// Tests that submitting a single buffer only receives an OnSubmission. This is
+// required behaviour to make sure that submitting buffers in a quiescent state
+// will be immediately acked.
+TEST_P(WaylandBufferManagerTest, OnSubmissionCalledForSingleBuffer) {
+  constexpr uint32_t kBufferId1 = 1;
+
+  const gfx::AcceleratedWidget widget = window_->GetWidget();
+  const gfx::Rect bounds = window_->GetBounds();
+
+  MockSurfaceGpu mock_surface_gpu(buffer_manager_gpu_.get(), widget);
+
+  auto* linux_dmabuf = server_.zwp_linux_dmabuf_v1();
+  EXPECT_CALL(*linux_dmabuf, CreateParams(_, _, _)).Times(1);
+  CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/, kBufferId1);
+
+  Sync();
+
+  ProcessCreatedBufferResourcesWithExpectation(1u /* expected size */,
+                                               false /* fail */);
+
+  EXPECT_CALL(mock_surface_gpu,
+              OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK))
+      .Times(1);
+  EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
+
+  buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds);
+  Sync();
+
+  DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+}
+
 INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
                          WaylandBufferManagerTest,
                          ::testing::Values(kXdgShellStable));
diff --git a/ui/snapshot/screenshot_grabber.cc b/ui/snapshot/screenshot_grabber.cc
index 2145955e..5401712 100644
--- a/ui/snapshot/screenshot_grabber.cc
+++ b/ui/snapshot/screenshot_grabber.cc
@@ -14,8 +14,8 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/task/post_task.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -73,7 +73,7 @@
 void ScreenshotGrabber::TakeScreenshot(gfx::NativeWindow window,
                                        const gfx::Rect& rect,
                                        ScreenshotCallback callback) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   last_screenshot_timestamp_ = base::TimeTicks::Now();
 
   bool is_partial = true;
@@ -106,7 +106,7 @@
     bool is_partial,
     ScreenshotCallback callback,
     scoped_refptr<base::RefCountedMemory> png_data) {
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
 
 #if defined(USE_AURA)
   cursor_hider_.reset();
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 1fdd051..d693215 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -7,10 +7,10 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "ui/accessibility/ax_action_data.h"
@@ -344,7 +344,7 @@
     set_views_delegate(std::move(test_views_delegate));
     ViewsTestBase::SetUp();
     Init();
-    ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet());
+    ASSERT_TRUE(base::CurrentUIThread::IsSet());
   }
 
   void TearDown() override {
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc
index 0f71ce4..b81ea77 100644
--- a/ui/views/controls/slider.cc
+++ b/ui/views/controls/slider.cc
@@ -8,9 +8,9 @@
 #include <memory>
 
 #include "base/check_op.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "build/build_config.h"
 #include "cc/paint/paint_flags.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -134,7 +134,7 @@
   if (listener_)
     listener_->SliderValueChanged(this, value_, old_value, reason);
 
-  if (old_value_valid && base::MessageLoopCurrent::Get()) {
+  if (old_value_valid && base::CurrentThread::Get()) {
     // Do not animate when setting the value of the slider for the first time.
     // There is no message-loop when running tests. So we cannot animate then.
     if (!move_animation_) {
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index b7fd268..a064c50 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -9,10 +9,10 @@
 
 #include "base/check_op.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/gfx/range/range.h"
@@ -345,7 +345,7 @@
 // the default kill ring size of 1 (i.e. a single buffer) is assumed.
 base::string16* GetKillBuffer() {
   static base::NoDestructor<base::string16> kill_buffer;
-  DCHECK(base::MessageLoopCurrentForUI::IsSet());
+  DCHECK(base::CurrentUIThread::IsSet());
   return kill_buffer.get();
 }
 
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index db4fe78..4cfdfcc 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -18,9 +18,9 @@
 #include "base/debug/alias.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -791,7 +791,7 @@
   MoveLoopMouseWatcher watcher(this, hide_on_escape);
   // In Aura, we handle touch events asynchronously. So we need to allow nested
   // tasks while in windows move loop.
-  base::MessageLoopCurrent::ScopedNestableTaskAllower allow_nested;
+  base::CurrentThread::ScopedNestableTaskAllower allow_nested;
 
   SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, GetMessagePos());
   // Windows doesn't appear to offer a way to determine whether the user
diff --git a/weblayer/browser/browser_main_parts_impl.cc b/weblayer/browser/browser_main_parts_impl.cc
index 7f9e846..3f585c5 100644
--- a/weblayer/browser/browser_main_parts_impl.cc
+++ b/weblayer/browser/browser_main_parts_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/base_switches.h"
 #include "base/bind.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"