diff --git a/DEPS b/DEPS
index ffa4032..c39d2e6 100644
--- a/DEPS
+++ b/DEPS
@@ -195,11 +195,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e3d6db4c3fac08059bcaa744ce429665fa10a8c1',
+  'skia_revision': 'aba6b93dfbc8e4491efe6d3b55612671c7c7ec79',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '2a00f38a34d5c3dffd2ef5cd1f538534ce7d66af',
+  'v8_revision': 'f41960f6c5ae9cd5fcf613ed66e73cc602f964ee',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -207,7 +207,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': '97013e85adfceabb4e4c4d95178e186481b82362',
+  'angle_revision': '282596778418f1b35c809cdba3dceb778f1d4a26',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -266,7 +266,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': '447a462be3f9d44c89994c8a5eb44b738d4c8dc6',
+  'devtools_frontend_revision': '7d194407e8b078c2cec653371f1200e0c7a38d00',
   # 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.
@@ -302,7 +302,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': '9e26ae04552617102ae22f04946e3b69552f7560',
+  'spv_tools_revision': 'bceab9fab4bcea27af04567ee5f899510c84a968',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -318,7 +318,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': '8575cb3ec773d43a86fe68eece70ae02cad6cfc5',
+  'dawn_revision': '900bd341a3c6fc71dfbaeac8adb45b1da0de53d0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -891,7 +891,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'fa27bc456b389a103f783f011e88f8bbf59658e7',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'ded752ca0c0b18e3e961b35b03f4d5938e6f3561',
       'condition': 'checkout_linux',
   },
 
@@ -1249,7 +1249,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ced41e1f394dc71e63fd979d50c2fe0e507f2fbe',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8e6246dafe6190ad560958a549f11f973a573aa1',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1471,7 +1471,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'c75c4280763435eeb44785dfc76f098bf06743bb',
+    Var('webrtc_git') + '/src.git' + '@' + 'a8327d441549f2abca3c4ac22b5d71c123e3d431',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
diff --git a/WATCHLISTS b/WATCHLISTS
index 76e7db6..2c293c1 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1344,7 +1344,7 @@
       'filepath': 'chrome/browser/nearby_sharing/|'\
                   'chrome/browser/resources/nearby_internals/|'\
                   'chrome/browser/resources/nearby_share/|'\
-                  'chrome/browser/resources/settings/nearby_share_page/|'\
+                  'chrome/browser/resources/settings/chromeos/nearby_share_page/|'\
                   'chrome/browser/ui/webui/nearby_internals/|'\
                   'chrome/browser/ui/webui/nearby_share/|'\
                   'chrome/services/sharing/'
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 7c0ea91b..4ab581f0 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -478,4 +478,10 @@
   client_->OnFocusLeavingSystemTray(reverse);
 }
 
+void LoginScreenController::NotifyLoginScreenShown() {
+  if (!client_)
+    return;
+  client_->OnLoginScreenShown();
+}
+
 }  // namespace ash
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index 87101bf8..ede05c4 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -144,6 +144,8 @@
 
   LoginDataDispatcher* data_dispatcher() { return &login_data_dispatcher_; }
 
+  void NotifyLoginScreenShown();
+
  private:
   void OnAuthenticateComplete(OnAuthenticateCallback callback, bool success);
 
diff --git a/ash/login/mock_login_screen_client.h b/ash/login/mock_login_screen_client.h
index 7caaa6d..3ee14ef 100644
--- a/ash/login/mock_login_screen_client.h
+++ b/ash/login/mock_login_screen_client.h
@@ -106,6 +106,7 @@
   MOCK_METHOD(void, FocusOobeDialog, (), (override));
   MOCK_METHOD(void, OnFocusLeavingSystemTray, (bool reverse), (override));
   MOCK_METHOD(void, OnUserActivity, (), (override));
+  MOCK_METHOD(void, OnLoginScreenShown, (), (override));
 
  private:
   bool authenticate_user_callback_result_ = true;
diff --git a/ash/login/ui/lock_screen.cc b/ash/login/ui/lock_screen.cc
index 738c611..c0df9f15 100644
--- a/ash/login/ui/lock_screen.cc
+++ b/ash/login/ui/lock_screen.cc
@@ -191,6 +191,8 @@
   swap(instance_->on_shown_callbacks_, on_shown_callbacks);
   for (auto& callback : on_shown_callbacks)
     std::move(callback).Run();
+
+  Shell::Get()->login_screen_controller()->NotifyLoginScreenShown();
 }
 
 }  // namespace ash
diff --git a/ash/public/cpp/login_screen_client.h b/ash/public/cpp/login_screen_client.h
index 086ae57..47e44cd 100644
--- a/ash/public/cpp/login_screen_client.h
+++ b/ash/public/cpp/login_screen_client.h
@@ -150,6 +150,9 @@
   // reversed direction.
   virtual void OnFocusLeavingSystemTray(bool reverse) = 0;
 
+  // Called when the lock screen is shown.
+  virtual void OnLoginScreenShown() = 0;
+
   // Used by Ash to signal that user activity occurred on the login screen.
   virtual void OnUserActivity() = 0;
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 44eb9eb6..876ebc2b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3005,6 +3005,7 @@
       "win/object_watcher_unittest.cc",
       "win/pe_image_reader_unittest.cc",
       "win/pe_image_unittest.cc",
+      "win/post_async_results_unittest.cc",
       "win/reference_unittest.cc",
       "win/registry_unittest.cc",
       "win/scoped_bstr_unittest.cc",
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 51c86e84..fd1236a 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -62,9 +62,6 @@
 static_assert(sizeof(internal::PartitionPage<internal::ThreadSafe>) <=
                   kPageMetadataSize,
               "PartitionPage should not be too big");
-static_assert(sizeof(internal::PartitionBucket<internal::ThreadSafe>) <=
-                  kPageMetadataSize,
-              "PartitionBucket should not be too big");
 static_assert(kPageMetadataSize * kNumPartitionPagesPerSuperPage <=
                   kSystemPageSize,
               "page metadata fits in hole");
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index e754eef2..f94677d2 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -832,18 +832,14 @@
   auto* page =
       internal::PartitionAllocGetPageForSize<internal::ThreadSafe>(ptr);
   PA_DCHECK(PartitionRoot<internal::ThreadSafe>::FromPage(page)->allow_extras);
-  size_t slot_size = page->bucket->slot_size;
 
   // Get the offset from the beginning of the slot span.
   uintptr_t ptr_addr = reinterpret_cast<uintptr_t>(ptr);
   uintptr_t slot_span_start = reinterpret_cast<uintptr_t>(
       internal::PartitionPage<internal::ThreadSafe>::ToPointer(page));
   size_t offset_in_slot_span = ptr_addr - slot_span_start;
-  // Knowing that slots are tightly packed in a slot span, calculate an offset
-  // within a slot using simple % operation.
-  // TODO(bartekn): Try to replace % with multiplication&shift magic.
-  size_t offset_in_slot = offset_in_slot_span % slot_size;
-  return offset_in_slot;
+
+  return page->bucket->GetSlotOffset(offset_in_slot_span);
 }
 
 #endif  // BUILDFLAG(USE_PARTITION_ALLOC)
diff --git a/base/allocator/partition_allocator/partition_alloc_constants.h b/base/allocator/partition_allocator/partition_alloc_constants.h
index 242bddf1..6fce6334 100644
--- a/base/allocator/partition_allocator/partition_alloc_constants.h
+++ b/base/allocator/partition_allocator/partition_alloc_constants.h
@@ -120,12 +120,12 @@
 //
 // A direct-mapped page's metadata page has the following layout:
 //
-//     +---------------------------------+
-//     | SuperPageExtentEntry (32 B)     |
-//     | PartitionPage (32 B)            |
-//     | PartitionBucket (32 B)          |
-//     | PartitionDirectMapExtent (32 B) |
-//     +---------------------------------+
+//     +---------------------------------------------------------+
+//     | SuperPageExtentEntry (32 B)                             |
+//     | PartitionPage (32 B)                                    |
+//     | PartitionBucket (32 B on 32-, 40 B on 64-bit platforms) |
+//     | PartitionDirectMapExtent (32 B)                         |
+//     +---------------------------------------------------------+
 
 static const size_t kSuperPageShift = 21;  // 2 MiB
 static const size_t kSuperPageSize = 1 << kSuperPageShift;
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index a83950e..c5dab89 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -904,6 +904,26 @@
               offset);
   }
 #endif
+
+  // Allocate the maximum allowed bucketed size.
+  requested_size = kMaxBucketed - kExtraAllocSize;
+  predicted_size = allocator.root()->ActualSize(requested_size);
+  ptr = allocator.root()->Alloc(requested_size, type_name);
+  EXPECT_TRUE(ptr);
+  actual_size = allocator.root()->GetSize(ptr);
+  EXPECT_EQ(predicted_size, actual_size);
+  EXPECT_EQ(requested_size, actual_size);
+#if defined(ARCH_CPU_64_BITS) && !defined(OS_NACL)
+  for (size_t offset = 0; offset < requested_size; offset += 4999) {
+    EXPECT_EQ(PartitionAllocGetSlotOffset(static_cast<char*>(ptr) + offset),
+              offset);
+    // TODO(bartekn): Remove when CheckedPtr2OrMTEImpl no longer calls
+    // mismatched vartiant.
+    EXPECT_EQ(PartitionAllocGetSlotOffset(static_cast<char*>(ptr) + offset),
+              offset);
+  }
+#endif
+
   // Check that we can write at the end of the reported size too.
   char* char_ptr = reinterpret_cast<char*>(ptr);
   *(char_ptr + (actual_size - 1)) = 'A';
@@ -2544,6 +2564,19 @@
 
 #endif
 
+// Test that the optimized `GetSlotOffset` implementation produces valid
+// results.
+TEST_F(PartitionAllocTest, OptimizedGetSlotOffset) {
+  auto* current_bucket = allocator.root()->buckets;
+
+  for (size_t i = 0; i < kNumBuckets; ++i, ++current_bucket) {
+    for (size_t offset = 0; offset <= kMaxBucketed; offset += 4999) {
+      EXPECT_EQ(offset % current_bucket->slot_size,
+                current_bucket->GetSlotOffset(offset));
+    }
+  }
+}
+
 }  // namespace internal
 }  // namespace base
 
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index 79118542..1c39fff1 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -202,6 +202,7 @@
 template <bool thread_safe>
 void PartitionBucket<thread_safe>::Init(uint32_t new_slot_size) {
   slot_size = new_slot_size;
+  slot_size_reciprocal = kReciprocalMask / new_slot_size + 1;
   active_pages_head = PartitionPage<thread_safe>::get_sentinel_page();
   empty_pages_head = nullptr;
   decommitted_pages_head = nullptr;
diff --git a/base/allocator/partition_allocator/partition_bucket.h b/base/allocator/partition_allocator/partition_bucket.h
index 09badb8..65311003 100644
--- a/base/allocator/partition_allocator/partition_bucket.h
+++ b/base/allocator/partition_allocator/partition_bucket.h
@@ -30,6 +30,24 @@
   uint32_t num_system_pages_per_slot_span : 8;
   uint32_t num_full_pages : 24;
 
+  // `slot_size_reciprocal` is used to improve the performance of
+  // `GetSlotOffset`. It is computed as `(1 / size) * (2 ** M)` where M is
+  // chosen to provide the desired accuracy. As a result, we can replace a slow
+  // integer division (or modulo) operation with a pair of multiplication and a
+  // bit shift, i.e. `value / size` becomes `(value * size_reciprocal) >> M`.
+  uint64_t slot_size_reciprocal;
+
+  // This is `M` from the formula above. For accurate results, both `value` and
+  // `size`, which are bound by `kMaxBucketed` for our purposes, must be less
+  // than `2 ** (M / 2)`. On the other hand, the result of the expression
+  // `3 * M / 2` must be less than 64, otherwise integer overflow can occur.
+  static constexpr uint64_t kReciprocalShift = 42;
+  static constexpr uint64_t kReciprocalMask = (1ull << kReciprocalShift) - 1;
+  static_assert(
+      kMaxBucketed < (1 << (kReciprocalShift / 2)),
+      "GetSlotOffset may produce an incorrect result when kMaxBucketed is too "
+      "large.");
+
   // Public API.
   void Init(uint32_t new_slot_size);
 
@@ -82,6 +100,27 @@
   // This is where the guts of the bucket maintenance is done!
   bool SetNewActivePage();
 
+  // Returns an offset within an allocation slot.
+  ALWAYS_INLINE size_t GetSlotOffset(size_t offset_in_slot_span) {
+    // Knowing that slots are tightly packed in a slot span, calculate an offset
+    // using an equivalent of a modulo operation.
+
+    // See the static assertion for `kReciprocalShift` above.
+    PA_DCHECK(offset_in_slot_span <= kMaxBucketed);
+    PA_DCHECK(slot_size <= kMaxBucketed);
+
+    // Calculate `decimal_part{offset_in_slot / size} * (2 ** M)` first.
+    uint64_t offset_in_slot =
+        (offset_in_slot_span * slot_size_reciprocal) & kReciprocalMask;
+
+    // (decimal_part * size) * (2 ** M) == offset_in_slot_span % size * (2 ** M)
+    // Divide by `2 ** M` using a bit shift.
+    offset_in_slot = (offset_in_slot * slot_size) >> kReciprocalShift;
+    PA_DCHECK(offset_in_slot_span % slot_size == offset_in_slot);
+
+    return static_cast<size_t>(offset_in_slot);
+  }
+
  private:
   static NOINLINE void OnFull();
 
diff --git a/base/allocator/partition_allocator/partition_direct_map_extent.h b/base/allocator/partition_allocator/partition_direct_map_extent.h
index 494f2352..de35fa27 100644
--- a/base/allocator/partition_allocator/partition_direct_map_extent.h
+++ b/base/allocator/partition_allocator/partition_direct_map_extent.h
@@ -30,7 +30,12 @@
     PartitionPage<thread_safe>* page) {
   PA_DCHECK(page->bucket->is_direct_mapped());
   return reinterpret_cast<PartitionDirectMapExtent<thread_safe>*>(
-      reinterpret_cast<char*>(page) + 3 * kPageMetadataSize);
+      reinterpret_cast<char*>(page) +
+      kPageMetadataSize +  // sizeof(PartitionSuperPageExtentEntry)
+                           // TODO(crbug.com/787153): Refactor the code to have
+                           // a more robust offset calculation.
+      sizeof(PartitionPage<thread_safe>) +
+      sizeof(PartitionBucket<thread_safe>));
 }
 
 }  // namespace internal
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 252bb5d..e1ec8031 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -172,6 +172,7 @@
 
   if (is_win) {
     sources += [
+      "fake_iasync_operation_win.h",
       "scoped_os_info_override_win.cc",
       "scoped_os_info_override_win.h",
       "test_file_util_win.cc",
diff --git a/base/test/fake_iasync_operation_win.h b/base/test/fake_iasync_operation_win.h
new file mode 100644
index 0000000..fff4ecd
--- /dev/null
+++ b/base/test/fake_iasync_operation_win.h
@@ -0,0 +1,144 @@
+// 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 BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
+#define BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
+
+#include <wrl/client.h>
+
+#include "base/notreached.h"
+#include "base/win/winrt_foundation_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+namespace internal {
+
+// Templates used to allow easy reference to the correct types.
+// See base/win/winrt_foundation_helpers.h for explanation.
+template <typename T>
+using AsyncOperationComplex =
+    typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
+
+template <typename T>
+using AsyncOperationAbi = AbiType<AsyncOperationComplex<T>>;
+
+template <typename T>
+using AsyncOperationOptionalStorage =
+    OptionalStorageType<AsyncOperationComplex<T>>;
+
+template <typename T>
+using AsyncOperationStorage = StorageType<AsyncOperationComplex<T>>;
+
+}  // namespace internal
+
+// Provides an implementation of Windows::Foundation::IAsyncOperation for
+// use in GTests.
+template <typename T>
+class FakeIAsyncOperation final
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<
+              Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
+          ABI::Windows::Foundation::IAsyncOperation<T>,
+          ABI::Windows::Foundation::IAsyncInfo> {
+ public:
+  FakeIAsyncOperation() = default;
+  FakeIAsyncOperation(const FakeIAsyncOperation&) = delete;
+  FakeIAsyncOperation& operator=(const FakeIAsyncOperation&) = delete;
+
+  // ABI::Windows::Foundation::IAsyncOperation:
+  IFACEMETHODIMP put_Completed(
+      ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>* handler)
+      final {
+    EXPECT_EQ(nullptr, handler_)
+        << "put_Completed called on IAsyncOperation with a CompletedHandler "
+           "already defined.";
+    handler_ = handler;
+    return S_OK;
+  }
+  IFACEMETHODIMP get_Completed(
+      ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>** handler)
+      final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP GetResults(internal::AsyncOperationAbi<T>* results) final {
+    if (!is_complete_) {
+      ADD_FAILURE() << "GetResults called on incomplete IAsyncOperation.";
+      return E_PENDING;
+    }
+    if (status_ != AsyncStatus::Completed)
+      return E_UNEXPECTED;
+    return base::win::internal::CopyTo(results_, results);
+  }
+
+  // ABI::Windows::Foundation::IAsyncInfo:
+  IFACEMETHODIMP get_Id(uint32_t* id) final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP get_Status(AsyncStatus* status) final {
+    *status = status_;
+    return S_OK;
+  }
+  IFACEMETHODIMP get_ErrorCode(HRESULT* error_code) final {
+    *error_code = error_code_;
+    return S_OK;
+  }
+  IFACEMETHODIMP Cancel() final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+  IFACEMETHODIMP Close() final {
+    NOTREACHED();
+    return E_NOTIMPL;
+  }
+
+  // Completes the operation with |error_code|.
+  //
+  // The get_ErrorCode API will be set to return |error_code|, the remainder of
+  // the APIs will be set to represent an error state, and the CompletedHandler
+  // (if defined) will be run.
+  void CompleteWithError(HRESULT error_code) {
+    error_code_ = error_code;
+    status_ = AsyncStatus::Error;
+    InvokeCompletedHandler();
+  }
+
+  // Completes the operation with |results|.
+  //
+  // The GetResults API will be set to return |results|, the remainder of the
+  // APIs will be set to represent a successfully completed state, and the
+  // CompletedHandler (if defined) will be run.
+  void CompleteWithResults(internal::AsyncOperationStorage<T> results) {
+    error_code_ = S_OK;
+    results_ = std::move(results);
+    status_ = AsyncStatus::Completed;
+    InvokeCompletedHandler();
+  }
+
+ private:
+  void InvokeCompletedHandler() {
+    ASSERT_FALSE(is_complete_)
+        << "Attempted to invoke completion on an already "
+           "completed IAsyncOperation.";
+    is_complete_ = true;
+    if (handler_)
+      handler_->Invoke(this, status_);
+  }
+
+  HRESULT error_code_ = S_OK;
+  Microsoft::WRL::ComPtr<
+      ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>>
+      handler_;
+  bool is_complete_ = false;
+  internal::AsyncOperationOptionalStorage<T> results_;
+  AsyncStatus status_ = AsyncStatus::Started;
+};
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc
index a5fba8e..fccc23c 100644
--- a/base/trace_event/traced_value.cc
+++ b/base/trace_event/traced_value.cc
@@ -882,49 +882,50 @@
   return str;
 }
 
-TracedValue::ArrayScope::ArrayScope(TracedValue* value) : value_(value) {
-  value_->BeginArray();
-}
-
-TracedValue::ArrayScope::ArrayScope(TracedValue* value, const char* name)
-    : value_(value) {
-  value_->BeginArray(name);
-}
+TracedValue::ArrayScope::ArrayScope(TracedValue* value) : value_(value) {}
 
 TracedValue::ArrayScope::~ArrayScope() {
   value_->EndArray();
 }
 
 TracedValue::ArrayScope TracedValue::AppendArrayScoped() {
+  BeginArray();
   return TracedValue::ArrayScope(this);
 }
 
 TracedValue::ArrayScope TracedValue::BeginArrayScoped(const char* name) {
-  return TracedValue::ArrayScope(this, name);
+  BeginArray(name);
+  return TracedValue::ArrayScope(this);
+}
+
+TracedValue::ArrayScope TracedValue::BeginArrayScopedWithCopiedName(
+    base::StringPiece name) {
+  BeginArrayWithCopiedName(name);
+  return TracedValue::ArrayScope(this);
 }
 
 TracedValue::DictionaryScope::DictionaryScope(TracedValue* value)
-    : value_(value) {
-  value_->BeginDictionary();
-}
-
-TracedValue::DictionaryScope::DictionaryScope(TracedValue* value,
-                                              const char* name)
-    : value_(value) {
-  value_->BeginDictionary(name);
-}
+    : value_(value) {}
 
 TracedValue::DictionaryScope::~DictionaryScope() {
   value_->EndDictionary();
 }
 
 TracedValue::DictionaryScope TracedValue::AppendDictionaryScoped() {
+  BeginDictionary();
   return TracedValue::DictionaryScope(this);
 }
 
 TracedValue::DictionaryScope TracedValue::BeginDictionaryScoped(
     const char* name) {
-  return TracedValue::DictionaryScope(this, name);
+  BeginDictionary(name);
+  return TracedValue::DictionaryScope(this);
+}
+
+TracedValue::DictionaryScope TracedValue::BeginDictionaryScopedWithCopiedName(
+    base::StringPiece name) {
+  BeginDictionaryWithCopiedName(name);
+  return TracedValue::DictionaryScope(this);
 }
 
 }  // namespace trace_event
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h
index f7f2c09..d6360520 100644
--- a/base/trace_event/traced_value.h
+++ b/base/trace_event/traced_value.h
@@ -67,14 +67,17 @@
 
   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
 
-  // Helper to open / close an array. The ctor of |ArrayScope| opens the array,
-  // the dtor closes. To be used via |TracedValue::AppendArrayScoped| and
-  // |TracedValue::BeginArrayScoped|.
+  // Helper to auto-close an array. The call to |ArrayScope::~ArrayScope| closes
+  // the array.
+  //
+  // To be constructed using:
+  //   |TracedValue::AppendArrayScoped|
+  //   |TracedValue::BeginArrayScoped|
+  //   |TracedValue::BeginArrayScopedWithCopiedName|
   //
   // |ArrayScope| holds a |TracedValue| pointer which should remain a valid
-  // pointer at the time |ArrayScope::~ArrayScope| is called.
+  // pointer until |ArrayScope::~ArrayScope| is called.
   //
-  // |ArrayScope::ArrayScope| calls |TracedValue::BeginArray|
   // |ArrayScope::~ArrayScope| calls |TracedValue::EndArray| (which checks if
   // the held |TracedValue*| is in array state).
   //
@@ -86,29 +89,37 @@
   //   }
   class BASE_EXPORT ArrayScope {
    public:
+    ArrayScope(const ArrayScope&) = delete;
+    ArrayScope(ArrayScope&&) = default;
+    ArrayScope& operator=(const ArrayScope&) = delete;
+    ArrayScope& operator=(ArrayScope&&) = default;
     ~ArrayScope();
 
    private:
     explicit ArrayScope(TracedValue* value);
-    explicit ArrayScope(TracedValue* value, const char* name);
 
     TracedValue* value_;
 
     friend class TracedValue;
   };
 
+  // Call |BeginArray| or |BeginArrayWithCopiedName| with no / the same
+  // parameter and return an |ArrayScope| holding |this|.
   ArrayScope AppendArrayScoped();
   ArrayScope BeginArrayScoped(const char* name);
+  ArrayScope BeginArrayScopedWithCopiedName(base::StringPiece name);
 
-  // Helper to open / close a dictionary. The ctor of |DictionaryScope| opens
-  // the dictionary, the dtor closes. To be used via
-  // |TracedValue::AppendDictionaryScoped| and
-  // |TracedValue::BeginDictionaryScoped|.
+  // Helper to auto-close a dictionary. The call to
+  // |DictionaryScope::~DictionaryScope| closes the dictionary.
+  //
+  // To be constructed using:
+  //   |TracedValue::AppendDictionaryScoped|
+  //   |TracedValue::BeginDictionaryScoped|
+  //   |TracedValue::BeginDictionaryScopedWithCopiedName|
   //
   // |DictionaryScope| holds a |TracedValue| pointer which should remain a valid
-  // pointer at the time |DictionaryScope::~DictionaryScope| is called.
+  // pointer until |DictionaryScope::~DictionaryScope| is called.
   //
-  // |DictionaryScope::DictionaryScope| calls |TracedValue::BeginDictionary|
   // |DictionaryScope::~DictionaryScope| calls |TracedValue::EndDictionary|
   // (which checks if the held |TracedValue*| is in dictionary state).
   //
@@ -120,19 +131,25 @@
   //   }
   class BASE_EXPORT DictionaryScope {
    public:
+    DictionaryScope(const DictionaryScope&) = delete;
+    DictionaryScope(DictionaryScope&&) = default;
+    DictionaryScope& operator=(const DictionaryScope&) = delete;
+    DictionaryScope& operator=(DictionaryScope&&) = default;
     ~DictionaryScope();
 
    private:
     explicit DictionaryScope(TracedValue* value);
-    explicit DictionaryScope(TracedValue* value, const char* name);
 
     TracedValue* value_;
 
     friend class TracedValue;
   };
 
+  // Call |BeginDictionary| or |BeginDictionaryWithCopiedName| with no / the
+  // same parameter and return a |DictionaryScope| holding |this|.
   DictionaryScope AppendDictionaryScoped();
   DictionaryScope BeginDictionaryScoped(const char* name);
+  DictionaryScope BeginDictionaryScopedWithCopiedName(base::StringPiece name);
 
   class BASE_EXPORT Array;
   class BASE_EXPORT Dictionary;
diff --git a/base/trace_event/traced_value_unittest.cc b/base/trace_event/traced_value_unittest.cc
index e06faf00..a357e848 100644
--- a/base/trace_event/traced_value_unittest.cc
+++ b/base/trace_event/traced_value_unittest.cc
@@ -66,7 +66,7 @@
   {
     auto surround_dictionary =
         value->BeginDictionaryScoped("outside_dictionary");
-    value->SetBoolean("my_bool:", true);
+    value->SetBoolean("my_bool", true);
     {
       auto inside_array = value->BeginArrayScoped("inside_array");
       value->AppendBoolean(false);
@@ -81,22 +81,32 @@
     value->AppendBoolean(false);
     {
       auto inside_dictionary = value->AppendDictionaryScoped();
-      value->SetBoolean("my_bool:", true);
+      value->SetBoolean("my_bool", true);
     }
     {
       auto inside_array = value->AppendArrayScoped();
       value->AppendBoolean(false);
     }
   }
+  {
+    auto dictionary = value->BeginDictionaryScopedWithCopiedName(
+        std::string("wonderful_") + std::string("world"));
+  }
+  {
+    auto array = value->BeginArrayScopedWithCopiedName(
+        std::string("wonderful_") + std::string("array"));
+  }
   std::string json;
   value->AppendAsTraceFormat(&json);
   EXPECT_EQ(
       "{"
       "\"dictionary_name\":{\"my_int\":1},"
       "\"array_name\":[2],"
-      "\"outside_dictionary\":{\"my_bool:\":true,\"inside_array\":[false],"
+      "\"outside_dictionary\":{\"my_bool\":true,\"inside_array\":[false],"
       "\"inside_dictionary\":{\"inner_bool\":false}},"
-      "\"outside_array\":[false,{\"my_bool:\":true},[false]]"
+      "\"outside_array\":[false,{\"my_bool\":true},[false]],"
+      "\"wonderful_world\":{},"
+      "\"wonderful_array\":[]"
       "}",
       json);
 }
diff --git a/base/win/post_async_results.h b/base/win/post_async_results.h
index 81fb18f..cb6ccf31 100644
--- a/base/win/post_async_results.h
+++ b/base/win/post_async_results.h
@@ -65,6 +65,7 @@
   if (FAILED(hr)) {
     VLOG(2) << "GetAsyncResults failed: "
             << logging::SystemErrorCodeToString(hr);
+    return AsyncResultsT<T>{};
   }
 
   return results;
diff --git a/base/win/post_async_results_unittest.cc b/base/win/post_async_results_unittest.cc
new file mode 100644
index 0000000..adb0226
--- /dev/null
+++ b/base/win/post_async_results_unittest.cc
@@ -0,0 +1,204 @@
+// 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 "base/win/post_async_results.h"
+
+#include "base/test/bind_test_util.h"
+#include "base/test/fake_iasync_operation_win.h"
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ABI::Windows::Foundation::IAsyncOperation;
+using ABI::Windows::Foundation::IAsyncOperation_impl;
+using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
+using ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl;
+using Microsoft::WRL::ComPtr;
+
+namespace {
+class TestClassImplementingIUnknown
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<
+              Microsoft::WRL::WinRtClassicComMix |
+              Microsoft::WRL::InhibitRoOriginateError>,
+          IUnknown> {};
+}  // namespace
+
+namespace ABI {
+namespace Windows {
+namespace Foundation {
+
+template <>
+struct __declspec(uuid("3895C200-8F26-4F5A-B29D-2B5D72E68F99"))
+    IAsyncOperation<IUnknown*> : IAsyncOperation_impl<IUnknown*> {};
+
+template <>
+struct __declspec(uuid("CD99A253-6473-4810-AF0D-763DAB79AC42"))
+    IAsyncOperationCompletedHandler<IUnknown*>
+    : IAsyncOperationCompletedHandler_impl<IUnknown*> {};
+
+template <>
+struct __declspec(uuid("CB52D855-8121-4AC8-A164-084A27FB377E"))
+    IAsyncOperation<int*> : IAsyncOperation_impl<int*> {};
+
+template <>
+struct __declspec(uuid("EA868415-A724-40BC-950A-C7DB6B1723C6"))
+    IAsyncOperationCompletedHandler<int*>
+    : IAsyncOperationCompletedHandler_impl<int*> {};
+
+// These specialization templates were included in windows.foundation.h, but
+// removed in 10.0.19041.0 SDK, so are included here conditionally
+#ifdef NTDDI_WIN10_VB  // Windows 10.0.19041
+template <>
+struct __declspec(uuid("968b9665-06ed-5744-8f53-8edeabd5f7b5"))
+    IAsyncOperation<int> : IAsyncOperation_impl<int> {};
+
+template <>
+struct __declspec(uuid("d60cae9d-88cb-59f1-8576-3fba44796be8"))
+    IAsyncOperationCompletedHandler<int>
+    : IAsyncOperationCompletedHandler_impl<int> {};
+#endif
+
+}  // namespace Foundation
+}  // namespace Windows
+}  // namespace ABI
+
+namespace base {
+namespace win {
+
+TEST(PostAsyncResultsTest, ValueType_Success) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<int>>();
+  ComPtr<IAsyncOperation<int>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  int value_received = 1;
+  ASSERT_EQ(
+      PostAsyncResults(async_op, base::BindLambdaForTesting([&](int result) {
+                         value_received = result;
+                         std::move(quit_closure).Run();
+                       })),
+      S_OK);
+
+  ASSERT_NO_FATAL_FAILURE(fake_iasync_op->CompleteWithResults(7));
+  run_loop.Run();
+  ASSERT_EQ(7, value_received);
+}
+
+TEST(PostAsyncResultsTest, ValueType_Failure) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<int>>();
+  ComPtr<IAsyncOperation<int>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  int value_received = 1;
+  ASSERT_EQ(
+      PostAsyncResults(async_op, base::BindLambdaForTesting([&](int result) {
+                         value_received = result;
+                         std::move(quit_closure).Run();
+                       })),
+      S_OK);
+
+  ASSERT_NO_FATAL_FAILURE(fake_iasync_op->CompleteWithError(E_FAIL));
+  run_loop.Run();
+  ASSERT_EQ(value_received, 0);
+}
+
+TEST(PostAsyncResultsTest, PointerType_Success) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<int*>>();
+  ComPtr<IAsyncOperation<int*>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  int* value_received = nullptr;
+  ASSERT_EQ(
+      PostAsyncResults(async_op, base::BindLambdaForTesting([&](int* result) {
+                         value_received = result;
+                         std::move(quit_closure).Run();
+                       })),
+      S_OK);
+
+  int test_value = 4;
+  ASSERT_NO_FATAL_FAILURE(fake_iasync_op->CompleteWithResults(&test_value));
+  run_loop.Run();
+  ASSERT_EQ(&test_value, value_received);
+}
+
+TEST(PostAsyncResultsTest, PointerType_Failure) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<int*>>();
+  ComPtr<IAsyncOperation<int*>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  int test_value = 2;
+  int* value_received = &test_value;
+  ASSERT_EQ(
+      PostAsyncResults(async_op, base::BindLambdaForTesting([&](int* result) {
+                         value_received = result;
+                         std::move(quit_closure).Run();
+                       })),
+      S_OK);
+
+  ASSERT_NO_FATAL_FAILURE(fake_iasync_op->CompleteWithError(E_FAIL));
+  run_loop.Run();
+  ASSERT_EQ(nullptr, value_received);
+}
+
+TEST(PostAsyncResultsTest, IUnknownType_Success) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<IUnknown*>>();
+  ComPtr<IAsyncOperation<IUnknown*>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  ComPtr<IUnknown> value_received = nullptr;
+  ASSERT_EQ(PostAsyncResults(async_op, base::BindLambdaForTesting(
+                                           [&](ComPtr<IUnknown> result) {
+                                             value_received = result;
+                                             std::move(quit_closure).Run();
+                                           })),
+            S_OK);
+
+  auto test_value = Microsoft::WRL::Make<TestClassImplementingIUnknown>();
+  ComPtr<IUnknown> value_to_send;
+  ASSERT_EQ(test_value.As(&value_to_send), S_OK);
+  ASSERT_NO_FATAL_FAILURE(
+      fake_iasync_op->CompleteWithResults(value_to_send.Get()));
+  run_loop.Run();
+  ASSERT_EQ(value_to_send.Get(), value_received.Get());
+}
+
+TEST(PostAsyncResultsTest, IUnknownType_Failure) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  auto fake_iasync_op = Microsoft::WRL::Make<FakeIAsyncOperation<IUnknown*>>();
+  ComPtr<IAsyncOperation<IUnknown*>> async_op;
+  ASSERT_EQ(fake_iasync_op.As(&async_op), S_OK);
+
+  RunLoop run_loop;
+  auto quit_closure = run_loop.QuitClosure();
+  auto test_value = Microsoft::WRL::Make<TestClassImplementingIUnknown>();
+  ComPtr<IUnknown> value_received;
+  ASSERT_EQ(test_value.As(&value_received), S_OK);
+  ASSERT_EQ(PostAsyncResults(async_op, base::BindLambdaForTesting(
+                                           [&](ComPtr<IUnknown> result) {
+                                             value_received = result;
+                                             std::move(quit_closure).Run();
+                                           })),
+            S_OK);
+
+  ASSERT_NO_FATAL_FAILURE(fake_iasync_op->CompleteWithError(E_FAIL));
+  run_loop.Run();
+  ASSERT_EQ(nullptr, value_received.Get());
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/build/linux/sysroot_scripts/libwayland-client-symbols b/build/linux/sysroot_scripts/libwayland-client-symbols
index d6bffeb..6e8a01f 100644
--- a/build/linux/sysroot_scripts/libwayland-client-symbols
+++ b/build/linux/sysroot_scripts/libwayland-client-symbols
@@ -1,74 +1,75 @@
 libwayland-client.so.0 libwayland-client0 #MINVER#
- wl_array_add@Base 1.4.0
- wl_array_copy@Base 1.4.0
- wl_array_init@Base 1.4.0
- wl_array_release@Base 1.4.0
- wl_buffer_interface@Base 1.4.0
- wl_callback_interface@Base 1.4.0
- wl_compositor_interface@Base 1.4.0
- wl_data_device_interface@Base 1.4.0
- wl_data_device_manager_interface@Base 1.4.0
- wl_data_offer_interface@Base 1.4.0
- wl_data_source_interface@Base 1.4.0
- wl_display_cancel_read@Base 1.4.0
- wl_display_connect@Base 1.4.0
- wl_display_connect_to_fd@Base 1.4.0
- wl_display_create_queue@Base 1.4.0
- wl_display_disconnect@Base 1.4.0
- wl_display_dispatch@Base 1.4.0
- wl_display_dispatch_pending@Base 1.4.0
- wl_display_dispatch_queue@Base 1.4.0
- wl_display_dispatch_queue_pending@Base 1.4.0
- wl_display_flush@Base 1.4.0
- wl_display_get_error@Base 1.4.0
- wl_display_get_fd@Base 1.4.0
- wl_display_get_protocol_error@Base 1.4.0
- wl_display_interface@Base 1.4.0
- wl_display_prepare_read@Base 1.4.0
- wl_display_prepare_read_queue@Base 1.4.0
- wl_display_read_events@Base 1.4.0
- wl_display_roundtrip@Base 1.4.0
- wl_display_roundtrip_queue@Base 1.4.0
- wl_event_queue_destroy@Base 1.4.0
- wl_keyboard_interface@Base 1.4.0
- wl_list_empty@Base 1.4.0
- wl_list_init@Base 1.4.0
- wl_list_insert@Base 1.4.0
- wl_list_insert_list@Base 1.4.0
- wl_list_length@Base 1.4.0
- wl_list_remove@Base 1.4.0
- wl_log_set_handler_client@Base 1.4.0
- wl_output_interface@Base 1.4.0
- wl_pointer_interface@Base 1.4.0
- wl_proxy_add_dispatcher@Base 1.4.0
- wl_proxy_add_listener@Base 1.4.0
- wl_proxy_create@Base 1.4.0
- wl_proxy_create_wrapper@Base 1.4.0
- wl_proxy_destroy@Base 1.4.0
- wl_proxy_get_class@Base 1.4.0
- wl_proxy_get_id@Base 1.4.0
- wl_proxy_get_listener@Base 1.4.0
- wl_proxy_get_tag@Base 1.4.0
- wl_proxy_get_user_data@Base 1.4.0
- wl_proxy_get_version@Base 1.4.0
- wl_proxy_marshal@Base 1.4.0
- wl_proxy_marshal_array@Base 1.4.0
- wl_proxy_marshal_array_constructor@Base 1.4.0
- wl_proxy_marshal_array_constructor_versioned@Base 1.4.0
- wl_proxy_marshal_constructor@Base 1.4.0
- wl_proxy_marshal_constructor_versioned@Base 1.4.0
- wl_proxy_set_queue@Base 1.4.0
- wl_proxy_set_tag@Base 1.4.0
- wl_proxy_set_user_data@Base 1.4.0
- wl_proxy_wrapper_destroy@Base 1.4.0
- wl_region_interface@Base 1.4.0
- wl_registry_interface@Base 1.4.0
- wl_seat_interface@Base 1.4.0
- wl_shell_interface@Base 1.4.0
- wl_shell_surface_interface@Base 1.4.0
- wl_shm_interface@Base 1.4.0
- wl_shm_pool_interface@Base 1.4.0
- wl_subcompositor_interface@Base 1.4.0
- wl_subsurface_interface@Base 1.4.0
- wl_surface_interface@Base 1.4.0
- wl_touch_interface@Base 1.4.0
+* Build-Depends-Package: libwayland-dev
+ wl_array_add@Base 1.0.2
+ wl_array_copy@Base 1.0.2
+ wl_array_init@Base 1.0.2
+ wl_array_release@Base 1.0.2
+ wl_buffer_interface@Base 1.0.2
+ wl_callback_interface@Base 1.0.2
+ wl_compositor_interface@Base 1.0.2
+ wl_data_device_interface@Base 1.0.2
+ wl_data_device_manager_interface@Base 1.0.2
+ wl_data_offer_interface@Base 1.0.2
+ wl_data_source_interface@Base 1.0.2
+ wl_display_cancel_read@Base 1.2.0
+ wl_display_connect@Base 1.0.2
+ wl_display_connect_to_fd@Base 1.0.2
+ wl_display_create_queue@Base 1.0.2
+ wl_display_disconnect@Base 1.0.2
+ wl_display_dispatch@Base 1.0.2
+ wl_display_dispatch_pending@Base 1.0.2
+ wl_display_dispatch_queue@Base 1.0.2
+ wl_display_dispatch_queue_pending@Base 1.0.2
+ wl_display_flush@Base 1.0.2
+ wl_display_get_error@Base 1.0.2
+ wl_display_get_fd@Base 1.0.2
+ wl_display_get_protocol_error@Base 1.5.91
+ wl_display_interface@Base 1.0.2
+ wl_display_prepare_read@Base 1.2.0
+ wl_display_prepare_read_queue@Base 1.2.0
+ wl_display_read_events@Base 1.2.0
+ wl_display_roundtrip@Base 1.0.2
+ wl_display_roundtrip_queue@Base 1.5.91
+ wl_event_queue_destroy@Base 1.0.2
+ wl_keyboard_interface@Base 1.0.2
+ wl_list_empty@Base 1.0.2
+ wl_list_init@Base 1.0.2
+ wl_list_insert@Base 1.0.2
+ wl_list_insert_list@Base 1.0.2
+ wl_list_length@Base 1.0.2
+ wl_list_remove@Base 1.0.2
+ wl_log_set_handler_client@Base 1.0.2
+ wl_output_interface@Base 1.0.2
+ wl_pointer_interface@Base 1.0.2
+ wl_proxy_add_dispatcher@Base 1.3.0
+ wl_proxy_add_listener@Base 1.0.2
+ wl_proxy_create@Base 1.0.2
+ wl_proxy_create_wrapper@Base 1.11.0
+ wl_proxy_destroy@Base 1.0.2
+ wl_proxy_get_class@Base 1.1.0
+ wl_proxy_get_id@Base 1.0.2
+ wl_proxy_get_listener@Base 1.3.0
+ wl_proxy_get_tag@Base 1.17.93
+ wl_proxy_get_user_data@Base 1.0.2
+ wl_proxy_get_version@Base 1.9.91
+ wl_proxy_marshal@Base 1.0.2
+ wl_proxy_marshal_array@Base 1.3.0
+ wl_proxy_marshal_array_constructor@Base 1.3.92
+ wl_proxy_marshal_array_constructor_versioned@Base 1.9.91
+ wl_proxy_marshal_constructor@Base 1.3.92
+ wl_proxy_marshal_constructor_versioned@Base 1.9.91
+ wl_proxy_set_queue@Base 1.0.2
+ wl_proxy_set_tag@Base 1.17.93
+ wl_proxy_set_user_data@Base 1.0.2
+ wl_proxy_wrapper_destroy@Base 1.11.0
+ wl_region_interface@Base 1.0.2
+ wl_registry_interface@Base 1.0.2
+ wl_seat_interface@Base 1.0.2
+ wl_shell_interface@Base 1.0.2
+ wl_shell_surface_interface@Base 1.0.2
+ wl_shm_interface@Base 1.0.2
+ wl_shm_pool_interface@Base 1.0.2
+ wl_subcompositor_interface@Base 1.3.92
+ wl_subsurface_interface@Base 1.3.92
+ wl_surface_interface@Base 1.0.2
+ wl_touch_interface@Base 1.0.2
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 368bda5..b524fbcb 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1053,9 +1053,9 @@
     "//components/download/public/common:public_java",
     "//components/embedder_support/android:browser_context_java",
     "//components/embedder_support/android:content_view_java",
+    "//components/embedder_support/android:embedder_support_javatests",
     "//components/embedder_support/android:util_java",
     "//components/embedder_support/android:web_contents_delegate_java",
-    "//components/embedder_support/android:web_contents_delegate_javatests",
     "//components/external_intents/android:java",
     "//components/external_intents/android:javatests",
     "//components/feature_engagement:feature_engagement_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
index 4b0d0b4..9323159 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
@@ -81,28 +81,29 @@
         }
 
         final boolean setUp = getFirstRunFlowSignInSetup();
-        signinManager.signIn(SigninAccessPoint.START_PAGE, account, new SignInCallback() {
-            @Override
-            public void onSignInComplete() {
-                UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled(
-                        Profile.getLastUsedRegularProfile(), true);
-                // Show sync settings if user pressed the "Settings" button.
-                if (setUp) {
-                    openSignInSettings(activity);
-                } else {
-                    ProfileSyncService.get().setFirstSetupComplete(
-                            SyncFirstSetupCompleteSource.BASIC_FLOW);
-                }
-                setFirstRunFlowSignInComplete(true);
-            }
+        signinManager.signinAndEnableSync(
+                SigninAccessPoint.START_PAGE, account, new SignInCallback() {
+                    @Override
+                    public void onSignInComplete() {
+                        UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled(
+                                Profile.getLastUsedRegularProfile(), true);
+                        // Show sync settings if user pressed the "Settings" button.
+                        if (setUp) {
+                            openSignInSettings(activity);
+                        } else {
+                            ProfileSyncService.get().setFirstSetupComplete(
+                                    SyncFirstSetupCompleteSource.BASIC_FLOW);
+                        }
+                        setFirstRunFlowSignInComplete(true);
+                    }
 
-            @Override
-            public void onSignInAborted() {
-                // Set FRE as complete even if signin fails because the user has already seen and
-                // accepted the terms of service.
-                setFirstRunFlowSignInComplete(true);
-            }
-        });
+                    @Override
+                    public void onSignInAborted() {
+                        // Set FRE as complete even if signin fails because the user has already
+                        // seen and accepted the terms of service.
+                        setFirstRunFlowSignInComplete(true);
+                    }
+                });
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
index 29d991d..a240caa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
@@ -85,7 +85,7 @@
                 Log.d(TAG, "Incorrect number of accounts (%d)", accounts.size());
                 return;
             }
-            signinManager.signIn(SigninAccessPoint.FORCED_SIGNIN, accounts.get(0),
+            signinManager.signinAndEnableSync(SigninAccessPoint.FORCED_SIGNIN, accounts.get(0),
                     new SigninManager.SignInCallback() {
                         @Override
                         public void onSignInComplete() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
index 2bab8a7..96270d2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
@@ -142,7 +142,7 @@
         }
         SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
                 Profile.getLastUsedRegularProfile());
-        signinManager.signIn(
+        signinManager.signinAndEnableSync(
                 mSigninAccessPoint, account, new SigninManager.SignInCallback() {
                     @Override
                     public void onSignInComplete() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index 32de32be..1564ffb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -206,15 +206,16 @@
         // This is the correct account now.
         final Account account = AccountUtils.createAccountFromName(newName);
 
-        mSigninManager.signIn(SigninAccessPoint.ACCOUNT_RENAMED, account, new SignInCallback() {
-            @Override
-            public void onSignInComplete() {
-                validateAccountsInternal(true);
-            }
+        mSigninManager.signinAndEnableSync(
+                SigninAccessPoint.ACCOUNT_RENAMED, account, new SignInCallback() {
+                    @Override
+                    public void onSignInComplete() {
+                        validateAccountsInternal(true);
+                    }
 
-            @Override
-            public void onSignInAborted() {}
-        });
+                    @Override
+                    public void onSignInAborted() {}
+                });
     }
 
     private static boolean accountExists(Account account) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index 7154449..4d49b17 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -251,7 +251,7 @@
 
     /**
      * Logs the access point when the user see the view of choosing account to sign in. Sign-in
-     * completion histogram is recorded by {@link #signIn}.
+     * completion histogram is recorded by {@link #signinAndEnableSync}.
      *
      * @param accessPoint {@link SigninAccessPoint} that initiated the sign-in flow.
      */
@@ -367,14 +367,15 @@
      * @param accountInfo The account to sign in to.
      * @param callback Optional callback for when the sign-in process is finished.
      */
-    public void signIn(@SigninAccessPoint int accessPoint, CoreAccountInfo accountInfo,
+    public void signinAndEnableSync(@SigninAccessPoint int accessPoint, CoreAccountInfo accountInfo,
             @Nullable SignInCallback callback) {
         assert accountInfo != null;
-        signIn(accessPoint, AccountUtils.createAccountFromName(accountInfo.getEmail()), callback);
+        signinAndEnableSync(
+                accessPoint, AccountUtils.createAccountFromName(accountInfo.getEmail()), callback);
     }
 
     /**
-     * @deprecated use {@link #signIn(int, CoreAccountInfo, SignInCallback)} instead.
+     * @deprecated use {@link #signinAndEnableSync(int, CoreAccountInfo, SignInCallback)} instead.
      * TODO(crbug.com/1002056): Remove this version after migrating all callers to CoreAccountInfo.
      *
      * Starts the sign-in flow, and executes the callback when finished.
@@ -392,7 +393,7 @@
      * @param callback Optional callback for when the sign-in process is finished.
      */
     @Deprecated
-    public void signIn(@SigninAccessPoint int accessPoint, Account account,
+    public void signinAndEnableSync(@SigninAccessPoint int accessPoint, Account account,
             @Nullable SignInCallback callback) {
         assert isSignInAllowed() : "Sign-in isn't allowed!";
         if (account == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
index c9b9af2..77ff151 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
@@ -69,7 +69,7 @@
         mOnSignInErrorCallback = onSignInErrorCallback;
         mWebSigninBridge = mWebSigninBridgeFactory.create(
                 Profile.getLastUsedRegularProfile(), coreAccountInfo, this);
-        mSigninManager.signIn(
+        mSigninManager.signinAndEnableSync(
                 SigninAccessPoint.WEB_SIGNIN, coreAccountInfo, new SigninManager.SignInCallback() {
                     @Override
                     public void onSignInComplete() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncAndServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncAndServicesSettings.java
index 5e9808c..b0ab351 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncAndServicesSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncAndServicesSettings.java
@@ -538,7 +538,8 @@
                             ()
                                     -> IdentityServicesProvider.get()
                                                .getSigninManager(getProfile())
-                                               .signIn(SigninAccessPoint.SYNC_ERROR_CARD, account,
+                                               .signinAndEnableSync(
+                                                       SigninAccessPoint.SYNC_ERROR_CARD, account,
                                                        null),
                             false);
             return;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 0dd47bdb..cafe11d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -566,7 +566,7 @@
             IdentityServicesProvider.get().getSigninManager(profile).onFirstRunCheckDone();
             IdentityServicesProvider.get().getSigninManager(profile).addSignInStateObserver(
                     mTestObserver);
-            IdentityServicesProvider.get().getSigninManager(profile).signIn(
+            IdentityServicesProvider.get().getSigninManager(profile).signinAndEnableSync(
                     SigninAccessPoint.UNKNOWN, account, null);
         });
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/previewtab/PreviewTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/previewtab/PreviewTabTest.java
index ed2d5e4..9fec625 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/previewtab/PreviewTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/previewtab/PreviewTabTest.java
@@ -22,6 +22,7 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.firstrun.DisableFirstRun;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.incognito.IncognitoUtils;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabbed_mode.TabbedRootUiCoordinator;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -29,6 +30,8 @@
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport;
 import org.chromium.content_public.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -77,6 +80,10 @@
                                                                .getBottomSheetController());
     }
 
+    /**
+     * End all animations that already started before so that the UI will be in a state ready
+     * for the next command.
+     */
     private void endAnimations() {
         TestThreadUtils.runOnUiThreadBlocking(mSheetTestSupport::endAllAnimations);
     }
@@ -115,6 +122,39 @@
     }
 
     /**
+     * Test that closing all incognito tabs successfully handles the base tab and
+     * its preview tab opened in incognito mode. This makes sure an incognito profile
+     * shared by the tabs is destroyed safely.
+     */
+    @Test
+    @MediumTest
+    @Feature({"PreviewTab"})
+    public void testCloseAllIncognitoTabsClosesPreviewTab() throws Throwable {
+        Assert.assertFalse("Test should have started without any Preview Tab",
+                mEphemeralTabCoordinator.isOpened());
+
+        mActivityTestRule.loadUrlInNewTab(mTestServer.getServer().getURL(BASE_PAGE),
+                /*incognito=*/true);
+        mActivityTestRule.getActivity().getTabModelSelector().selectModel(true);
+        ChromeActivity activity = mActivityTestRule.getActivity();
+        Tab tab = activity.getActivityTab();
+        Assert.assertTrue(tab.isIncognito());
+
+        ContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(),
+                activity, tab, PREVIEW_TAB_DOM_ID, R.id.contextmenu_open_in_ephemeral_tab);
+        endAnimations();
+        BottomSheetController bottomSheet =
+                activity.getRootUiCoordinatorForTesting().getBottomSheetController();
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            bottomSheet.expandSheet();
+            endAnimations();
+            IncognitoUtils.closeAllIncognitoTabs();
+            endAnimations();
+        });
+        Assert.assertEquals(SheetState.HIDDEN, bottomSheet.getSheetState());
+    }
+
+    /**
      * Test preview tab suppresses contextual search.
      */
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
index 01be172..bb1de5a19 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
@@ -229,8 +229,9 @@
     private void signIn() {
         Account account = mAccountManagerTestRule.addAccountAndWaitForSeeding(
                 AccountManagerTestRule.TEST_ACCOUNT_EMAIL);
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mSigninManager.signIn(SigninAccessPoint.SETTINGS, account, null); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mSigninManager.signinAndEnableSync(SigninAccessPoint.SETTINGS, account, null);
+        });
         assertSignedIn();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
index 6c62151..f4c940ef 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -414,20 +414,21 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             IdentityServicesProvider.get()
                     .getSigninManager(Profile.getLastUsedRegularProfile())
-                    .signIn(SigninAccessPoint.UNKNOWN, account, new SigninManager.SignInCallback() {
-                        @Override
-                        public void onSignInComplete() {
-                            if (setFirstSetupComplete) {
-                                mProfileSyncService.setFirstSetupComplete(
-                                        SyncFirstSetupCompleteSource.BASIC_FLOW);
-                            }
-                        }
+                    .signinAndEnableSync(
+                            SigninAccessPoint.UNKNOWN, account, new SigninManager.SignInCallback() {
+                                @Override
+                                public void onSignInComplete() {
+                                    if (setFirstSetupComplete) {
+                                        mProfileSyncService.setFirstSetupComplete(
+                                                SyncFirstSetupCompleteSource.BASIC_FLOW);
+                                    }
+                                }
 
-                        @Override
-                        public void onSignInAborted() {
-                            Assert.fail("Sign-in was aborted");
-                        }
-                    });
+                                @Override
+                                public void onSignInAborted() {
+                                    Assert.fail("Sign-in was aborted");
+                                }
+                            });
             // Outside of tests, URL-keyed anonymized data collection is enabled by sign-in UI.
             UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled(
                     Profile.getLastUsedRegularProfile(), true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
index 1d3c1f5..78bc1b0f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
@@ -20,7 +20,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.MathUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -102,11 +101,6 @@
         });
     }
 
-    /** @return The height of the container view. */
-    private int getContainerHeight() {
-        return mActivityTestRule.getActivity().getActivityTabProvider().get().getView().getHeight();
-    }
-
     @Test
     @SmallTest
     @Feature({"BottomSheetController"})
@@ -434,30 +428,30 @@
     @MediumTest
     public void testCustomHalfRatio() throws TimeoutException {
         final float customHalfHeight = 0.3f;
-        int containerHeight = getContainerHeight();
         mLowPriorityContent.setHalfHeightRatio(customHalfHeight);
         requestContentInSheet(mLowPriorityContent, true);
 
         expandSheet();
 
-        assertEquals("Half height is incorrect for custom ratio.",
-                (int) (customHalfHeight * containerHeight), mSheetController.getCurrentOffset(),
-                MathUtils.EPSILON);
+        int computedOffset = (int) (customHalfHeight
+                * (mSheetController.getContainerHeight() + mSheetController.getTopShadowHeight()));
+        assertEquals("Half height is incorrect for custom ratio.", computedOffset,
+                mSheetController.getCurrentOffset());
     }
 
     @Test
     @MediumTest
     public void testCustomFullRatio() throws TimeoutException {
         final float customFullHeight = 0.5f;
-        int containerHeight = getContainerHeight();
         mLowPriorityContent.setFullHeightRatio(customFullHeight);
         requestContentInSheet(mLowPriorityContent, true);
 
         maximizeSheet();
 
-        assertEquals("Full height is incorrect for custom ratio.",
-                (int) (customFullHeight * containerHeight), mSheetController.getCurrentOffset(),
-                MathUtils.EPSILON);
+        int computedOffset = (int) (customFullHeight
+                * (mSheetController.getContainerHeight() + mSheetController.getTopShadowHeight()));
+        assertEquals("Full height is incorrect for custom ratio.", computedOffset,
+                mSheetController.getCurrentOffset());
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
index 1594a53..e16d0530 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -99,7 +99,7 @@
                         eq(mAccount.getEmail()));
 
         mSigninManager.onFirstRunCheckDone();
-        mSigninManager.signIn(SigninAccessPoint.START_PAGE, mAccount, null);
+        mSigninManager.signinAndEnableSync(SigninAccessPoint.START_PAGE, mAccount, null);
 
         verify(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), eq(mAccount), any());
     }
@@ -251,7 +251,7 @@
 
         mSigninManager.onFirstRunCheckDone(); // Allow sign-in.
 
-        mSigninManager.signIn(SigninAccessPoint.UNKNOWN, account, null);
+        mSigninManager.signinAndEnableSync(SigninAccessPoint.UNKNOWN, account, null);
         assertTrue(mSigninManager.isOperationInProgress());
         AtomicInteger callCount = new AtomicInteger(0);
         mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
@@ -280,7 +280,7 @@
 
         mSigninManager.onFirstRunCheckDone(); // Allow sign-in.
 
-        mSigninManager.signIn(SigninAccessPoint.UNKNOWN, account, null);
+        mSigninManager.signinAndEnableSync(SigninAccessPoint.UNKNOWN, account, null);
         assertTrue(mSigninManager.isOperationInProgress());
 
         // The following should throw an assertion error
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegateTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegateTest.java
index 88514cb4..a281d44b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegateTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegateTest.java
@@ -113,7 +113,7 @@
         calledInOrder.verify(mWebSigninBridgeFactoryMock)
                 .create(mProfileMock, coreAccountInfo, mDelegate);
         calledInOrder.verify(mSigninManagerMock)
-                .signIn(eq(SigninAccessPoint.WEB_SIGNIN), eq(coreAccountInfo), any());
+                .signinAndEnableSync(eq(SigninAccessPoint.WEB_SIGNIN), eq(coreAccountInfo), any());
         mDelegate.onSigninSucceded();
         verify(mChromeActivityMock.getActivityTab()).loadUrl(mLoadUrlParamsCaptor.capture());
         LoadUrlParams loadUrlParams = mLoadUrlParamsCaptor.getValue();
@@ -131,7 +131,7 @@
             return null;
         })
                 .when(mSigninManagerMock)
-                .signIn(eq(SigninAccessPoint.WEB_SIGNIN), eq(coreAccountInfo), any());
+                .signinAndEnableSync(eq(SigninAccessPoint.WEB_SIGNIN), eq(coreAccountInfo), any());
         mDelegate.signIn(coreAccountInfo, error -> {});
         verify(mWebSigninBridgeMock).destroy();
     }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4f7fe3a..c84d3d74 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4401,11 +4401,6 @@
      flag_descriptions::kAutofillProfileServerValidationDescription, kOsAll,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillProfileServerValidation)},
 
-    {"autofill-reject-company-birthyear",
-     flag_descriptions::kAutofillRejectCompanyBirthyearName,
-     flag_descriptions::kAutofillRejectCompanyBirthyearDescription, kOsAll,
-     FEATURE_VALUE_TYPE(autofill::features::kAutofillRejectCompanyBirthyear)},
-
     {"autofill-restrict-formless-form-extraction",
      flag_descriptions::kAutofillRestrictUnownedFieldsToFormlessCheckoutName,
      flag_descriptions::
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index 8964ade..134d8c2 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -841,19 +841,26 @@
 
   // For BROWSE state the back button should react in its default way.
   if (ui_delegate_ != nullptr &&
-      ui_delegate_->GetState() == AutofillAssistantState::BROWSE) {
+      (ui_delegate_->GetState() == AutofillAssistantState::BROWSE)) {
     return false;
   }
 
   if (ui_delegate_ == nullptr ||
-      ui_delegate_->GetState() == AutofillAssistantState::STOPPED) {
+      ui_delegate_->GetState() == AutofillAssistantState::STOPPED ||
+      ui_delegate_->IsRunningLiteScript()) {
     if (client_->GetWebContents() != nullptr &&
         client_->GetWebContents()->GetController().CanGoBack()) {
       client_->GetWebContents()->GetController().GoBack();
     }
-    DestroySelf();  // Destroying UI here because Shutdown does not do so in
-                    // all cases.
-    Shutdown(Metrics::DropOutReason::BACK_BUTTON_CLICKED);
+
+    // Lite scripts should not shut down here. The navigation will be handled
+    // by the lite script coordinator.
+    if (!ui_delegate_ || !ui_delegate_->IsRunningLiteScript()) {
+      // Destroying UI here because Shutdown does not do so in all cases.
+      DestroySelf();
+      Shutdown(Metrics::DropOutReason::BACK_BUTTON_CLICKED);
+    }
+
     return true;
   }
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 49a1f223..59a1243 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -450,8 +450,8 @@
   // Managed devices and supervised users can have restrictions on history
   // deletion.
   PrefService* prefs = profile_->GetPrefs();
-  bool may_delete_history = prefs->GetBoolean(
-      prefs::kAllowDeletingBrowserHistory);
+  bool may_delete_history =
+      prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory);
 
   // All the UI entry points into the BrowsingDataRemoverImpl should be
   // disabled, but this will fire if something was missed or added.
@@ -547,8 +547,8 @@
         WebDataServiceFactory::GetAutofillWebDataForProfile(
             profile_, ServiceAccessType::EXPLICIT_ACCESS);
     if (web_data_service.get()) {
-      web_data_service->RemoveOriginURLsModifiedBetween(
-          delete_begin_, delete_end_);
+      web_data_service->RemoveOriginURLsModifiedBetween(delete_begin_,
+                                                        delete_end_);
       // Ask for a call back when the above call is finished.
       web_data_service->GetDBTaskRunner()->PostTaskAndReply(
           FROM_HERE, base::DoNothing(),
@@ -892,6 +892,10 @@
           CreateTaskCompletionClosure(TracingDataType::kAccountPasswords),
           CreateTaskCompletionCallback(TracingDataType::kAccountPasswordsSynced,
                                        DATA_TYPE_PASSWORDS));
+      account_store->RemoveCompromisedCredentialsByUrlAndTime(
+          nullable_filter, delete_begin_, delete_end_,
+          CreateTaskCompletionClosure(
+              TracingDataType::kAccountCompromisedCredentials));
     }
 
     BrowserContext::GetDefaultStoragePartition(profile_)
@@ -939,8 +943,9 @@
 
   if (remove_mask & DATA_TYPE_HISTORY) {
     password_manager::PasswordStore* password_store =
-        PasswordStoreFactory::GetForProfile(
-            profile_, ServiceAccessType::EXPLICIT_ACCESS).get();
+        PasswordStoreFactory::GetForProfile(profile_,
+                                            ServiceAccessType::EXPLICIT_ACCESS)
+            .get();
 
     if (password_store) {
       password_store->RemoveStatisticsByOriginAndTime(
@@ -964,9 +969,9 @@
 
     if (web_data_service.get()) {
       web_data_service->RemoveFormElementsAddedBetween(delete_begin_,
-          delete_end_);
-      web_data_service->RemoveAutofillDataModifiedBetween(
-          delete_begin_, delete_end_);
+                                                       delete_end_);
+      web_data_service->RemoveAutofillDataModifiedBetween(delete_begin_,
+                                                          delete_end_);
       // Clear out the Autofill StrikeDatabase in its entirety.
       // TODO(crbug.com/884817): Respect |delete_begin_| and |delete_end_| and
       // only clear out entries whose last strikes were created in that
@@ -1117,8 +1122,7 @@
 
     if (filter_builder->MatchesAllOriginsAndDomains()) {
       DCHECK(!plugin_data_remover_);
-      plugin_data_remover_.reset(
-          content::PluginDataRemover::Create(profile_));
+      plugin_data_remover_.reset(content::PluginDataRemover::Create(profile_));
       base::WaitableEvent* event =
           plugin_data_remover_->StartRemoving(delete_begin_);
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
index 942dc41..1ea832a9 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
@@ -246,7 +246,8 @@
     kMediaFeeds = 36,
     kAccountPasswords = 37,
     kAccountPasswordsSynced = 38,
-    kMaxValue = kAccountPasswordsSynced,
+    kAccountCompromisedCredentials = 39,
+    kMaxValue = kAccountCompromisedCredentials,
   };
 
   // Called by CreateTaskCompletionClosure().
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index ded1333..31d3d601 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -174,8 +174,8 @@
 using testing::Eq;
 using testing::FloatEq;
 using testing::Invoke;
-using testing::Matcher;
 using testing::MakeMatcher;
+using testing::Matcher;
 using testing::MatcherInterface;
 using testing::MatchResultListener;
 using testing::Return;
@@ -234,7 +234,7 @@
 #if defined(OS_ANDROID)
 class TestWebappRegistry : public WebappRegistry {
  public:
-  TestWebappRegistry() : WebappRegistry() { }
+  TestWebappRegistry() : WebappRegistry() {}
 
   void UnregisterWebappsForUrls(
       const base::RepeatingCallback<bool(const GURL&)>& url_filter) override {
@@ -1221,9 +1221,8 @@
 
     content::BrowsingDataRemoverCompletionObserver completion_observer(
         remover_);
-    remover_->RemoveAndReply(
-        delete_begin, delete_end, remove_mask, origin_type_mask,
-        &completion_observer);
+    remover_->RemoveAndReply(delete_begin, delete_end, remove_mask,
+                             origin_type_mask, &completion_observer);
     base::ThreadPoolInstance::Get()->FlushForTesting();
     completion_observer.BlockUntilCompletion();
     return completion_observer.failed_data_types();
@@ -1258,9 +1257,7 @@
 
   network::NetworkContext* network_context() { return network_context_.get(); }
 
-  TestingProfile* GetProfile() {
-    return profile_.get();
-  }
+  TestingProfile* GetProfile() { return profile_.get(); }
 
   bool Match(const GURL& origin,
              uint64_t mask,
@@ -1476,8 +1473,8 @@
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY |
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
 
-  BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(),
-                                removal_mask, false);
+  BlockUntilBrowsingDataRemoved(AnHourAgo(), base::Time::Max(), removal_mask,
+                                false);
   EXPECT_EQ(removal_mask, GetRemovalMask());
   EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
             GetOriginTypeMask());
@@ -1975,8 +1972,7 @@
 // ChromeDownloadManagerDelegate is correctly created and shut down.
 TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveDownloads) {
   RemoveDownloadsTester tester(GetProfile());
-  EXPECT_CALL(
-      *tester.download_manager(), RemoveDownloadsByURLAndTime(_, _, _));
+  EXPECT_CALL(*tester.download_manager(), RemoveDownloadsByURLAndTime(_, _, _));
 
   BlockUntilBrowsingDataRemoved(
       base::Time(), base::Time::Max(),
@@ -2148,6 +2144,30 @@
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS, false);
 }
 
+TEST_F(ChromeBrowsingDataRemoverDelegateTest,
+       RemoveCompromisedCredentialsByTimeOnly_WithAccountStore) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      password_manager::features::kEnablePasswordsAccountStorage);
+
+  RemovePasswordsTester tester(GetProfile());
+  base::RepeatingCallback<bool(const GURL&)> empty_filter;
+
+  EXPECT_CALL(
+      *tester.profile_store(),
+      RemoveCompromisedCredentialsByUrlAndTimeImpl(
+          ProbablySameFilter(empty_filter), base::Time(), base::Time::Max()));
+
+  EXPECT_CALL(
+      *tester.account_store(),
+      RemoveCompromisedCredentialsByUrlAndTimeImpl(
+          ProbablySameFilter(empty_filter), base::Time(), base::Time::Max()));
+
+  BlockUntilBrowsingDataRemoved(
+      base::Time(), base::Time::Max(),
+      ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS, false);
+}
+
 // TODO(crbug.com/589586): Disabled, since history is not yet marked as
 // a filterable datatype.
 TEST_F(ChromeBrowsingDataRemoverDelegateTest,
@@ -3111,11 +3131,12 @@
 #if defined(OS_ANDROID)
 TEST_F(ChromeBrowsingDataRemoverDelegateTest, WipeOriginVerifierData) {
   int before =
-    customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting();
+      customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting();
   BlockUntilBrowsingDataRemoved(
       base::Time(), base::Time::Max(),
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, false);
-  EXPECT_EQ(before + 1,
+  EXPECT_EQ(
+      before + 1,
       customtabs::OriginVerifier::GetClearBrowsingDataCallCountForTesting());
 }
 #endif  // defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index bac93a6..cc1fe302 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2818,12 +2818,16 @@
 
   if (!is_official_build) {
     deps += [
-      "//chromeos/components/sample_system_web_app_ui:sample_system_web_app_ui",
+      "//chromeos/components/sample_system_web_app_ui",
+      "//chromeos/components/telemetry_extension_ui",
       "//chromeos/resources:sample_system_web_app_resources_grit",
+      "//chromeos/resources:telemetry_extension_resources",
     ]
     sources += [
       "web_applications/sample_system_web_app_info.cc",
       "web_applications/sample_system_web_app_info.h",
+      "web_applications/telemetry_extension_web_app_info.cc",
+      "web_applications/telemetry_extension_web_app_info.h",
     ]
   }
 
diff --git a/chrome/browser/chromeos/crosapi/browser_manager.cc b/chrome/browser/chromeos/crosapi/browser_manager.cc
index 5422ea5..711aed4 100644
--- a/chrome/browser/chromeos/crosapi/browser_manager.cc
+++ b/chrome/browser/chromeos/crosapi/browser_manager.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/chromeos/crosapi/browser_manager.h"
 
+#include <fcntl.h>
+#include <unistd.h>
+
 #include <string>
 #include <utility>
 #include <vector>
@@ -15,6 +18,7 @@
 #include "base/logging.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
 #include "base/process/process_handle.h"
 #include "base/strings/string_number_conversions.h"
@@ -52,6 +56,29 @@
   return browser_util::GetUserDataDir().Append("lacros.log");
 }
 
+base::ScopedFD CreateLogFile() {
+  base::FilePath::StringType log_path = LacrosLogPath().value();
+
+  // Delete old log file if exists.
+  if (unlink(log_path.c_str()) != 0) {
+    if (errno != ENOENT) {
+      // unlink() failed for reason other than the file not existing.
+      PLOG(ERROR) << "Failed to unlink the log file " << log_path;
+      return base::ScopedFD();
+    }
+  }
+
+  int fd =
+      HANDLE_EINTR(open(log_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, 644));
+
+  if (fd < 0) {
+    PLOG(ERROR) << "Failed to get file descriptor for " << log_path;
+    return base::ScopedFD();
+  }
+
+  return base::ScopedFD(fd);
+}
+
 std::string GetXdgRuntimeDir() {
   // If ash-chrome was given an environment variable, use it.
   std::unique_ptr<base::Environment> env = base::Environment::Create();
@@ -146,11 +173,14 @@
     return;
   }
 
+  if (state_ == State::CREATING_LOG_FILE) {
+    LOG(WARNING) << "lacros-chrome is in the process of launching";
+    return;
+  }
+
   if (state_ == State::STOPPED) {
     // If lacros-chrome is not running, launch it.
-    bool succeeded = Start();
-    LOG_IF(ERROR, !succeeded)
-        << "lacros-chrome failed to launch. Cannot open a window";
+    Start();
     return;
   }
 
@@ -158,10 +188,21 @@
   lacros_chrome_service_->NewWindow(base::DoNothing());
 }
 
-bool BrowserManager::Start() {
+void BrowserManager::Start() {
   DCHECK_EQ(state_, State::STOPPED);
   DCHECK(!lacros_path_.empty());
 
+  state_ = State::CREATING_LOG_FILE;
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, base::BindOnce(&CreateLogFile),
+      base::BindOnce(&BrowserManager::StartWithLogFile,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void BrowserManager::StartWithLogFile(base::ScopedFD logfd) {
+  DCHECK_EQ(state_, State::CREATING_LOG_FILE);
+
   std::string chrome_path = lacros_path_.MaybeAsASCII() + "/chrome";
   LOG(WARNING) << "Launching lacros-chrome at " << chrome_path;
 
@@ -210,9 +251,17 @@
     argv.push_back(flag);
   }
 
-  // Always enable logging.
-  argv.push_back("--enable-logging");
-  argv.push_back("--log-file=" + LacrosLogPath().value());
+  // If logfd is valid, enable logging and redirect stdout/stderr to logfd.
+  if (logfd.is_valid()) {
+    // The next flag will make chrome log only via stderr. See
+    // DetermineLoggingDestination in logging_chrome.cc.
+    argv.push_back("--enable-logging=stderr");
+
+    // These options will assign stdout/stderr fds to logfd in the fd table of
+    // the new process.
+    options.fds_to_remap.push_back(std::make_pair(logfd.get(), STDOUT_FILENO));
+    options.fds_to_remap.push_back(std::make_pair(logfd.get(), STDERR_FILENO));
+  }
 
   // Set up Mojo channel.
   base::CommandLine command_line(argv);
@@ -243,7 +292,8 @@
   lacros_process_ = base::LaunchProcess(command_line, options);
   if (!lacros_process_.IsValid()) {
     LOG(ERROR) << "Failed to launch lacros-chrome";
-    return false;
+    state_ = State::STOPPED;
+    return;
   }
   state_ = State::STARTING;
   LOG(WARNING) << "Launched lacros-chrome with pid " << lacros_process_.Pid();
@@ -253,7 +303,6 @@
   mojo::OutgoingInvitation::Send(std::move(invitation),
                                  lacros_process_.Handle(),
                                  channel.TakeLocalEndpoint());
-  return true;
 }
 
 void BrowserManager::OnAshChromeServiceReceiverReceived(
diff --git a/chrome/browser/chromeos/crosapi/browser_manager.h b/chrome/browser/chromeos/crosapi/browser_manager.h
index 5b45a96..72fb310 100644
--- a/chrome/browser/chromeos/crosapi/browser_manager.h
+++ b/chrome/browser/chromeos/crosapi/browser_manager.h
@@ -52,10 +52,11 @@
   void SetLoadCompleteCallback(LoadCompleteCallback callback);
 
   // Opens the browser window in lacros-chrome.
-  // If lacros-chrome is not yet launched, it triggers to launch.
-  // This needs to be called after loading. The condition can be checked
-  // IsReady(), and if not yet, SetLoadCompletionCallback can be used
-  // to wait for the loading.
+  // If lacros-chrome is not yet launched, it triggers to launch. If this is
+  // called again during the setup phase of the launch process, it will be
+  // ignored. This needs to be called after loading. The condition can be
+  // checked IsReady(), and if not yet, SetLoadCompletionCallback can be used to
+  // wait for the loading.
   // TODO(crbug.com/1101676): Notify callers the result of opening window
   // request. Because of asynchronous operations crossing processes,
   // there's no guarantee that the opening window request succeeds.
@@ -83,6 +84,9 @@
     // Lacros-chrome is loaded and ready for launching.
     STOPPED,
 
+    // Lacros-chrome is creating a new log file to log to.
+    CREATING_LOG_FILE,
+
     // Lacros-chrome is launching.
     STARTING,
 
@@ -94,10 +98,12 @@
     TERMINATING,
   };
 
-  // Starts the lacros-chrome process. Returns whether the subprocess is
-  // created. Note that the subprocess may be crashed immediately, even if this
-  // returns true. This can be called only in STOPPED state.
-  bool Start();
+  // Posts CreateLogFile() and StartWithLogFile() to the thread pooll.
+  void Start();
+
+  // Starts the lacros-chrome process and redirects stdout/err to file pointed
+  // by logfd.
+  void StartWithLogFile(base::ScopedFD logfd);
 
   // Called when PendingReceiver of AshChromeService is passed from
   // lacros-chrome.
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc
index 4acdd72..0f0766b 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.cc
+++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -76,8 +76,8 @@
     extensions::api::input_method_private::SetAutocorrectRange;
 namespace SetSelectionRange =
     extensions::api::input_method_private::SetSelectionRange;
-namespace OnSettingsChanged =
-    extensions::api::input_method_private::OnSettingsChanged;
+namespace OnInputMethodOptionsChanged =
+    extensions::api::input_method_private::OnInputMethodOptionsChanged;
 
 using chromeos::InputMethodEngineBase;
 
@@ -392,11 +392,11 @@
   // The router will only send the event to extensions that are listening.
   extensions::EventRouter* router =
       extensions::EventRouter::Get(browser_context());
-  if (router->HasEventListener(OnSettingsChanged::kEventName)) {
+  if (router->HasEventListener(OnInputMethodOptionsChanged::kEventName)) {
     auto event = std::make_unique<extensions::Event>(
-        extensions::events::INPUT_METHOD_PRIVATE_ON_SETTINGS_CHANGED,
-        OnSettingsChanged::kEventName,
-        OnSettingsChanged::Create(params->engine_id, params->settings),
+        extensions::events::INPUT_IME_ON_INPUT_METHOD_OPTIONS_CHANGED,
+        OnInputMethodOptionsChanged::kEventName,
+        OnInputMethodOptionsChanged::Create(params->engine_id),
         browser_context());
     router->BroadcastEvent(std::move(event));
   }
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
index cedbaed..11993bc2 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
 #include "chrome/browser/chromeos/web_applications/default_web_app_ids.h"
+#include "chrome/browser/chromeos/web_applications/test/profile_test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/system_web_app_manager.h"
@@ -99,7 +100,8 @@
       profile, "extensions/api_test/file_browser/app_file_handler");
 }
 
-class FileTasksBrowserTestBase : public InProcessBrowserTest {
+class FileTasksBrowserTestBase
+    : public TestProfileTypeMixin<InProcessBrowserTest> {
  public:
   void SetUpOnMainThread() override {
     test::AddDefaultComponentExtensionsOnMainThread(browser()->profile());
@@ -217,7 +219,7 @@
 }  // namespace
 
 // Test file extensions correspond to mime types where expected.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTest, ExtensionToMimeMapping) {
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTest, ExtensionToMimeMapping) {
   constexpr struct {
     const char* file_extension;
     bool has_mime = true;
@@ -287,7 +289,7 @@
 // resolution mechanism is "sort by extension ID", which has the desired result.
 // If desires change, we'll need to update ChooseAndSetDefaultTask() with some
 // additional logic.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTest, DefaultHandlerChangeDetector) {
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTest, DefaultHandlerChangeDetector) {
   //  With the Media App disabled, all images should be handled by Gallery.
   std::vector<Expectation> expectations = {
       // Images.
@@ -303,7 +305,7 @@
 
 // Spot test the default handlers for selections that include multiple different
 // file types. Only tests combinations of interest to the Media App.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTest, MultiSelectDefaultHandler) {
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTest, MultiSelectDefaultHandler) {
   std::vector<Expectation> expectations = {
       {"jpg/gif", kGalleryAppId},
       {"jpg/mp4", kGalleryAppId},
@@ -313,7 +315,7 @@
 }
 
 // Tests the default handlers with the Media App installed.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTestWithMediaApp,
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTestWithMediaApp,
                        DefaultHandlerChangeDetector) {
   // With the Media App enabled, images should be handled by it by default (but
   // video, which it also handles should be unchanged).
@@ -331,7 +333,7 @@
 
 // Spot test the default handlers for selections that include multiple different
 // file types with the Media App installed.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTestWithMediaApp,
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTestWithMediaApp,
                        MultiSelectDefaultHandler) {
   std::vector<Expectation> expectations = {
       {"jpg/gif", kMediaAppId},
@@ -350,27 +352,56 @@
 
 // Sanity check: the tiff-specific file handler is preferred when MediaApp is
 // not enabled.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTest, InstalledAppsAreImplicitDefaults) {
-  auto extension = InstallTiffHandlerChromeApp(browser()->profile());
-  TestExpectationsAgainstDefaultTasks({{"tiff", extension->id().c_str()}});
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTest, InstalledAppsAreImplicitDefaults) {
+  if (GetParam() == TestProfileType::kRegular) {
+    auto extension = InstallTiffHandlerChromeApp(browser()->profile());
+    TestExpectationsAgainstDefaultTasks({{"tiff", extension->id().c_str()}});
+  } else if (GetParam() == TestProfileType::kGuest) {
+    // The extension can't be installed in guest mode. (FATAL check under
+    // ExtensionService::AddNewOrUpdatedExtension()). There should be no tiff
+    // handler.
+    TestExpectationsAgainstDefaultTasks({{"tiff", nullptr}});
+  } else {
+    // The extension installs in incognito, but doesn't register a file handler.
+    // So, also no tiff handler.
+    InstallTiffHandlerChromeApp(browser()->profile());
+    TestExpectationsAgainstDefaultTasks({{"tiff", nullptr}});
+  }
 }
 
 // If the media app is enabled, it will be preferred over a chrome app with a
 // specific extension, unless that app is set default via prefs.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTestWithMediaApp,
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTestWithMediaApp,
                        MediaAppPreferredOverChromeApps) {
+  if (GetParam() == TestProfileType::kGuest) {
+    // The provided file system can't install in guest mode. Just check that
+    // MediaApp handles tiff.
+    TestExpectationsAgainstDefaultTasks({{"tiff", kMediaAppId}});
+    return;
+  }
   Profile* profile = browser()->profile();
   auto extension = InstallTiffHandlerChromeApp(profile);
   TestExpectationsAgainstDefaultTasks({{"tiff", kMediaAppId}});
 
   UpdateDefaultTask(profile->GetPrefs(), extension->id() + "|app|tiffAction",
                     {"tiff"}, {"image/tiff"});
-  TestExpectationsAgainstDefaultTasks({{"tiff", extension->id().c_str()}});
+  if (GetParam() == TestProfileType::kIncognito) {
+    // In incognito, the provided file system can exist, but the file handler
+    // preference can't be changed.
+    TestExpectationsAgainstDefaultTasks({{"tiff", kMediaAppId}});
+  } else {
+    TestExpectationsAgainstDefaultTasks({{"tiff", extension->id().c_str()}});
+  }
 }
 
 // Test expectations for files coming from provided file systems.
-IN_PROC_BROWSER_TEST_F(FileTasksBrowserTestWithMediaApp,
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTestWithMediaApp,
                        ProvidedFileSystemFileSource) {
+  if (GetParam() == TestProfileType::kGuest) {
+    // Provided file systems don't exist in guest. This test seems to work OK in
+    // incognito mode though.
+    return;
+  }
   // The current test expectation: a GIF file in the provided file system called
   // "readwrite.gif" should open with the MediaApp.
   const char kTestFile[] = "readwrite.gif";
@@ -415,5 +446,19 @@
   EXPECT_EQ(remaining_expectations, 0);
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         FileTasksBrowserTest,
+                         ::testing::Values(TestProfileType::kRegular,
+                                           TestProfileType::kIncognito,
+                                           TestProfileType::kGuest),
+                         TestProfileTypeToString);
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         FileTasksBrowserTestWithMediaApp,
+                         ::testing::Values(TestProfileType::kRegular,
+                                           TestProfileType::kIncognito,
+                                           TestProfileType::kGuest),
+                         TestProfileTypeToString);
+
 }  // namespace file_tasks
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl.cc b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl.cc
index 058a0e79..263866d1 100644
--- a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl.cc
+++ b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl.cc
@@ -257,12 +257,6 @@
                             result);
 }
 
-void RecordUmaResponseSize(unsigned long responseSize) {
-  UMA_HISTOGRAM_COUNTS_1M(
-      "OOBE.RecommendApps.Fetcher.ResponseSize",
-      static_cast<base::HistogramBase::Sample>(responseSize));
-}
-
 }  // namespace
 
 RecommendAppsFetcherImpl::RecommendAppsFetcherImpl(
@@ -488,7 +482,6 @@
   //
   // The response starts with a prefix ")]}'". This needs to be removed before
   // further parsing.
-  RecordUmaResponseSize(response_body->size());
   constexpr base::StringPiece json_xss_prevention_prefix(")]}'");
   base::StringPiece response_body_json(*response_body);
   if (base::StartsWith(response_body_json, json_xss_prevention_prefix))
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen.cc b/chrome/browser/chromeos/login/ui/user_adding_screen.cc
index f0ffeac1..1393c82 100644
--- a/chrome/browser/chromeos/login/ui/user_adding_screen.cc
+++ b/chrome/browser/chromeos/login/ui/user_adding_screen.cc
@@ -6,13 +6,14 @@
 
 #include "base/bind.h"
 #include "base/memory/singleton.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_mojo.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
 #include "chrome/browser/chromeos/login/ui/user_adding_screen_input_methods_controller.h"
+#include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/session_manager/core/session_manager.h"
@@ -30,20 +31,20 @@
   void Cancel() override;
   bool IsRunning() override;
 
-  void AddObserver(Observer* observer) override;
-  void RemoveObserver(Observer* observer) override;
+  void AddObserver(UserAddingScreen::Observer* observer) override;
+  void RemoveObserver(UserAddingScreen::Observer* observer) override;
 
   static UserAddingScreenImpl* GetInstance();
 
  private:
   friend struct base::DefaultSingletonTraits<UserAddingScreenImpl>;
-  class LoadTimeReporter : public OobeUI::Observer {
+  class LoadTimeReporterWebUi : public OobeUI::Observer {
    public:
-    LoadTimeReporter() : start_time_(base::TimeTicks::Now()) {}
-    LoadTimeReporter(const LoadTimeReporter&) = delete;
-    LoadTimeReporter& operator=(const LoadTimeReporter&) = delete;
+    LoadTimeReporterWebUi() : start_time_(base::TimeTicks::Now()) {}
+    LoadTimeReporterWebUi(const LoadTimeReporterWebUi&) = delete;
+    LoadTimeReporterWebUi& operator=(const LoadTimeReporterWebUi&) = delete;
 
-    ~LoadTimeReporter() override {
+    ~LoadTimeReporterWebUi() override {
       if (remove_observer_)
         oobe_ui_->RemoveObserver(this);
       remove_observer_ = false;
@@ -62,26 +63,53 @@
       if (new_screen != OobeScreen::SCREEN_ACCOUNT_PICKER)
         return;
       const base::TimeDelta load_time = base::TimeTicks::Now() - start_time_;
-      UMA_HISTOGRAM_TIMES("ChromeOS.UserAddingScreen.LoadTime", load_time);
+      UmaHistogramTimes("ChromeOS.UserAddingScreen.LoadTime", load_time);
       remove_observer_ = false;
       oobe_ui_->RemoveObserver(this);
     }
     void OnDestroyingOobeUI() override { remove_observer_ = false; }
 
-   private:
     const base::TimeTicks start_time_;
     OobeUI* oobe_ui_ = nullptr;
     bool remove_observer_ = false;
   };
 
-  std::unique_ptr<LoadTimeReporter> reporter_;
+  class LoadTimeReporterMojo : public LoginScreenShownObserver {
+   public:
+    LoadTimeReporterMojo() : start_time_(base::TimeTicks::Now()) {
+      LoginScreenClient::Get()->AddLoginScreenShownObserver(this);
+    }
+    LoadTimeReporterMojo(const LoadTimeReporterMojo&) = delete;
+    LoadTimeReporterMojo& operator=(const LoadTimeReporterMojo&) = delete;
+
+    ~LoadTimeReporterMojo() override {
+      // In tests, LoginScreenClient's instance may be destroyed before
+      // LoadTimeReporterMojo's destructor is called.
+      if (LoginScreenClient::HasInstance())
+        LoginScreenClient::Get()->RemoveLoginScreenShownObserver(this);
+    }
+
+    // LoginScreenShownObserver:
+    void OnLoginScreenShown() override {
+      const base::TimeDelta load_time = base::TimeTicks::Now() - start_time_;
+      UmaHistogramTimes("ChromeOS.UserAddingScreen.LoadTimeViewsBased",
+                        load_time);
+      LoginScreenClient::Get()->RemoveLoginScreenShownObserver(this);
+    }
+
+   private:
+    const base::TimeTicks start_time_;
+  };
+
+  std::unique_ptr<LoadTimeReporterWebUi> reporter_web_ui_;
+  std::unique_ptr<LoadTimeReporterMojo> reporter_mojo_;
 
   void OnDisplayHostCompletion();
 
   UserAddingScreenImpl();
   ~UserAddingScreenImpl() override;
 
-  base::ObserverList<Observer>::Unchecked observers_;
+  base::ObserverList<UserAddingScreen::Observer>::Unchecked observers_;
   LoginDisplayHost* display_host_;
 
   UserAddingScreenInputMethodsController im_controller_;
@@ -94,16 +122,18 @@
   if (viewBasedEnabled) {
     display_host_ = new chromeos::LoginDisplayHostMojo(
         LoginDisplayHostMojo::DisplayedScreen::USER_ADDING_SCREEN);
+    reporter_mojo_ = std::make_unique<LoadTimeReporterMojo>();
   } else {
     display_host_ = new chromeos::LoginDisplayHostWebUI();
-    reporter_ = std::make_unique<LoadTimeReporter>();
+    reporter_web_ui_ = std::make_unique<LoadTimeReporterWebUi>();
   }
   session_manager::SessionManager::Get()->SetSessionState(
       session_manager::SessionState::LOGIN_SECONDARY);
   display_host_->StartUserAdding(base::BindOnce(
       &UserAddingScreenImpl::OnDisplayHostCompletion, base::Unretained(this)));
-  if (!viewBasedEnabled)
-    reporter_->Observe(display_host_->GetOobeUI());
+  if (!viewBasedEnabled) {
+    reporter_web_ui_->Observe(display_host_->GetOobeUI());
+  }
 
   for (auto& observer : observers_)
     observer.OnUserAddingStarted();
@@ -111,7 +141,8 @@
 
 void UserAddingScreenImpl::Cancel() {
   CHECK(IsRunning());
-  reporter_.reset();
+  reporter_web_ui_.reset();
+  reporter_mojo_.reset();
 
   display_host_->CancelUserAdding();
 
@@ -126,11 +157,12 @@
   return display_host_ != NULL;
 }
 
-void UserAddingScreenImpl::AddObserver(Observer* observer) {
+void UserAddingScreenImpl::AddObserver(UserAddingScreen::Observer* observer) {
   observers_.AddObserver(observer);
 }
 
-void UserAddingScreenImpl::RemoveObserver(Observer* observer) {
+void UserAddingScreenImpl::RemoveObserver(
+    UserAddingScreen::Observer* observer) {
   observers_.RemoveObserver(observer);
 }
 
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
index 276a4600..f7c26c9 100644
--- a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/login_screen_client.h"
+#include "chrome/browser/ui/ash/login_screen_shown_observer.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -148,14 +150,32 @@
             users[0].account_id);
 }
 
-class UserAddingScreenWithViewBasedTest : public UserAddingScreenTest {
+class UserAddingScreenWithViewBasedTest : public UserAddingScreenTest,
+                                          public LoginScreenShownObserver {
  public:
   UserAddingScreenWithViewBasedTest() : UserAddingScreenTest() {
     feature_list_.InitWithFeatures(
         {chromeos::features::kViewBasedMultiprofileLogin}, {});
   }
 
+  // LoginScreenShownObserver:
+  void OnLoginScreenShown() override {
+    LoginScreenClient::Get()->RemoveLoginScreenShownObserver(this);
+    login_screen_shown_ = true;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  void WaitUntilLoginScreenShown() {
+    if (login_screen_shown_)
+      return;
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
+  }
+
  private:
+  bool login_screen_shown_ = false;
+  std::unique_ptr<base::RunLoop> run_loop_;
   base::test::ScopedFeatureList feature_list_;
 };
 
@@ -171,7 +191,10 @@
   EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
             session_manager::SessionState::ACTIVE);
 
+  base::HistogramTester histogram_tester;
   UserAddingScreen::Get()->Start();
+  LoginScreenClient::Get()->AddLoginScreenShownObserver(this);
+  WaitUntilLoginScreenShown();
 
   EXPECT_EQ(user_adding_started(), 1);
   EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
@@ -181,6 +204,9 @@
   EXPECT_TRUE(ash::LoginScreenTestApi::ClickCancelButton());
   WaitUntilUserAddingFinishedOrCancelled();
 
+  histogram_tester.ExpectTotalCount(
+      "ChromeOS.UserAddingScreen.LoadTimeViewsBased", 1);
+
   EXPECT_EQ(user_adding_finished(), 1);
   EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
             session_manager::SessionState::ACTIVE);
@@ -238,7 +264,11 @@
 
   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
 
+  base::HistogramTester histogram_tester;
   UserAddingScreen::Get()->Start();
+  LoginScreenClient::Get()->AddLoginScreenShownObserver(this);
+  WaitUntilLoginScreenShown();
+
   EXPECT_EQ(user_adding_started(), 1);
   EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
             session_manager::SessionState::LOGIN_SECONDARY);
@@ -258,6 +288,9 @@
   EXPECT_TRUE(LoginDisplayHost::default_host() == nullptr);
   ASSERT_EQ(user_manager->GetLoggedInUsers().size(), 2u);
 
+  histogram_tester.ExpectTotalCount(
+      "ChromeOS.UserAddingScreen.LoadTimeViewsBased", 1);
+
   EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
             session_manager::SessionState::ACTIVE);
 }
@@ -384,6 +417,9 @@
   const int n = users.size();
   for (int i = 1; i < n; ++i) {
     UserAddingScreen::Get()->Start();
+    LoginScreenClient::Get()->AddLoginScreenShownObserver(this);
+    WaitUntilLoginScreenShown();
+
     EXPECT_EQ(user_adding_started(), i);
     EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
               session_manager::SessionState::LOGIN_SECONDARY);
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 69f583a8..2183e0f 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
+#include "chrome/browser/chromeos/login/test/webview_content_extractor.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -742,29 +743,23 @@
     navigation_observer.WatchExistingWebContents();
     navigation_observer.StartWatchingNewWebContents();
 
-    // TODO(https://crbug.com/830337): Remove the logs if flakiness is gone.
+    // TODO(https://crbug.com/1092562): Remove the logs if flakiness is gone.
     // If you see this after April 2019, please ping the owner of the above bug.
-    LOG(INFO) << "Triggering navigation to " << url.spec() << ".";
     test::OobeJS().Evaluate(base::StringPrintf(
         "%s.src='%s'", test::GetOobeElementPath(webview_path).c_str(),
         url.spec().c_str()));
     navigation_observer.Wait();
     LOG(INFO) << "Navigation done.";
 
-    content::WebContents* main_web_contents = GetLoginUI()->GetWebContents();
-    const std::string webview_id = std::prev(webview_path.end())->as_string();
-    content::WebContents* frame_web_contents =
-        signin::GetAuthFrameWebContents(main_web_contents, webview_id);
-    test::JSChecker frame_js_checker(frame_web_contents);
     const std::string https_reply_content =
-        frame_js_checker.GetString("document.body.textContent");
-    // TODO(https://crbug.com/830337): Remove this is if flakiness does not
+        test::GetWebViewContents(webview_path);
+    // TODO(https://crbug.com/1092562): Remove this is if flakiness does not
     // reproduce.
-    // If you see this after April 2019, please ping the owner of the above bug.
+    // If you see this after October 2020, please ping the above bug.
     if (https_reply_content.empty()) {
       base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1000));
       const std::string https_reply_content_after_sleep =
-          frame_js_checker.GetString("document.body.textContent");
+          test::GetWebViewContents(webview_path);
       if (!https_reply_content_after_sleep.empty())
         LOG(INFO) << "Magic - textContent appeared after sleep.";
     }
diff --git a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
index 6640b65..3164731 100644
--- a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
@@ -20,9 +20,12 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/web_applications/system_web_app_manager.h"
 #include "chrome/browser/web_applications/system_web_app_manager_browsertest.h"
+#include "chrome/common/chrome_switches.h"
 #include "chromeos/components/help_app_ui/url_constants.h"
 #include "chromeos/components/web_applications/test/sandboxed_web_ui_test_base.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "components/user_manager/user_names.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -293,3 +296,33 @@
                           web_app::ProviderType::kWebApps),
         ::testing::Values(web_app::InstallationType::kManifestInstall)),
     web_app::ProviderAndInstallationTypeToString);
+
+class HelpAppGuestSessionIntegrationTest : public HelpAppIntegrationTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(chromeos::switches::kGuestSession);
+    command_line->AppendSwitch(::switches::kIncognito);
+    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "hash");
+    command_line->AppendSwitchASCII(
+        chromeos::switches::kLoginUser,
+        user_manager::GuestAccountId().GetUserEmail());
+  }
+};
+
+// Test that the Help App shortcut doesn't crash in guest mode.
+IN_PROC_BROWSER_TEST_P(HelpAppGuestSessionIntegrationTest, HelpAppShowHelp) {
+  WaitForTestSystemAppInstall();
+  // TODO(carpenterr): Verify the right windows are launched in the chrome
+  // branded and non-chrome branded codepaths.
+  EXPECT_NO_FATAL_FAILURE(
+      chrome::ShowHelp(browser(), chrome::HELP_SOURCE_KEYBOARD));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    HelpAppGuestSessionIntegrationTest,
+    ::testing::Combine(
+        ::testing::Values(web_app::ProviderType::kBookmarkApps,
+                          web_app::ProviderType::kWebApps),
+        ::testing::Values(web_app::InstallationType::kManifestInstall)),
+    web_app::ProviderAndInstallationTypeToString);
diff --git a/chrome/browser/chromeos/web_applications/sample_system_web_app_info.cc b/chrome/browser/chromeos/web_applications/sample_system_web_app_info.cc
index fcdd1d5..ce332ecf 100644
--- a/chrome/browser/chromeos/web_applications/sample_system_web_app_info.cc
+++ b/chrome/browser/chromeos/web_applications/sample_system_web_app_info.cc
@@ -6,15 +6,13 @@
 
 #include <memory>
 
-#include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/web_applications/system_web_app_install_utils.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/common/web_application_info.h"
 #include "chromeos/components/sample_system_web_app_ui/url_constants.h"
 #include "chromeos/grit/chromeos_sample_system_web_app_resources.h"
-#include "services/network/public/mojom/content_security_policy.mojom.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 
 std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForSampleSystemWebApp() {
   std::unique_ptr<WebApplicationInfo> info =
diff --git a/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.cc b/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.cc
new file mode 100644
index 0000000..56a8ed41
--- /dev/null
+++ b/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.cc
@@ -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.
+
+#include "chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/web_applications/system_web_app_install_utils.h"
+#include "chrome/common/web_application_info.h"
+#include "chromeos/components/telemetry_extension_ui/url_constants.h"
+#include "chromeos/grit/chromeos_telemetry_extension_resources.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
+
+std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForTelemetryExtension() {
+  auto info = std::make_unique<WebApplicationInfo>();
+  info->app_url = GURL(chromeos::kChromeUITelemetryExtensionURL);
+  info->scope = GURL(chromeos::kChromeUITelemetryExtensionURL);
+  info->title = base::UTF8ToUTF16("Telemetry Extension");
+  web_app::CreateIconInfoForSystemWebApp(info->app_url, "app_icon_96.png", 96,
+                                         IDR_TELEMETRY_EXTENSION_ICON_96,
+                                         *info);
+  info->theme_color = 0xFF4285F4;
+  info->background_color = 0xFFFFFFFF;
+  info->display_mode = blink::mojom::DisplayMode::kStandalone;
+  info->open_as_window = true;
+
+  return info;
+}
diff --git a/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h b/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h
new file mode 100644
index 0000000..1601503
--- /dev/null
+++ b/chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h
@@ -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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_TELEMETRY_EXTENSION_WEB_APP_INFO_H_
+#define CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_TELEMETRY_EXTENSION_WEB_APP_INFO_H_
+
+#include <memory>
+
+#if defined(OFFICIAL_BUILD)
+#error Telemetry Extension should only be included in unofficial builds.
+#endif
+
+struct WebApplicationInfo;
+
+// Return a WebApplicationInfo used to install the app.
+std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForTelemetryExtension();
+
+#endif  // CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_TELEMETRY_EXTENSION_WEB_APP_INFO_H_
diff --git a/chrome/browser/chromeos/web_applications/test/profile_test_helper.cc b/chrome/browser/chromeos/web_applications/test/profile_test_helper.cc
new file mode 100644
index 0000000..0cf8bb31
--- /dev/null
+++ b/chrome/browser/chromeos/web_applications/test/profile_test_helper.cc
@@ -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.
+
+#include "chrome/browser/chromeos/web_applications/test/profile_test_helper.h"
+
+#include "chromeos/constants/chromeos_switches.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/user_names.h"
+
+std::string TestProfileTypeToString(
+    const ::testing::TestParamInfo<TestProfileType>& info) {
+  switch (info.param) {
+    case TestProfileType::kRegular:
+      return "Regular";
+    case TestProfileType::kIncognito:
+      return "Incognito";
+    case TestProfileType::kGuest:
+      return "Guest";
+  }
+}
+
+void ConfigureCommandLineForGuestMode(base::CommandLine* command_line) {
+  command_line->AppendSwitch(chromeos::switches::kGuestSession);
+  command_line->AppendSwitch(::switches::kIncognito);
+  command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "hash");
+  command_line->AppendSwitchASCII(
+      chromeos::switches::kLoginUser,
+      user_manager::GuestAccountId().GetUserEmail());
+}
diff --git a/chrome/browser/chromeos/web_applications/test/profile_test_helper.h b/chrome/browser/chromeos/web_applications/test/profile_test_helper.h
new file mode 100644
index 0000000..6e2935e
--- /dev/null
+++ b/chrome/browser/chromeos/web_applications/test/profile_test_helper.h
@@ -0,0 +1,61 @@
+// 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_WEB_APPLICATIONS_TEST_PROFILE_TEST_HELPER_H_
+#define CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_TEST_PROFILE_TEST_HELPER_H_
+
+#include <string>
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Profile type to test. Provided to subclasses of TestProfileTypeMixin via
+// GetParam().
+enum class TestProfileType {
+  kRegular,
+  kIncognito,
+  kGuest,
+};
+
+// GTest string formatter for TestProfileType. Appends, e.g. "/Guest" to the end
+// of test names.
+std::string TestProfileTypeToString(
+    const ::testing::TestParamInfo<TestProfileType>& param);
+
+// Adds the necessary flags to |command_line| to start a browser test in guest
+// mode. Should be invoked in SetUpCommandLine(). Any test can call this: it is
+// not coupled to TestProfileTypeMixin.
+void ConfigureCommandLineForGuestMode(base::CommandLine* command_line);
+
+// "Mixin" for configuring a test harness to parameterize on different profile
+// types. To use it, inherit from
+//     : public TestProfileTypeMixin<BaseBrowserTest>
+// rather than BaseBrowserTest (e.g. a descendant of InProcessBrowserTest).
+// Then choose the profile types to test against. E.g.,
+//
+// INSTANTIATE_TEST_SUITE_P(All,
+//                          MySubclassOfTestProfileTypeMixin,
+//                          ::testing::Values(TestProfileType::kRegular,
+//                                            TestProfileType::kIncognito,
+//                                            TestProfileType::kGuest),
+//                          TestProfileTypeToString);
+//
+// Remember to use IN_PROC_BROWSER_TEST_P (not _F).
+template <class T>
+class TestProfileTypeMixin
+    : public T,
+      public ::testing::WithParamInterface<TestProfileType> {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    if (GetParam() == TestProfileType::kGuest) {
+      ConfigureCommandLineForGuestMode(command_line);
+    } else if (GetParam() == TestProfileType::kIncognito) {
+      command_line->AppendSwitch(::switches::kIncognito);
+    }
+    T::SetUpCommandLine(command_line);
+  }
+};
+
+#endif  // CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_TEST_PROFILE_TEST_HELPER_H_
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 1835d03..a042f4f 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -102,6 +102,8 @@
 static const char kDevToolsActionTakenHistogram[] = "DevTools.ActionTaken";
 static const char kDevToolsPanelShownHistogram[] = "DevTools.PanelShown";
 static const char kDevToolsPanelClosedHistogram[] = "DevTools.PanelClosed";
+static const char kDevToolsSidebarPaneShownHistogram[] =
+    "DevTools.SidebarPaneShown";
 static const char kDevToolsKeyboardShortcutFiredHistogram[] =
     "DevTools.KeyboardShortcutFired";
 static const char kDevToolsIssuesPanelOpenedFromHistogram[] =
@@ -1271,6 +1273,8 @@
     base::UmaHistogramExactLinear(name, sample, boundary_value);
   else if (name == kDevToolsPanelClosedHistogram)
     base::UmaHistogramExactLinear(name, sample, boundary_value);
+  else if (name == kDevToolsSidebarPaneShownHistogram)
+    base::UmaHistogramExactLinear(name, sample, boundary_value);
   else if (name == kDevToolsKeyboardShortcutFiredHistogram)
     base::UmaHistogramExactLinear(name, sample, boundary_value);
   else if (name == kDevToolsIssuesPanelOpenedFromHistogram)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 11690fb..1a4cbb6 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2629,7 +2629,7 @@
   {
     "name": "fullscreen-controller-browser-scoped",
     "owners": [ "thegreenfrog", "bling-flags" ],
-    "expiry_milestone": 85
+    "expiry_milestone": 87
   },
   {
     "name": "fullscreen-viewport-adjustment-experiment",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 87dce039..a673cf7 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -299,12 +299,6 @@
 const char kAutofillPruneSuggestionsDescription[] =
     "Further limits the number of suggestions in the Autofill dropdown.";
 
-const char kAutofillRejectCompanyBirthyearName[] =
-    "Autofill Rejects Invalid Company Names";
-const char kAutofillRejectCompanyBirthyearDescription[] =
-    "Autofill rejects using non-verified company names that are in the "
-    "format of a birthyear.";
-
 const char kAutofillRestrictUnownedFieldsToFormlessCheckoutName[] =
     "Restrict formless form extraction";
 const char kAutofillRestrictUnownedFieldsToFormlessCheckoutDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e464d1f..993e415f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -179,9 +179,6 @@
 extern const char kAutofillProfileServerValidationName[];
 extern const char kAutofillProfileServerValidationDescription[];
 
-extern const char kAutofillRejectCompanyBirthyearName[];
-extern const char kAutofillRejectCompanyBirthyearDescription[];
-
 extern const char kAutofillPruneSuggestionsName[];
 extern const char kAutofillPruneSuggestionsDescription[];
 
diff --git a/chrome/browser/nearby_sharing/BUILD.gn b/chrome/browser/nearby_sharing/BUILD.gn
index 571f802..789b6d24 100644
--- a/chrome/browser/nearby_sharing/BUILD.gn
+++ b/chrome/browser/nearby_sharing/BUILD.gn
@@ -18,6 +18,7 @@
     "//base",
     "//chrome/services/sharing/public/mojom",
     "//chrome/services/sharing/public/mojom:nearby_share_target_types",
+    "//net",
     "//url",
   ]
 }
diff --git a/chrome/browser/nearby_sharing/attachment.cc b/chrome/browser/nearby_sharing/attachment.cc
index e75814e..bfced4d9 100644
--- a/chrome/browser/nearby_sharing/attachment.cc
+++ b/chrome/browser/nearby_sharing/attachment.cc
@@ -23,6 +23,10 @@
 
 Attachment::Attachment(const Attachment&) = default;
 
+Attachment::Attachment(Attachment&&) = default;
+
 Attachment& Attachment::operator=(const Attachment&) = default;
 
+Attachment& Attachment::operator=(Attachment&&) = default;
+
 Attachment::~Attachment() = default;
diff --git a/chrome/browser/nearby_sharing/attachment.h b/chrome/browser/nearby_sharing/attachment.h
index 68ff2889..f0264d3 100644
--- a/chrome/browser/nearby_sharing/attachment.h
+++ b/chrome/browser/nearby_sharing/attachment.h
@@ -7,6 +7,8 @@
 
 #include <stdint.h>
 
+struct ShareTarget;
+
 // A single attachment to be sent by / received from a ShareTarget, can be
 // either a file or text.
 class Attachment {
@@ -16,7 +18,9 @@
   Attachment(Family family, int64_t size);
   Attachment(int64_t id, Family family, int64_t size);
   Attachment(const Attachment&);
+  Attachment(Attachment&&);
   Attachment& operator=(const Attachment&);
+  Attachment& operator=(Attachment&&);
   virtual ~Attachment();
 
   int64_t id() const { return id_; }
@@ -24,6 +28,8 @@
   int64_t size() const { return size_; }
   void set_size(int64_t size) { size_ = size; }
 
+  virtual void MoveToShareTarget(ShareTarget& share_target) = 0;
+
  private:
   int64_t id_;
   Family family_;
diff --git a/chrome/browser/nearby_sharing/file_attachment.cc b/chrome/browser/nearby_sharing/file_attachment.cc
index 996a52c..bf0544bbf 100644
--- a/chrome/browser/nearby_sharing/file_attachment.cc
+++ b/chrome/browser/nearby_sharing/file_attachment.cc
@@ -2,33 +2,68 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <utility>
-
 #include "chrome/browser/nearby_sharing/file_attachment.h"
 
-FileAttachment::FileAttachment(std::string file_name,
-                               Type type,
-                               int64_t size,
-                               base::Optional<base::FilePath> file_path,
-                               std::string mime_type)
-    : Attachment(Attachment::Family::kFile, size),
-      file_name_(std::move(file_name)),
-      type_(type),
-      file_path_(std::move(file_path)),
-      mime_type_(std::move(mime_type)) {}
+#include <utility>
+
+#include "base/strings/string_util.h"
+#include "chrome/browser/nearby_sharing/share_target.h"
+#include "net/base/mime_util.h"
+
+namespace {
+
+FileAttachment::Type FileAttachmentTypeFromMimeType(
+    const std::string& mime_type) {
+  if (base::StartsWith(mime_type, "image/"))
+    return FileAttachment::Type::kImage;
+
+  if (base::StartsWith(mime_type, "video/"))
+    return FileAttachment::Type::kVideo;
+
+  if (base::StartsWith(mime_type, "audio/"))
+    return FileAttachment::Type::kAudio;
+
+  return FileAttachment::Type::kUnknown;
+}
+
+std::string MimeTypeFromPath(const base::FilePath& path) {
+  std::string mime_type = "application/octet-stream";
+  base::FilePath::StringType ext = path.Extension();
+  if (!ext.empty())
+    net::GetWellKnownMimeTypeFromExtension(ext.substr(1), &mime_type);
+
+  return mime_type;
+}
+
+}  // namespace
+
+FileAttachment::FileAttachment(base::FilePath file_path)
+    : Attachment(Attachment::Family::kFile, /*size=*/0),
+      file_name_(file_path.BaseName().AsUTF8Unsafe()),
+      mime_type_(MimeTypeFromPath(file_path)),
+      type_(FileAttachmentTypeFromMimeType(mime_type_)),
+      file_path_(std::move(file_path)) {}
 
 FileAttachment::FileAttachment(int64_t id,
-                               std::string file_name,
-                               Type type,
                                int64_t size,
-                               std::string mime_type)
+                               std::string file_name,
+                               std::string mime_type,
+                               Type type)
     : Attachment(id, Attachment::Family::kFile, size),
       file_name_(std::move(file_name)),
-      type_(type),
-      mime_type_(std::move(mime_type)) {}
+      mime_type_(std::move(mime_type)),
+      type_(type) {}
 
 FileAttachment::FileAttachment(const FileAttachment&) = default;
 
+FileAttachment::FileAttachment(FileAttachment&&) = default;
+
 FileAttachment& FileAttachment::operator=(const FileAttachment&) = default;
 
+FileAttachment& FileAttachment::operator=(FileAttachment&&) = default;
+
 FileAttachment::~FileAttachment() = default;
+
+void FileAttachment::MoveToShareTarget(ShareTarget& share_target) {
+  share_target.file_attachments.push_back(std::move(*this));
+}
diff --git a/chrome/browser/nearby_sharing/file_attachment.h b/chrome/browser/nearby_sharing/file_attachment.h
index 8e18c84..3c3d557 100644
--- a/chrome/browser/nearby_sharing/file_attachment.h
+++ b/chrome/browser/nearby_sharing/file_attachment.h
@@ -18,30 +18,31 @@
  public:
   using Type = sharing::mojom::FileMetadata::Type;
 
-  FileAttachment(std::string file_name,
-                 Type type,
-                 int64_t size,
-                 base::Optional<base::FilePath> file_path,
-                 std::string mime_type);
+  explicit FileAttachment(base::FilePath file_path);
   FileAttachment(int64_t id,
-                 std::string file_name,
-                 Type type,
                  int64_t size,
-                 std::string mime_type);
+                 std::string file_name,
+                 std::string mime_type,
+                 Type type);
   FileAttachment(const FileAttachment&);
+  FileAttachment(FileAttachment&&);
   FileAttachment& operator=(const FileAttachment&);
+  FileAttachment& operator=(FileAttachment&&);
   ~FileAttachment() override;
 
   const std::string& file_name() const { return file_name_; }
+  const std::string& mime_type() const { return mime_type_; }
   Type type() const { return type_; }
   const base::Optional<base::FilePath>& file_path() const { return file_path_; }
-  const std::string& mime_type() const { return mime_type_; }
+
+  // Attachment:
+  void MoveToShareTarget(ShareTarget& share_target) override;
 
  private:
   std::string file_name_;
+  std::string mime_type_;
   Type type_;
   base::Optional<base::FilePath> file_path_;
-  std::string mime_type_;
 };
 
 #endif  // CHROME_BROWSER_NEARBY_SHARING_FILE_ATTACHMENT_H_
diff --git a/chrome/browser/nearby_sharing/mock_nearby_sharing_service.h b/chrome/browser/nearby_sharing/mock_nearby_sharing_service.h
index 4c19f85c..34ed05d 100644
--- a/chrome/browser/nearby_sharing/mock_nearby_sharing_service.h
+++ b/chrome/browser/nearby_sharing/mock_nearby_sharing_service.h
@@ -33,12 +33,8 @@
               (TransferUpdateCallback*),
               (override));
   MOCK_METHOD(StatusCodes,
-              SendText,
-              (const ShareTarget&, std::string),
-              (override));
-  MOCK_METHOD(StatusCodes,
-              SendFiles,
-              (const ShareTarget&, const std::vector<base::FilePath>&),
+              SendAttachments,
+              (const ShareTarget&, std::vector<std::unique_ptr<Attachment>>),
               (override));
   MOCK_METHOD(void,
               Accept,
diff --git a/chrome/browser/nearby_sharing/nearby_confirmation_manager.cc b/chrome/browser/nearby_sharing/nearby_confirmation_manager.cc
index 8c036e54..0a4bc36f 100644
--- a/chrome/browser/nearby_sharing/nearby_confirmation_manager.cc
+++ b/chrome/browser/nearby_sharing/nearby_confirmation_manager.cc
@@ -43,3 +43,9 @@
   nearby_service_->Reject(share_target_,
                           ToStatusCodesCallback(std::move(callback)));
 }
+
+void NearbyConfirmationManager::Cancel(CancelCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  nearby_service_->Cancel(share_target_,
+                          ToStatusCodesCallback(std::move(callback)));
+}
diff --git a/chrome/browser/nearby_sharing/nearby_confirmation_manager.h b/chrome/browser/nearby_sharing/nearby_confirmation_manager.h
index f823d43..ac447b7 100644
--- a/chrome/browser/nearby_sharing/nearby_confirmation_manager.h
+++ b/chrome/browser/nearby_sharing/nearby_confirmation_manager.h
@@ -25,6 +25,7 @@
   // nearby_share::mojom::ConfirmationManager:
   void Accept(AcceptCallback callback) override;
   void Reject(RejectCallback callback) override;
+  void Cancel(CancelCallback callback) override;
 
  private:
   NearbySharingService* nearby_service_;
diff --git a/chrome/browser/nearby_sharing/nearby_confirmation_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_confirmation_manager_unittest.cc
index 4473161..8fb1336 100644
--- a/chrome/browser/nearby_sharing/nearby_confirmation_manager_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_confirmation_manager_unittest.cc
@@ -88,3 +88,31 @@
 
   manager().Reject(callback.Get());
 }
+
+TEST_F(NearbyConfirmationManagerTest, Cancel_Success) {
+  EXPECT_CALL(sharing_service(), Cancel(testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&](const ShareTarget& target,
+              NearbySharingService::StatusCodesCallback callback) {
+            EXPECT_EQ(share_target().id, target.id);
+            std::move(callback).Run(NearbySharingService::StatusCodes::kOk);
+          }));
+  base::MockCallback<NearbyConfirmationManager::CancelCallback> callback;
+  EXPECT_CALL(callback, Run(testing::Eq(true)));
+
+  manager().Cancel(callback.Get());
+}
+
+TEST_F(NearbyConfirmationManagerTest, Cancel_Error) {
+  EXPECT_CALL(sharing_service(), Cancel(testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [&](const ShareTarget& target,
+              NearbySharingService::StatusCodesCallback callback) {
+            EXPECT_EQ(share_target().id, target.id);
+            std::move(callback).Run(NearbySharingService::StatusCodes::kError);
+          }));
+  base::MockCallback<NearbyConfirmationManager::CancelCallback> callback;
+  EXPECT_CALL(callback, Run(testing::Eq(false)));
+
+  manager().Cancel(callback.Get());
+}
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.cc b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
index ed9d6545..521a576 100644
--- a/chrome/browser/nearby_sharing/nearby_notification_manager.cc
+++ b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
@@ -4,20 +4,30 @@
 
 #include "chrome/browser/nearby_sharing/nearby_notification_manager.h"
 
+#include "base/files/file_util.h"
 #include "base/notreached.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/image_decoder/image_decoder.h"
 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
 #include "chrome/browser/nearby_sharing/logging/logging.h"
 #include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
 #include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "ui/base/clipboard/clipboard_buffer.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_types.h"
@@ -253,6 +263,171 @@
   bool has_accept_button_;
 };
 
+class ReceivedImageDecoder : public ImageDecoder::ImageRequest {
+ public:
+  explicit ReceivedImageDecoder(
+      base::OnceCallback<
+          void(NearbyNotificationManager::SuccessNotificationAction)>
+          testing_callback)
+      : testing_callback_(std::move(testing_callback)) {}
+  ~ReceivedImageDecoder() override = default;
+
+  void DecodeImage(const base::FilePath& image_path) {
+    auto contents = std::make_unique<std::string>();
+    auto* contents_ptr = contents.get();
+
+    base::ThreadPool::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::MayBlock()},
+        base::BindOnce(&base::ReadFileToString, image_path, contents_ptr),
+        base::BindOnce(&ReceivedImageDecoder::OnFileRead,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(contents)));
+  }
+
+  // ImageDecoder::ImageRequest implementation:
+  void OnImageDecoded(const SkBitmap& decoded_image) override {
+    NS_LOG(VERBOSE) << __func__ << ": Image decoding succeeded.";
+    ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
+        .WriteImage(decoded_image);
+
+    if (testing_callback_) {
+      std::move(testing_callback_)
+          .Run(
+              NearbyNotificationManager::SuccessNotificationAction::kCopyImage);
+    }
+
+    delete this;
+  }
+
+  void OnDecodeImageFailed() override {
+    NS_LOG(ERROR) << __func__ << ": Failed to decode received image.";
+    if (testing_callback_) {
+      std::move(testing_callback_)
+          .Run(NearbyNotificationManager::SuccessNotificationAction::kNone);
+    }
+    delete this;
+  }
+
+ private:
+  void OnFileRead(std::unique_ptr<std::string> contents,
+                  bool is_contents_read) {
+    if (!is_contents_read || !contents || contents->empty()) {
+      NS_LOG(VERBOSE) << __func__ << ": Image contents not found.";
+
+      if (testing_callback_) {
+        std::move(testing_callback_)
+            .Run(NearbyNotificationManager::SuccessNotificationAction::kNone);
+      }
+
+      delete this;
+      return;
+    }
+
+    ImageDecoder::Start(this, *contents);
+  }
+
+  base::OnceCallback<void(NearbyNotificationManager::SuccessNotificationAction)>
+      testing_callback_;
+
+  base::WeakPtrFactory<ReceivedImageDecoder> weak_ptr_factory_{this};
+};
+
+class SuccessNotificationDelegate : public NearbyNotificationDelegate {
+ public:
+  SuccessNotificationDelegate(
+      NearbyNotificationManager* manager,
+      ShareTarget share_target,
+      Profile* profile,
+      base::OnceCallback<
+          void(NearbyNotificationManager::SuccessNotificationAction)>
+          testing_callback)
+      : manager_(manager),
+        share_target_(std::move(share_target)),
+        profile_(profile),
+        testing_callback_(std::move(testing_callback)) {}
+  ~SuccessNotificationDelegate() override = default;
+
+  static bool CanCopyAttachmentToClipboard(const ShareTarget& share_target) {
+    if (!share_target.text_attachments.empty()) {
+      return true;
+    }
+
+    if (share_target.file_attachments.size() == 1 &&
+        share_target.file_attachments[0].type() ==
+            sharing::mojom::FileMetadata::Type::kImage &&
+        share_target.file_attachments[0].file_path()) {
+      return true;
+    }
+
+    return false;
+  }
+
+  // NearbyNotificationDelegate:
+  void OnClick(const std::string& notification_id,
+               const base::Optional<int>& action_index) override {
+    DCHECK(!action_index);
+
+    if (!CanCopyAttachmentToClipboard(share_target_)) {
+      // TODO(crbug.com/1085069) - Open downloads tab instead for non ChromeOS
+      // browsers.
+      OpenDownloadsFolder();
+    } else if (!share_target_.text_attachments.empty()) {
+      CopyTextToClipboard(share_target_.text_attachments[0].text_body());
+    } else {
+      DCHECK_EQ(sharing::mojom::FileMetadata::Type::kImage,
+                share_target_.file_attachments[0].type());
+
+      CopyImageToClipboard(share_target_.file_attachments[0].file_path());
+    }
+
+    manager_->CloseSuccessNotification();
+  }
+
+  void OnClose(const std::string& notification_id) override {
+    manager_->CloseSuccessNotification();
+  }
+
+ private:
+  void OpenDownloadsFolder() {
+    platform_util::OpenItem(
+        profile_,
+        DownloadPrefs::FromDownloadManager(
+            content::BrowserContext::GetDownloadManager(profile_))
+            ->DownloadPath(),
+        platform_util::OPEN_FOLDER, platform_util::OpenOperationCallback());
+
+    if (testing_callback_) {
+      std::move(testing_callback_)
+          .Run(NearbyNotificationManager::SuccessNotificationAction::
+                   kOpenDownloads);
+    }
+  }
+
+  void CopyTextToClipboard(const std::string& text) {
+    ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
+        .WriteText(
+            base::UTF8ToUTF16(share_target_.text_attachments[0].text_body()));
+
+    if (testing_callback_) {
+      std::move(testing_callback_)
+          .Run(NearbyNotificationManager::SuccessNotificationAction::kCopyText);
+    }
+  }
+
+  void CopyImageToClipboard(const base::Optional<base::FilePath>& file_path) {
+    // ReceivedImageDecoder will delete itself on completion of ImageDecoder
+    // callback.
+    ReceivedImageDecoder* decoder =
+        new ReceivedImageDecoder(std::move(testing_callback_));
+    decoder->DecodeImage(*file_path);
+  }
+
+  NearbyNotificationManager* manager_;
+  ShareTarget share_target_;
+  Profile* profile_;
+  base::OnceCallback<void(NearbyNotificationManager::SuccessNotificationAction)>
+      testing_callback_;
+};
+
 class OnboardingNotificationDelegate : public NearbyNotificationDelegate {
  public:
   explicit OnboardingNotificationDelegate(NearbyNotificationManager* manager)
@@ -304,10 +479,12 @@
 NearbyNotificationManager::NearbyNotificationManager(
     NotificationDisplayService* notification_display_service,
     NearbySharingService* nearby_service,
-    PrefService* pref_service)
+    PrefService* pref_service,
+    Profile* profile)
     : notification_display_service_(notification_display_service),
       nearby_service_(nearby_service),
-      pref_service_(pref_service) {
+      pref_service_(pref_service),
+      profile_(profile) {
   DCHECK(notification_display_service_);
   DCHECK(nearby_service_);
   DCHECK(pref_service_);
@@ -466,7 +643,14 @@
   notification.set_title(GetSuccessNotificationTitle(share_target));
 
   // TODO(crbug.com/1102348): Show content specific actions and preview images.
-  delegate_map_.erase(kNearbyNotificationId);
+  if (share_target.is_incoming) {
+    delegate_map_[kNearbyNotificationId] =
+        std::make_unique<SuccessNotificationDelegate>(
+            this, share_target, profile_,
+            std::move(success_action_test_callback_));
+  } else {
+    delegate_map_.erase(kNearbyNotificationId);
+  }
 
   notification_display_service_->Display(
       NotificationHandler::Type::NEARBY_SHARE, notification,
@@ -533,3 +717,14 @@
   CloseOnboarding();
   UpdateOnboardingDismissedTime(pref_service_);
 }
+
+void NearbyNotificationManager::CloseSuccessNotification() {
+  delegate_map_.erase(kNearbyNotificationId);
+  notification_display_service_->Close(NotificationHandler::Type::NEARBY_SHARE,
+                                       kNearbyNotificationId);
+}
+
+void NearbyNotificationManager::SetOnSuccessClickedForTesting(
+    base::OnceCallback<void(SuccessNotificationAction)> callback) {
+  success_action_test_callback_ = std::move(callback);
+}
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.h b/chrome/browser/nearby_sharing/nearby_notification_manager.h
index 72fa20e6..2a8555a 100644
--- a/chrome/browser/nearby_sharing/nearby_notification_manager.h
+++ b/chrome/browser/nearby_sharing/nearby_notification_manager.h
@@ -17,6 +17,7 @@
 class NearbySharingService;
 class NotificationDisplayService;
 class PrefService;
+class Profile;
 
 // Manages notifications shown for Nearby Share. Only a single notification will
 // be shown as simultaneous connections are not supported. All methods should be
@@ -27,10 +28,18 @@
   static constexpr base::TimeDelta kOnboardingDismissedTimeout =
       base::TimeDelta::FromMinutes(15);
 
+  enum class SuccessNotificationAction {
+    kNone,
+    kCopyText,
+    kCopyImage,
+    kOpenDownloads,
+  };
+
   NearbyNotificationManager(
       NotificationDisplayService* notification_display_service,
       NearbySharingService* nearby_service,
-      PrefService* pref_service);
+      PrefService* pref_service,
+      Profile* profile);
   ~NearbyNotificationManager() override;
 
   // TransferUpdateCallback:
@@ -90,10 +99,16 @@
   // another one for a certain time period after this.
   void OnOnboardingDismissed();
 
+  void CloseSuccessNotification();
+
+  void SetOnSuccessClickedForTesting(
+      base::OnceCallback<void(SuccessNotificationAction)> callback);
+
  private:
   NotificationDisplayService* notification_display_service_;
   NearbySharingService* nearby_service_;
   PrefService* pref_service_;
+  Profile* profile_;
 
   // Maps notification ids to notification delegates.
   base::flat_map<std::string, std::unique_ptr<NearbyNotificationDelegate>>
@@ -101,6 +116,9 @@
 
   // ShareTarget of the current transfer.
   base::Optional<ShareTarget> share_target_;
+
+  base::OnceCallback<void(SuccessNotificationAction)>
+      success_action_test_callback_;
 };
 
 #endif  // CHROME_BROWSER_NEARBY_SHARING_NEARBY_NOTIFICATION_MANAGER_H_
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
index 7d1dc479..6a33403 100644
--- a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
@@ -7,14 +7,22 @@
 #include <memory>
 #include <vector>
 
+#include "base/files/file_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "base/threading/thread_restrictions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/browser_features.h"
+#include "chrome/browser/download/chrome_download_manager_delegate.h"
+#include "chrome/browser/download/download_core_service_factory.h"
+#include "chrome/browser/download/download_core_service_impl.h"
+#include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
+#include "chrome/browser/nearby_sharing/constants.h"
 #include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h"
 #include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
 #include "chrome/browser/nearby_sharing/share_target.h"
@@ -26,26 +34,32 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/browser_task_environment.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/test/clipboard_test_util.h"
+#include "ui/base/clipboard/test/test_clipboard.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "ui/strings/grit/ui_strings.h"
 
 namespace {
 
+const char kTextBody[] = "text body";
+
 MATCHER_P(MatchesTarget, target, "") {
   return arg.id == target.id;
 }
 
 TextAttachment CreateTextAttachment(TextAttachment::Type type) {
-  return TextAttachment(type, "text body");
+  return TextAttachment(type, kTextBody);
 }
 
 FileAttachment CreateFileAttachment(FileAttachment::Type type) {
-  return FileAttachment(/*file_name=*/"file.jpg", type,
-                        /*size=*/10,
-                        /*file_path=*/base::nullopt,
-                        /*mime_type=*/"example");
+  return FileAttachment(/*id=*/0, /*size=*/10, /*file_name=*/"file.jpg",
+                        /*mime_type=*/"example", type);
 }
 
 std::unique_ptr<KeyedService> CreateMockNearbySharingService(
@@ -61,6 +75,64 @@
           base::BindRepeating(&CreateMockNearbySharingService)));
 }
 
+std::string GetClipboardText() {
+  base::string16 text;
+  ui::Clipboard::GetForCurrentThread()->ReadText(
+      ui::ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &text);
+  return base::UTF16ToUTF8(text);
+}
+
+SkBitmap GetClipboardImage() {
+  return ui::clipboard_test_util::ReadImage(
+      ui::Clipboard::GetForCurrentThread());
+}
+
+SkBitmap CreateTestSkBitmap() {
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(/*w=*/10, /*h=*/15);
+  bitmap.eraseColor(SK_ColorRED);
+  return bitmap;
+}
+
+ShareTarget CreateIncomingShareTarget(int text_attachments,
+                                      int image_attachments,
+                                      int other_file_attachments) {
+  ShareTarget share_target;
+  share_target.is_incoming = true;
+  for (int i = 0; i < text_attachments; i++) {
+    share_target.text_attachments.push_back(
+        CreateTextAttachment(TextAttachment::Type::kText));
+  }
+
+  for (int i = 0; i < image_attachments; i++) {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    base::FilePath file_path;
+    base::CreateTemporaryFile(&file_path);
+    SkBitmap image = CreateTestSkBitmap();
+
+    std::vector<unsigned char> png_data;
+    EXPECT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(
+        image, /*discard_transparency=*/true, &png_data));
+    char* data = reinterpret_cast<char*>(&png_data[0]);
+    int size = static_cast<int>(png_data.size());
+    base::WriteFile(file_path, data, size);
+
+    FileAttachment attachment(/*file_name=*/"file.jpg",
+                              FileAttachment::Type::kImage,
+                              /*size=*/10,
+                              /*file_path=*/file_path,
+                              /*mime_type=*/"example");
+
+    share_target.file_attachments.push_back(std::move(attachment));
+  }
+
+  for (int i = 0; i < other_file_attachments; i++) {
+    share_target.file_attachments.push_back(
+        CreateFileAttachment(FileAttachment::Type::kVideo));
+  }
+  return share_target;
+}
+
 class NearbyNotificationManagerTest : public testing::Test {
  public:
   NearbyNotificationManagerTest() {
@@ -75,8 +147,19 @@
             testing::Invoke([&](const std::string& notification_id) {
               return manager_->GetNotificationDelegate(notification_id);
             }));
+
+    DownloadCoreServiceFactory::GetForBrowserContext(&profile_)
+        ->SetDownloadManagerDelegateForTesting(
+            std::make_unique<ChromeDownloadManagerDelegate>(&profile_));
+
+    ui::TestClipboard::CreateForCurrentThread();
   }
-  ~NearbyNotificationManagerTest() override = default;
+
+  ~NearbyNotificationManagerTest() override {
+    DownloadCoreServiceFactory::GetForBrowserContext(&profile_)
+        ->SetDownloadManagerDelegateForTesting(nullptr);
+    ui::Clipboard::DestroyClipboardForCurrentThread();
+  }
 
   NearbyNotificationManager* manager() { return manager_.get(); }
 
@@ -89,7 +172,8 @@
     NotificationDisplayService* notification_display_service =
         NotificationDisplayServiceFactory::GetForProfile(&profile_);
     return std::make_unique<NearbyNotificationManager>(
-        notification_display_service, nearby_service_, &pref_service_);
+        notification_display_service, nearby_service_, &pref_service_,
+        &profile_);
   }
 
  protected:
@@ -101,6 +185,8 @@
   std::unique_ptr<NotificationDisplayServiceTester> notification_tester_;
   MockNearbySharingService* nearby_service_;
   std::unique_ptr<NearbyNotificationManager> manager_;
+  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
+  base::ScopedDisallowBlocking disallow_blocking_;
 };
 
 struct AttachmentsTestParamInternal {
@@ -781,3 +867,162 @@
   manager()->ShowOnboarding();
   EXPECT_EQ(1u, GetDisplayedNotifications().size());
 }
+
+TEST_F(NearbyNotificationManagerTest,
+       SuccessNotificationClicked_SingleImageReceived) {
+  base::RunLoop run_loop;
+  manager()->SetOnSuccessClickedForTesting(base::BindLambdaForTesting(
+      [&](NearbyNotificationManager::SuccessNotificationAction action) {
+        EXPECT_EQ(
+            NearbyNotificationManager::SuccessNotificationAction::kCopyImage,
+            action);
+        run_loop.Quit();
+      }));
+
+  ShareTarget share_target =
+      CreateIncomingShareTarget(/*text_attachments=*/0, /*image_attachments=*/1,
+                                /*other_file_attachments=*/0);
+  manager()->ShowSuccess(share_target);
+
+  std::vector<message_center::Notification> notifications =
+      GetDisplayedNotifications();
+  ASSERT_EQ(1u, notifications.size());
+
+  notification_tester_->SimulateClick(NotificationHandler::Type::NEARBY_SHARE,
+                                      notifications[0].id(),
+                                      /*action_index=*/base::nullopt,
+                                      /*reply=*/base::nullopt);
+
+  run_loop.Run();
+
+  // Expected behaviour is to copy to clipboard.
+  SkBitmap image = GetClipboardImage();
+  EXPECT_TRUE(gfx::BitmapsAreEqual(CreateTestSkBitmap(), image));
+
+  // Notification should be closed.
+  EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(NearbyNotificationManagerTest,
+       SuccessNotificationClicked_MultipleImagesReceived) {
+  base::RunLoop run_loop;
+  manager()->SetOnSuccessClickedForTesting(base::BindLambdaForTesting(
+      [&](NearbyNotificationManager::SuccessNotificationAction action) {
+        EXPECT_EQ(NearbyNotificationManager::SuccessNotificationAction::
+                      kOpenDownloads,
+                  action);
+        run_loop.Quit();
+      }));
+
+  ShareTarget share_target =
+      CreateIncomingShareTarget(/*text_attachments=*/0, /*image_attachments=*/2,
+                                /*other_file_attachments=*/0);
+  manager()->ShowSuccess(share_target);
+
+  std::vector<message_center::Notification> notifications =
+      GetDisplayedNotifications();
+  ASSERT_EQ(1u, notifications.size());
+
+  notification_tester_->SimulateClick(NotificationHandler::Type::NEARBY_SHARE,
+                                      notifications[0].id(),
+                                      /*action_index=*/base::nullopt,
+                                      /*reply=*/base::nullopt);
+
+  run_loop.Run();
+
+  // Notification should be closed.
+  EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(NearbyNotificationManagerTest, SuccessNotificationClicked_TextReceived) {
+  base::RunLoop run_loop;
+  manager()->SetOnSuccessClickedForTesting(base::BindLambdaForTesting(
+      [&](NearbyNotificationManager::SuccessNotificationAction action) {
+        EXPECT_EQ(
+            NearbyNotificationManager::SuccessNotificationAction::kCopyText,
+            action);
+        run_loop.Quit();
+      }));
+
+  ShareTarget share_target =
+      CreateIncomingShareTarget(/*text_attachments=*/1, /*image_attachments=*/0,
+                                /*other_file_attachments=*/0);
+  manager()->ShowSuccess(share_target);
+
+  std::vector<message_center::Notification> notifications =
+      GetDisplayedNotifications();
+  ASSERT_EQ(1u, notifications.size());
+
+  notification_tester_->SimulateClick(NotificationHandler::Type::NEARBY_SHARE,
+                                      notifications[0].id(),
+                                      /*action_index=*/base::nullopt,
+                                      /*reply=*/base::nullopt);
+
+  run_loop.Run();
+  EXPECT_EQ(kTextBody, GetClipboardText());
+
+  // Notification should be closed.
+  EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(NearbyNotificationManagerTest,
+       SuccessNotificationClicked_SingleFileReceived) {
+  base::RunLoop run_loop;
+  manager()->SetOnSuccessClickedForTesting(base::BindLambdaForTesting(
+      [&](NearbyNotificationManager::SuccessNotificationAction action) {
+        EXPECT_EQ(NearbyNotificationManager::SuccessNotificationAction::
+                      kOpenDownloads,
+                  action);
+        run_loop.Quit();
+      }));
+
+  ShareTarget share_target =
+      CreateIncomingShareTarget(/*text_attachments=*/0, /*image_attachments=*/0,
+                                /*other_file_attachments=*/1);
+  manager()->ShowSuccess(share_target);
+
+  std::vector<message_center::Notification> notifications =
+      GetDisplayedNotifications();
+  ASSERT_EQ(1u, notifications.size());
+
+  notification_tester_->SimulateClick(NotificationHandler::Type::NEARBY_SHARE,
+                                      notifications[0].id(),
+                                      /*action_index=*/base::nullopt,
+                                      /*reply=*/base::nullopt);
+
+  run_loop.Run();
+
+  // Notification should be closed.
+  EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(NearbyNotificationManagerTest,
+       SuccessNotificationClicked_MultipleFilesReceived) {
+  base::RunLoop run_loop;
+  manager()->SetOnSuccessClickedForTesting(base::BindLambdaForTesting(
+      [&](NearbyNotificationManager::SuccessNotificationAction action) {
+        EXPECT_EQ(NearbyNotificationManager::SuccessNotificationAction::
+                      kOpenDownloads,
+                  action);
+        run_loop.Quit();
+      }));
+
+  ShareTarget share_target =
+      CreateIncomingShareTarget(/*text_attachments=*/0, /*image_attachments=*/1,
+                                /*other_file_attachments=*/2);
+  manager()->ShowSuccess(share_target);
+
+  std::vector<message_center::Notification> notifications =
+      GetDisplayedNotifications();
+  ASSERT_EQ(1u, notifications.size());
+
+  notification_tester_->SimulateClick(NotificationHandler::Type::NEARBY_SHARE,
+                                      notifications[0].id(),
+                                      /*action_index=*/base::nullopt,
+                                      /*reply=*/base::nullopt);
+
+  run_loop.Run();
+
+  // Notification should be closed.
+  EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
diff --git a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc
index 91cde05b..ed0a00b 100644
--- a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc
+++ b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc
@@ -14,9 +14,35 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
+namespace {
+
+base::Optional<nearby_share::mojom::TransferStatus> GetTransferStatus(
+    const TransferMetadata& transfer_metadata) {
+  switch (transfer_metadata.status()) {
+    case TransferMetadata::Status::kAwaitingLocalConfirmation:
+      return nearby_share::mojom::TransferStatus::kAwaitingLocalConfirmation;
+    case TransferMetadata::Status::kAwaitingRemoteAcceptance:
+      return nearby_share::mojom::TransferStatus::kAwaitingRemoteAcceptance;
+    case TransferMetadata::Status::kComplete:
+    case TransferMetadata::Status::kInProgress:
+      return nearby_share::mojom::TransferStatus::kInProgress;
+    default:
+      break;
+  }
+
+  // TODO(knollr): Show error if transfer_metadata.is_final_status().
+
+  // Ignore all other transfer status updates.
+  return base::nullopt;
+}
+
+}  // namespace
+
 NearbyPerSessionDiscoveryManager::NearbyPerSessionDiscoveryManager(
-    NearbySharingService* nearby_sharing_service)
-    : nearby_sharing_service_(nearby_sharing_service) {}
+    NearbySharingService* nearby_sharing_service,
+    std::vector<std::unique_ptr<Attachment>> attachments)
+    : nearby_sharing_service_(nearby_sharing_service),
+      attachments_(std::move(attachments)) {}
 
 NearbyPerSessionDiscoveryManager::~NearbyPerSessionDiscoveryManager() {
   UnregisterSendSurface();
@@ -25,33 +51,14 @@
 void NearbyPerSessionDiscoveryManager::OnTransferUpdate(
     const ShareTarget& share_target,
     const TransferMetadata& transfer_metadata) {
-  switch (transfer_metadata.status()) {
-    case TransferMetadata::Status::kAwaitingLocalConfirmation: {
-      DCHECK(select_share_target_callback_);
-      mojo::PendingRemote<nearby_share::mojom::ConfirmationManager> remote;
-      mojo::MakeSelfOwnedReceiver(std::make_unique<NearbyConfirmationManager>(
-                                      nearby_sharing_service_, share_target),
-                                  remote.InitWithNewPipeAndPassReceiver());
-      std::move(select_share_target_callback_)
-          .Run(nearby_share::mojom::SelectShareTargetResult::kOk,
-               transfer_metadata.token(), std::move(remote));
-      break;
-    }
-    case TransferMetadata::Status::kAwaitingRemoteAcceptance:
-      DCHECK(select_share_target_callback_);
-      std::move(select_share_target_callback_)
-          .Run(nearby_share::mojom::SelectShareTargetResult::kOk,
-               /*token=*/base::nullopt, mojo::NullRemote());
-      break;
-    default:
-      if (transfer_metadata.is_final_status() &&
-          select_share_target_callback_) {
-        std::move(select_share_target_callback_)
-            .Run(nearby_share::mojom::SelectShareTargetResult::kError,
-                 /*token=*/base::nullopt, mojo::NullRemote());
-      }
-      break;
-  }
+  DCHECK(transfer_update_listener_.is_bound());
+  base::Optional<nearby_share::mojom::TransferStatus> status =
+      GetTransferStatus(transfer_metadata);
+  if (!status)
+    return;
+
+  transfer_update_listener_->OnTransferUpdate(*status,
+                                              transfer_metadata.token());
 }
 
 void NearbyPerSessionDiscoveryManager::OnShareTargetDiscovered(
@@ -93,34 +100,41 @@
     const base::UnguessableToken& share_target_id,
     SelectShareTargetCallback callback) {
   DCHECK(share_target_listener_.is_bound());
-  DCHECK(!select_share_target_callback_);
+  DCHECK(!transfer_update_listener_.is_bound());
 
   auto iter = discovered_share_targets_.find(share_target_id);
   if (iter == discovered_share_targets_.end()) {
     NS_LOG(VERBOSE) << "Unknown share target selected: id=" << share_target_id;
     std::move(callback).Run(
         nearby_share::mojom::SelectShareTargetResult::kInvalidShareTarget,
-        /*token=*/base::nullopt, mojo::NullRemote());
+        mojo::NullReceiver(), mojo::NullRemote());
     return;
   }
 
-  select_share_target_callback_ = std::move(callback);
-  // TODO(crbug.com/1099710): Call correct method and pass attachments.
-  NearbySharingService::StatusCodes status =
-      nearby_sharing_service_->SendText(iter->second, "Example Text");
+  // Bind update listener before calling the sharing service to get all updates.
+  mojo::PendingReceiver<nearby_share::mojom::TransferUpdateListener> receiver =
+      transfer_update_listener_.BindNewPipeAndPassReceiver();
 
-  // Nothing to do if the result has been returned already.
-  if (!select_share_target_callback_)
-    return;
+  NearbySharingService::StatusCodes status =
+      nearby_sharing_service_->SendAttachments(iter->second,
+                                               std::move(attachments_));
 
   // If the send call succeeded, we expect OnTransferUpdate() to be called next.
-  if (status == NearbySharingService::StatusCodes::kOk)
+  if (status == NearbySharingService::StatusCodes::kOk) {
+    mojo::PendingRemote<nearby_share::mojom::ConfirmationManager> remote;
+    mojo::MakeSelfOwnedReceiver(std::make_unique<NearbyConfirmationManager>(
+                                    nearby_sharing_service_, iter->second),
+                                remote.InitWithNewPipeAndPassReceiver());
+
+    std::move(callback).Run(nearby_share::mojom::SelectShareTargetResult::kOk,
+                            std::move(receiver), std::move(remote));
     return;
+  }
 
   NS_LOG(VERBOSE) << "Failed to select share target";
-  std::move(select_share_target_callback_)
-      .Run(nearby_share::mojom::SelectShareTargetResult::kError,
-           /*token=*/base::nullopt, mojo::NullRemote());
+  transfer_update_listener_.reset();
+  std::move(callback).Run(nearby_share::mojom::SelectShareTargetResult::kError,
+                          mojo::NullReceiver(), mojo::NullRemote());
 }
 
 void NearbyPerSessionDiscoveryManager::UnregisterSendSurface() {
diff --git a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h
index bee8e7c..c133da4 100644
--- a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h
+++ b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h
@@ -5,9 +5,13 @@
 #ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_PER_SESSION_DISCOVERY_MANAGER_H_
 #define CHROME_BROWSER_NEARBY_SHARING_NEARBY_PER_SESSION_DISCOVERY_MANAGER_H_
 
+#include <memory>
+#include <vector>
+
 #include "base/containers/flat_map.h"
 #include "base/memory/weak_ptr.h"
 #include "base/unguessable_token.h"
+#include "chrome/browser/nearby_sharing/attachment.h"
 #include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
 #include "chrome/browser/nearby_sharing/share_target_discovered_callback.h"
 #include "chrome/browser/nearby_sharing/transfer_update_callback.h"
@@ -23,8 +27,9 @@
       public ShareTargetDiscoveredCallback,
       public nearby_share::mojom::DiscoveryManager {
  public:
-  explicit NearbyPerSessionDiscoveryManager(
-      NearbySharingService* nearby_sharing_service);
+  NearbyPerSessionDiscoveryManager(
+      NearbySharingService* nearby_sharing_service,
+      std::vector<std::unique_ptr<Attachment>> attachments);
   ~NearbyPerSessionDiscoveryManager() override;
 
   // TransferUpdateCallback:
@@ -47,8 +52,10 @@
   void UnregisterSendSurface();
 
   NearbySharingService* nearby_sharing_service_;
+  std::vector<std::unique_ptr<Attachment>> attachments_;
   mojo::Remote<nearby_share::mojom::ShareTargetListener> share_target_listener_;
-  SelectShareTargetCallback select_share_target_callback_;
+  mojo::Remote<nearby_share::mojom::TransferUpdateListener>
+      transfer_update_listener_;
 
   // Map of ShareTarget id to discovered ShareTargets.
   base::flat_map<base::UnguessableToken, ShareTarget> discovered_share_targets_;
diff --git a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc
index 30e80ed..fa5216a0 100644
--- a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h"
 
+#include <string>
+
+#include "base/optional.h"
 #include "base/test/mock_callback.h"
 #include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h"
 #include "chrome/browser/nearby_sharing/share_target.h"
@@ -11,6 +14,8 @@
 #include "chrome/browser/nearby_sharing/transfer_metadata_builder.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
 #include "content/public/test/browser_task_environment.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,6 +28,25 @@
   return arg.id == target.id;
 }
 
+const char kTextAttachmentBody[] = "Test text payload";
+
+std::vector<std::unique_ptr<Attachment>> CreateAttachments() {
+  std::vector<std::unique_ptr<Attachment>> attachments;
+  attachments.push_back(std::make_unique<TextAttachment>(
+      TextAttachment::Type::kText, kTextAttachmentBody));
+  return attachments;
+}
+
+void ExpectTextAttachment(
+    const std::string& text_body,
+    const std::vector<std::unique_ptr<Attachment>>& attachments) {
+  ASSERT_EQ(1u, attachments.size());
+  ASSERT_TRUE(attachments[0]);
+  ASSERT_EQ(Attachment::Family::kText, attachments[0]->family());
+  auto* text_attachment = static_cast<TextAttachment*>(attachments[0].get());
+  EXPECT_EQ(text_body, text_attachment->text_body());
+}
+
 class MockShareTargetListener
     : public nearby_share::mojom::ShareTargetListener {
  public:
@@ -41,6 +65,27 @@
   mojo::Receiver<ShareTargetListener> receiver_{this};
 };
 
+class MockTransferUpdateListener
+    : public nearby_share::mojom::TransferUpdateListener {
+ public:
+  MockTransferUpdateListener() = default;
+  ~MockTransferUpdateListener() override = default;
+
+  void Bind(mojo::PendingReceiver<TransferUpdateListener> receiver) {
+    return receiver_.Bind(std::move(receiver));
+  }
+
+  // nearby_share::mojom::TransferUpdateListener:
+  MOCK_METHOD(void,
+              OnTransferUpdate,
+              (nearby_share::mojom::TransferStatus status,
+               const base::Optional<std::string>&),
+              (override));
+
+ private:
+  mojo::Receiver<TransferUpdateListener> receiver_{this};
+};
+
 class NearbyPerSessionDiscoveryManagerTest : public testing::Test {
  public:
   using MockSelectShareTargetCallback = base::MockCallback<
@@ -58,7 +103,8 @@
  private:
   content::BrowserTaskEnvironment task_environment_;
   MockNearbySharingService sharing_service_;
-  NearbyPerSessionDiscoveryManager manager_{&sharing_service_};
+  NearbyPerSessionDiscoveryManager manager_{&sharing_service_,
+                                            CreateAttachments()};
 };
 
 }  // namespace
@@ -69,7 +115,8 @@
   EXPECT_CALL(sharing_service(), UnregisterSendSurface(&manager(), &manager()))
       .Times(0);
   {
-    NearbyPerSessionDiscoveryManager manager(&sharing_service());
+    NearbyPerSessionDiscoveryManager manager(&sharing_service(),
+                                             CreateAttachments());
     // Creating and destroying an instance should not register itself with the
     // NearbySharingService.
   }
@@ -156,7 +203,7 @@
   EXPECT_CALL(
       callback,
       Run(nearby_share::mojom::SelectShareTargetResult::kInvalidShareTarget,
-          testing::Eq(base::nullopt), testing::IsFalse()));
+          testing::IsFalse(), testing::IsFalse()));
 
   manager().SelectShareTarget({}, callback.Get());
 }
@@ -172,15 +219,17 @@
   ShareTarget share_target;
   manager().OnShareTargetDiscovered(share_target);
 
-  // We don't expect the callback to be called until OnTransferUpdate().
   MockSelectShareTargetCallback callback;
-  EXPECT_CALL(callback, Run(_, _, _)).Times(0);
+  EXPECT_CALL(callback, Run(nearby_share::mojom::SelectShareTargetResult::kOk,
+                            testing::IsTrue(), testing::IsTrue()));
 
-  // TODO(crbug.com/1099710): Call correct method and pass attachments.
-  EXPECT_CALL(sharing_service(), SendText(_, _))
+  EXPECT_CALL(sharing_service(), SendAttachments(_, _))
       .WillOnce(testing::Invoke(
-          [&share_target](const ShareTarget& target, std::string text) {
+          [&share_target](
+              const ShareTarget& target,
+              std::vector<std::unique_ptr<Attachment>> attachments) {
             EXPECT_EQ(share_target.id, target.id);
+            ExpectTextAttachment(kTextAttachmentBody, attachments);
             return NearbySharingService::StatusCodes::kOk;
           }));
 
@@ -202,13 +251,15 @@
   MockSelectShareTargetCallback callback;
   EXPECT_CALL(callback,
               Run(nearby_share::mojom::SelectShareTargetResult::kError,
-                  testing::Eq(base::nullopt), testing::IsFalse()));
+                  testing::IsFalse(), testing::IsFalse()));
 
-  // TODO(crbug.com/1099710): Call correct method and pass attachments.
-  EXPECT_CALL(sharing_service(), SendText(_, _))
+  EXPECT_CALL(sharing_service(), SendAttachments(_, _))
       .WillOnce(testing::Invoke(
-          [&share_target](const ShareTarget& target, std::string text) {
+          [&share_target](
+              const ShareTarget& target,
+              std::vector<std::unique_ptr<Attachment>> attachments) {
             EXPECT_EQ(share_target.id, target.id);
+            ExpectTextAttachment(kTextAttachmentBody, attachments);
             return NearbySharingService::StatusCodes::kError;
           }));
 
@@ -218,21 +269,39 @@
 TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitRemote) {
   // Setup share target
   MockShareTargetListener listener;
+  MockTransferUpdateListener transfer_listener;
   EXPECT_CALL(sharing_service(),
               RegisterSendSurface(testing::_, testing::_, testing::_))
       .WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
 
+  base::RunLoop run_loop;
+  EXPECT_CALL(transfer_listener, OnTransferUpdate)
+      .WillOnce(testing::Invoke(
+          [&run_loop](nearby_share::mojom::TransferStatus status,
+                      const base::Optional<std::string>& token) {
+            EXPECT_EQ(
+                nearby_share::mojom::TransferStatus::kAwaitingRemoteAcceptance,
+                status);
+            EXPECT_FALSE(token.has_value());
+            run_loop.Quit();
+          }));
+
   manager().StartDiscovery(listener.Bind(), base::DoNothing());
   ShareTarget share_target;
   manager().OnShareTargetDiscovered(share_target);
 
-  // Expect success without confirmation manager and token.
   MockSelectShareTargetCallback callback;
   EXPECT_CALL(callback, Run(nearby_share::mojom::SelectShareTargetResult::kOk,
-                            testing::Eq(base::nullopt), testing::IsFalse()));
+                            testing::IsTrue(), testing::IsTrue()))
+      .WillOnce(testing::Invoke(
+          [&transfer_listener](
+              nearby_share::mojom::SelectShareTargetResult result,
+              mojo::PendingReceiver<nearby_share::mojom::TransferUpdateListener>
+                  listener,
+              mojo::PendingRemote<nearby_share::mojom::ConfirmationManager>
+                  manager) { transfer_listener.Bind(std::move(listener)); }));
 
-  // TODO(crbug.com/1099710): Call correct method and pass attachments.
-  EXPECT_CALL(sharing_service(), SendText(_, _))
+  EXPECT_CALL(sharing_service(), SendAttachments(_, _))
       .WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
 
   manager().SelectShareTarget(share_target.id, callback.Get());
@@ -242,28 +311,48 @@
           .set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
           .build();
   manager().OnTransferUpdate(share_target, metadata);
+
+  run_loop.Run();
 }
 
 TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitLocal) {
   // Setup share target
   MockShareTargetListener listener;
+  MockTransferUpdateListener transfer_listener;
   EXPECT_CALL(sharing_service(),
               RegisterSendSurface(testing::_, testing::_, testing::_))
       .WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
 
+  const std::string expected_token = "Test Token";
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(transfer_listener, OnTransferUpdate)
+      .WillOnce(testing::Invoke([&run_loop, &expected_token](
+                                    nearby_share::mojom::TransferStatus status,
+                                    const base::Optional<std::string>& token) {
+        EXPECT_EQ(
+            nearby_share::mojom::TransferStatus::kAwaitingLocalConfirmation,
+            status);
+        EXPECT_EQ(expected_token, token);
+        run_loop.Quit();
+      }));
+
   manager().StartDiscovery(listener.Bind(), base::DoNothing());
   ShareTarget share_target;
   manager().OnShareTargetDiscovered(share_target);
 
-  std::string token = "Test Token";
-
-  // Expect to get a valid confirmation manager remote and token.
   MockSelectShareTargetCallback callback;
   EXPECT_CALL(callback, Run(nearby_share::mojom::SelectShareTargetResult::kOk,
-                            testing::Eq(token), testing::IsTrue()));
+                            testing::IsTrue(), testing::IsTrue()))
+      .WillOnce(testing::Invoke(
+          [&transfer_listener](
+              nearby_share::mojom::SelectShareTargetResult result,
+              mojo::PendingReceiver<nearby_share::mojom::TransferUpdateListener>
+                  listener,
+              mojo::PendingRemote<nearby_share::mojom::ConfirmationManager>
+                  manager) { transfer_listener.Bind(std::move(listener)); }));
 
-  // TODO(crbug.com/1099710): Call correct method and pass attachments.
-  EXPECT_CALL(sharing_service(), SendText(_, _))
+  EXPECT_CALL(sharing_service(), SendAttachments(_, _))
       .WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
 
   manager().SelectShareTarget(share_target.id, callback.Get());
@@ -271,7 +360,9 @@
   auto metadata =
       TransferMetadataBuilder()
           .set_status(TransferMetadata::Status::kAwaitingLocalConfirmation)
-          .set_token(token)
+          .set_token(expected_token)
           .build();
   manager().OnTransferUpdate(share_target, metadata);
+
+  run_loop.Run();
 }
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service.h b/chrome/browser/nearby_sharing/nearby_sharing_service.h
index 3e17452..0eaa2ec 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service.h
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_H_
 #define CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -87,13 +88,10 @@
   virtual StatusCodes UnregisterReceiveSurface(
       TransferUpdateCallback* transfer_callback) = 0;
 
-  // Sends text to the remote |share_target|.
-  virtual StatusCodes SendText(const ShareTarget& share_target,
-                               std::string text) = 0;
-
-  // Sends files to the remote |share_target|.
-  virtual StatusCodes SendFiles(const ShareTarget& share_target,
-                                const std::vector<base::FilePath>& files) = 0;
+  // Sends |attachments| to the remote |share_target|.
+  virtual StatusCodes SendAttachments(
+      const ShareTarget& share_target,
+      std::vector<std::unique_ptr<Attachment>> attachments) = 0;
 
   // Accepts incoming share from the remote |share_target|.
   virtual void Accept(const ShareTarget& share_target,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index 8e25868..d8d2677c 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -10,7 +10,6 @@
 #include "base/files/file.h"
 #include "base/logging.h"
 #include "base/numerics/checked_math.h"
-#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "base/task/post_task.h"
@@ -40,7 +39,6 @@
 #include "content/public/browser/storage_partition.h"
 #include "crypto/random.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "net/base/mime_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/base/idle/idle.h"
 #include "url/gurl.h"
@@ -159,41 +157,6 @@
   return payload_id;
 }
 
-TextAttachment TextAttachmentFromText(const std::string& text) {
-  return TextAttachment(TextAttachment::Type::kText, text);
-}
-
-FileAttachment::Type FileAttachmentTypeFromMimeType(
-    const std::string& mime_type) {
-  if (base::StartsWith(mime_type, "image/"))
-    return FileAttachment::Type::kImage;
-
-  if (base::StartsWith(mime_type, "video/"))
-    return FileAttachment::Type::kVideo;
-
-  if (base::StartsWith(mime_type, "audio/"))
-    return FileAttachment::Type::kAudio;
-
-  return FileAttachment::Type::kUnknown;
-}
-
-std::string MimeTypeFromPath(const base::FilePath path) {
-  std::string mime_type = "application/octet-stream";
-  base::FilePath::StringType ext = path.Extension();
-  if (!ext.empty())
-    net::GetWellKnownMimeTypeFromExtension(ext.substr(1), &mime_type);
-
-  return mime_type;
-}
-
-FileAttachment FileAttachmentFromPath(const base::FilePath path) {
-  std::string mime_type = MimeTypeFromPath(path);
-  // Size will be updated later asynchronously, see OnOpenFiles().
-  return FileAttachment(path.BaseName().AsUTF8Unsafe(),
-                        FileAttachmentTypeFromMimeType(mime_type),
-                        /*size=*/0, path, mime_type);
-}
-
 // Wraps a call to OnTransferUpdate() to filter any updates after receiving a
 // final status.
 class TransferUpdateDecorator : public TransferUpdateCallback {
@@ -264,7 +227,7 @@
   GetBluetoothAdapter();
 
   nearby_notification_manager_ = std::make_unique<NearbyNotificationManager>(
-      notification_display_service, this, prefs);
+      notification_display_service, this, prefs, profile_);
 }
 
 NearbySharingServiceImpl::~NearbySharingServiceImpl() {
@@ -475,25 +438,6 @@
   return StatusCodes::kOk;
 }
 
-NearbySharingServiceImpl::StatusCodes NearbySharingServiceImpl::SendText(
-    const ShareTarget& share_target,
-    std::string text) {
-  ShareTarget share_target_copy = share_target;
-  share_target_copy.text_attachments.push_back(TextAttachmentFromText(text));
-
-  return SendAttachments(std::move(share_target_copy));
-}
-
-NearbySharingServiceImpl::StatusCodes NearbySharingServiceImpl::SendFiles(
-    const ShareTarget& share_target,
-    const std::vector<base::FilePath>& files) {
-  ShareTarget share_target_copy = share_target;
-  for (const base::FilePath& path : files)
-    share_target_copy.file_attachments.push_back(FileAttachmentFromPath(path));
-
-  return SendAttachments(std::move(share_target_copy));
-}
-
 void NearbySharingServiceImpl::Accept(
     const ShareTarget& share_target,
     StatusCodesCallback status_codes_callback) {
@@ -1480,11 +1424,11 @@
 }
 
 NearbySharingService::StatusCodes NearbySharingServiceImpl::SendAttachments(
-    ShareTarget share_target) {
+    const ShareTarget& share_target,
+    std::vector<std::unique_ptr<Attachment>> attachments) {
   if (!is_scanning_) {
-    NS_LOG(WARNING)
-        << __func__
-        << ": Failed to send file to remote ShareTarget. Not scanning.";
+    NS_LOG(WARNING) << __func__
+                    << ": Failed to send attachments. Not scanning.";
     return StatusCodes::kError;
   }
 
@@ -1497,9 +1441,19 @@
   ShareTargetInfo* info = GetShareTargetInfo(share_target);
   if (!info || !info->endpoint_id()) {
     // TODO(crbug.com/1119276): Support scanning for unknown share targets.
-    NS_LOG(WARNING)
-        << __func__
-        << ": Failed to send file to remote ShareTarget. Unknown ShareTarget.";
+    NS_LOG(WARNING) << __func__
+                    << ": Failed to send attachments. Unknown ShareTarget.";
+    return StatusCodes::kError;
+  }
+
+  ShareTarget share_target_copy = share_target;
+  for (std::unique_ptr<Attachment>& attachment : attachments) {
+    DCHECK(attachment);
+    attachment->MoveToShareTarget(share_target_copy);
+  }
+
+  if (!share_target_copy.has_attachments()) {
+    NS_LOG(WARNING) << __func__ << ": No attachments to send.";
     return StatusCodes::kError;
   }
 
@@ -1523,11 +1477,11 @@
   // Send process initialized successfully, from now on status updated will be
   // sent out via OnOutgoingTransferUpdate().
   info->transfer_update_callback()->OnTransferUpdate(
-      share_target, TransferMetadataBuilder()
-                        .set_status(TransferMetadata::Status::kConnecting)
-                        .build());
+      share_target_copy, TransferMetadataBuilder()
+                             .set_status(TransferMetadata::Status::kConnecting)
+                             .build());
 
-  CreatePayloads(std::move(share_target),
+  CreatePayloads(std::move(share_target_copy),
                  base::BindOnce(&NearbySharingServiceImpl::OnCreatePayloads,
                                 weak_ptr_factory_.GetWeakPtr(),
                                 std::move(*endpoint_info)));
@@ -2181,8 +2135,8 @@
     NS_LOG(VERBOSE) << __func__ << "Found file attachment " << file->name
                     << " of type " << file->type << " with mimeType "
                     << file->mime_type;
-    FileAttachment attachment(file->id, file->name, file->type, file->size,
-                              file->mime_type);
+    FileAttachment attachment(file->id, file->size, file->name, file->mime_type,
+                              file->type);
     SetAttachmentPayloadId(attachment, file->payload_id);
     share_target.file_attachments.push_back(std::move(attachment));
 
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
index a4d2e900..3e202187 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -79,10 +79,9 @@
                                      ReceiveSurfaceState state) override;
   StatusCodes UnregisterReceiveSurface(
       TransferUpdateCallback* transfer_callback) override;
-  StatusCodes SendText(const ShareTarget& share_target,
-                       std::string text) override;
-  StatusCodes SendFiles(const ShareTarget& share_target,
-                        const std::vector<base::FilePath>& files) override;
+  StatusCodes SendAttachments(
+      const ShareTarget& share_target,
+      std::vector<std::unique_ptr<Attachment>> attachments) override;
   void Accept(const ShareTarget& share_target,
               StatusCodesCallback status_codes_callback) override;
   void Reject(const ShareTarget& share_target,
@@ -166,7 +165,6 @@
   StatusCodes ReceivePayloads(const ShareTarget& share_target);
   StatusCodes SendPayloads(const ShareTarget& share_target);
 
-  StatusCodes SendAttachments(ShareTarget share_target);
   void OnOutgoingConnection(const ShareTarget& share_target,
                             NearbyConnection* connection);
   void SendIntroduction(const ShareTarget& share_target,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
index dc9e6190..e9a6f7f6 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -268,6 +268,26 @@
   return free_space;
 }
 
+std::vector<std::unique_ptr<Attachment>> CreateTextAttachments(
+    std::vector<std::string> texts) {
+  std::vector<std::unique_ptr<Attachment>> attachments;
+  for (auto& text : texts) {
+    attachments.push_back(std::make_unique<TextAttachment>(
+        TextAttachment::Type::kText, std::move(text)));
+  }
+  return attachments;
+}
+
+std::vector<std::unique_ptr<Attachment>> CreateFileAttachments(
+    std::vector<base::FilePath> file_paths) {
+  std::vector<std::unique_ptr<Attachment>> attachments;
+  for (auto& file_path : file_paths) {
+    attachments.push_back(
+        std::make_unique<FileAttachment>(std::move(file_path)));
+  }
+  return attachments;
+}
+
 class NearbySharingServiceImplTest : public testing::Test {
  public:
   NearbySharingServiceImplTest()
@@ -2340,8 +2360,9 @@
                          TransferMetadata::Status::kAwaitingLocalConfirmation,
                          TransferMetadata::Status::kAwaitingRemoteAcceptance},
                         run_loop.QuitClosure());
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   run_loop.Run();
 
   NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface(
@@ -2353,6 +2374,17 @@
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
 }
 
+TEST_F(NearbySharingServiceImplTest, SendAttachments_WithoutAttachments) {
+  MockTransferUpdateCallback transfer_callback;
+  MockShareTargetDiscoveredCallback discovery_callback;
+  ShareTarget target =
+      DiscoverShareTarget(transfer_callback, discovery_callback);
+
+  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kError,
+            service_->SendAttachments(target, /*attachments=*/{}));
+  service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
+}
+
 TEST_F(NearbySharingServiceImplTest, SendText_AlreadySending) {
   MockTransferUpdateCallback transfer_callback;
   MockShareTargetDiscoveredCallback discovery_callback;
@@ -2365,21 +2397,24 @@
                          TransferMetadata::Status::kAwaitingLocalConfirmation,
                          TransferMetadata::Status::kAwaitingRemoteAcceptance},
                         run_loop.QuitClosure());
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   run_loop.Run();
 
   // We're now in the sending state, try to send again should fail
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kError,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kError,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
 
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
 }
 
 TEST_F(NearbySharingServiceImplTest, SendText_WithoutScanning) {
   ShareTarget target;
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kError,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kError,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
 }
 
 TEST_F(NearbySharingServiceImplTest, SendText_UnknownTarget) {
@@ -2388,8 +2423,9 @@
   DiscoverShareTarget(transfer_callback, discovery_callback);
 
   ShareTarget target;
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kError,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kError,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
 }
 
@@ -2402,8 +2438,9 @@
   ShareTarget target =
       DiscoverShareTarget(transfer_callback, discovery_callback);
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kError,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kError,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
 
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
 }
@@ -2422,8 +2459,9 @@
                          TransferMetadata::Status::kFailed},
                         run_loop.QuitClosure());
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   run_loop.Run();
 
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
@@ -2447,8 +2485,9 @@
                                                               kToken);
   fake_nearby_connections_manager_->set_nearby_connection(&connection_);
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   run_loop.Run();
 
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
@@ -2473,8 +2512,9 @@
                                                               kToken);
   fake_nearby_connections_manager_->set_nearby_connection(&connection_);
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   run_loop.Run();
 
   service_->UnregisterSendSurface(&transfer_callback, &discovery_callback);
@@ -2493,8 +2533,9 @@
                          TransferMetadata::Status::kAwaitingRemoteAcceptance},
                         introduction_run_loop.QuitClosure());
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   introduction_run_loop.Run();
 
   // Verify data sent to the remote device so far.
@@ -2533,7 +2574,7 @@
                         introduction_run_loop.QuitClosure());
 
   EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendFiles(target, {path}));
+            service_->SendAttachments(target, CreateFileAttachments({path})));
   introduction_run_loop.Run();
 
   // Verify data sent to the remote device so far.
@@ -2572,8 +2613,9 @@
                          TransferMetadata::Status::kAwaitingRemoteAcceptance},
                         introduction_run_loop.QuitClosure());
 
-  EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendText(target, kTextPayload));
+  EXPECT_EQ(
+      NearbySharingServiceImpl::StatusCodes::kOk,
+      service_->SendAttachments(target, CreateTextAttachments({kTextPayload})));
   introduction_run_loop.Run();
 
   // Verify data sent to the remote device so far.
@@ -2647,7 +2689,7 @@
                         introduction_run_loop.QuitClosure());
 
   EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
-            service_->SendFiles(target, {path}));
+            service_->SendAttachments(target, CreateFileAttachments({path})));
   introduction_run_loop.Run();
 
   // Verify data sent to the remote device so far.
diff --git a/chrome/browser/nearby_sharing/payload_tracker_unittest.cc b/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
index 97cd0ec..8deb5eac 100644
--- a/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
+++ b/chrome/browser/nearby_sharing/payload_tracker_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/files/file_path.h"
 #include "base/test/mock_callback.h"
 #include "chrome/browser/nearby_sharing/constants.h"
 #include "chrome/browser/nearby_sharing/transfer_metadata_builder.h"
@@ -37,10 +38,8 @@
 
   void SetUp() override {
     for (int i = 0; i < kAttachmentCount / 2; i++) {
-      FileAttachment file(/*file_name=*/"file.jpg",
-                          FileAttachment::Type::kImage, kTotalSize,
-                          /*file_path=*/base::nullopt,
-                          /*mime_type=*/"example");
+      FileAttachment file(base::FilePath(FILE_PATH_LITERAL("file.jpg")));
+      file.set_size(kTotalSize);
 
       AttachmentInfo info;
       info.payload_id = i;
diff --git a/chrome/browser/nearby_sharing/sharesheet/nearby_share_action.cc b/chrome/browser/nearby_sharing/sharesheet/nearby_share_action.cc
index 45727053..f8d620a 100644
--- a/chrome/browser/nearby_sharing/sharesheet/nearby_share_action.cc
+++ b/chrome/browser/nearby_sharing/sharesheet/nearby_share_action.cc
@@ -4,18 +4,66 @@
 
 #include "chrome/browser/nearby_sharing/sharesheet/nearby_share_action.h"
 
+#include <memory>
+#include <vector>
+
+#include "base/files/file_path.h"
 #include "base/logging.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/chromeos/file_manager/app_id.h"
+#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
+#include "chrome/browser/nearby_sharing/attachment.h"
+#include "chrome/browser/nearby_sharing/file_attachment.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sharesheet/sharesheet_types.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "storage/browser/file_system/file_system_context.h"
+#include "storage/browser/file_system/file_system_url.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/controls/webview/webview.h"
+#include "url/gurl.h"
+
+namespace {
+
+std::vector<base::FilePath> ResolveFileUrls(
+    Profile* profile,
+    const std::vector<GURL>& file_urls) {
+  std::vector<base::FilePath> file_paths;
+  storage::FileSystemContext* fs_context =
+      file_manager::util::GetFileSystemContextForExtensionId(
+          profile, file_manager::kFileManagerAppId);
+  for (const auto& file_url : file_urls) {
+    storage::FileSystemURL fs_url = fs_context->CrackURL(file_url);
+    file_paths.push_back(fs_url.path());
+  }
+  return file_paths;
+}
+
+std::vector<std::unique_ptr<Attachment>> CreateAttachmentsFromIntent(
+    Profile* profile,
+    apps::mojom::IntentPtr intent) {
+  std::vector<std::unique_ptr<Attachment>> attachments;
+
+  // TODO(knollr): Support other attachment types.
+  if (intent->file_urls) {
+    std::vector<base::FilePath> file_paths =
+        ResolveFileUrls(profile, *intent->file_urls);
+    for (auto& file_path : file_paths) {
+      attachments.push_back(
+          std::make_unique<FileAttachment>(std::move(file_path)));
+    }
+  }
+
+  return attachments;
+}
+
+}  // namespace
 
 namespace {
 
@@ -37,7 +85,8 @@
 }
 
 const gfx::ImageSkia NearbyShareAction::GetActionIcon() {
-  return gfx::CreateVectorIcon(kNearbyShareIcon);
+  return gfx::CreateVectorIcon(kNearbyShareIcon, sharesheet::kIconSize,
+                               gfx::kPlaceholderColor);
 }
 
 void NearbyShareAction::LaunchAction(
@@ -70,7 +119,8 @@
   DCHECK(nearby_ui_ != nullptr);
 
   nearby_ui_->AddObserver(this);
-  nearby_ui_->SetShareIntent(std::move(intent));
+  nearby_ui_->SetAttachments(
+      CreateAttachmentsFromIntent(profile, std::move(intent)));
 }
 
 void NearbyShareAction::OnClose() {
diff --git a/chrome/browser/nearby_sharing/text_attachment.cc b/chrome/browser/nearby_sharing/text_attachment.cc
index 65cbeb7..edac51a4 100644
--- a/chrome/browser/nearby_sharing/text_attachment.cc
+++ b/chrome/browser/nearby_sharing/text_attachment.cc
@@ -6,6 +6,7 @@
 #include <utility>
 
 #include "base/strings/strcat.h"
+#include "chrome/browser/nearby_sharing/share_target.h"
 #include "chrome/browser/nearby_sharing/text_attachment.h"
 #include "url/gurl.h"
 
@@ -109,6 +110,14 @@
 
 TextAttachment::TextAttachment(const TextAttachment&) = default;
 
+TextAttachment::TextAttachment(TextAttachment&&) = default;
+
 TextAttachment& TextAttachment::operator=(const TextAttachment&) = default;
 
+TextAttachment& TextAttachment::operator=(TextAttachment&&) = default;
+
 TextAttachment::~TextAttachment() = default;
+
+void TextAttachment::MoveToShareTarget(ShareTarget& share_target) {
+  share_target.text_attachments.push_back(std::move(*this));
+}
diff --git a/chrome/browser/nearby_sharing/text_attachment.h b/chrome/browser/nearby_sharing/text_attachment.h
index c5f7bf9b..62af31b 100644
--- a/chrome/browser/nearby_sharing/text_attachment.h
+++ b/chrome/browser/nearby_sharing/text_attachment.h
@@ -19,13 +19,18 @@
   TextAttachment(Type type, std::string text_body);
   TextAttachment(int64_t id, Type type, std::string text_title, int64_t size);
   TextAttachment(const TextAttachment&);
+  TextAttachment(TextAttachment&&);
   TextAttachment& operator=(const TextAttachment&);
+  TextAttachment& operator=(TextAttachment&&);
   ~TextAttachment() override;
 
   const std::string& text_body() const { return text_body_; }
   const std::string& text_title() const { return text_title_; }
   Type type() const { return type_; }
 
+  // Attachment:
+  void MoveToShareTarget(ShareTarget& share_target) override;
+
  private:
   Type type_;
   std::string text_title_;
diff --git a/chrome/browser/password_check/android/password_check_manager.cc b/chrome/browser/password_check/android/password_check_manager.cc
index eef97491..0b16fed0 100644
--- a/chrome/browser/password_check/android/password_check_manager.cc
+++ b/chrome/browser/password_check/android/password_check_manager.cc
@@ -206,9 +206,11 @@
 void PasswordCheckManager::OnCredentialDone(
     const password_manager::LeakCheckCredential& credential,
     password_manager::IsLeaked is_leaked) {
-  progress_->OnProcessed(credential);
-  observer_->OnPasswordCheckProgressChanged(progress_->already_processed(),
-                                            progress_->remaining_in_queue());
+  if (progress_) {
+    progress_->OnProcessed(credential);
+    observer_->OnPasswordCheckProgressChanged(progress_->already_processed(),
+                                              progress_->remaining_in_queue());
+  }
   if (is_leaked) {
     // TODO(crbug.com/1092444): Trigger single-credential update.
     compromised_credentials_manager_.SaveCompromisedCredential(credential);
diff --git a/chrome/browser/password_check/android/password_check_manager_unittest.cc b/chrome/browser/password_check/android/password_check_manager_unittest.cc
index 76d7e3a..a29dd71 100644
--- a/chrome/browser/password_check/android/password_check_manager_unittest.cc
+++ b/chrome/browser/password_check/android/password_check_manager_unittest.cc
@@ -436,3 +436,18 @@
                                                 base::ASCIIToUTF16(kPassword1)),
           password_manager::IsLeaked(false));
 }
+
+TEST_F(PasswordCheckManagerTest, DoesntUpdateNonExistingProgress) {
+  InitializeManager();
+  store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+  store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1, kPassword1));
+  store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2));
+  RunUntilIdle();
+
+  EXPECT_CALL(mock_observer(), OnPasswordCheckProgressChanged).Times(0);
+  static_cast<password_manager::BulkLeakCheckDelegateInterface*>(service())
+      ->OnFinishedCredential(
+          password_manager::LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+                                                base::ASCIIToUTF16(kPassword1)),
+          password_manager::IsLeaked(false));
+}
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 57f1f6b..1821b042 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -786,8 +786,7 @@
   return std::string();
 }
 
-#if defined(ON_FOCUS_PING_ENABLED) || \
-    defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
 safe_browsing::PasswordProtectionService*
 ChromePasswordManagerClient::GetPasswordProtectionService() const {
   return safe_browsing::ChromePasswordProtectionService::
@@ -809,7 +808,7 @@
 }
 #endif  // defined(ON_FOCUS_PING_ENABLED)
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void ChromePasswordManagerClient::CheckProtectedPasswordEntry(
     PasswordType password_type,
     const std::string& username,
@@ -825,9 +824,9 @@
       web_contents(), web_contents()->GetLastCommittedURL(), username,
       password_type, matching_reused_credentials, password_field_exists);
 }
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 void ChromePasswordManagerClient::LogPasswordReuseDetectedEvent() {
   safe_browsing::PasswordProtectionService* pps =
       GetPasswordProtectionService();
@@ -835,7 +834,7 @@
     pps->MaybeLogPasswordReuseDetectedEvent(web_contents());
   }
 }
-#endif  // defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#endif  // defined(PASSWORD_REUSE_WARNING_ENABLED)
 
 ukm::SourceId ChromePasswordManagerClient::GetUkmSourceId() {
   return ukm::GetSourceIdForWebContentsDocument(web_contents());
@@ -1059,25 +1058,25 @@
 }
 void ChromePasswordManagerClient::OnImeTextCommittedEvent(
     const base::string16& text_str) {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   password_reuse_detection_manager_.OnKeyPressedCommitted(text_str);
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 }
 
 void ChromePasswordManagerClient::OnImeSetComposingTextEvent(
     const base::string16& text_str) {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   last_composing_text_ = text_str;
   password_reuse_detection_manager_.OnKeyPressedUncommitted(
       last_composing_text_);
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 }
 
 void ChromePasswordManagerClient::OnImeFinishComposingTextEvent() {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   password_reuse_detection_manager_.OnKeyPressedCommitted(last_composing_text_);
   last_composing_text_.clear();
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 }
 #endif  // defined(OS_ANDROID)
 
@@ -1164,7 +1163,7 @@
           profile_->GetPrefs(),
           ProfileSyncServiceFactory::GetForProfile(profile_)),
       httpauth_manager_(this),
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
       password_reuse_detection_manager_(this),
 #endif
       driver_factory_(nullptr),
@@ -1226,9 +1225,9 @@
   // requests.
   content_credential_manager_.DisconnectBinding();
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   password_reuse_detection_manager_.DidNavigateMainFrame(GetLastCommittedURL());
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 
 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
   // TODO(https://crbug.com/1104919): Remove this logging.
@@ -1324,7 +1323,7 @@
     const blink::WebInputEvent& event) {
 #if defined(OS_ANDROID)
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // On Android, key down events are triggered if a user types in through a
   // number bar on Android keyboard. If text is typed in through other parts of
   // Android keyboard, ImeTextCommittedEvent is triggered instead.
@@ -1333,7 +1332,7 @@
   const blink::WebKeyboardEvent& key_event =
       static_cast<const blink::WebKeyboardEvent&>(event);
   password_reuse_detection_manager_.OnKeyPressedCommitted(key_event.text);
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 
 #else   // !defined(OS_ANDROID)
   if (event.GetType() != blink::WebInputEvent::Type::kChar)
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index d7296bce..6fcd28b 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -173,8 +173,7 @@
   void AnnotateNavigationEntry(bool has_password_field) override;
   std::string GetPageLanguage() const override;
 
-#if defined(ON_FOCUS_PING_ENABLED) || \
-    defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
   safe_browsing::PasswordProtectionService* GetPasswordProtectionService()
       const override;
 #endif
@@ -184,7 +183,7 @@
                                    const GURL& frame_url) override;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   void CheckProtectedPasswordEntry(
       password_manager::metrics_util::PasswordType reused_password_type,
       const std::string& username,
@@ -193,7 +192,7 @@
       bool password_field_exists) override;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   void LogPasswordReuseDetectedEvent() override;
 #endif
 
@@ -335,7 +334,7 @@
   password_manager::PasswordFeatureManagerImpl password_feature_manager_;
   password_manager::HttpAuthManagerImpl httpauth_manager_;
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   password_manager::PasswordReuseDetectionManager
       password_reuse_detection_manager_;
 #endif
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc
index a60f569c..11534a4 100644
--- a/chrome/browser/password_manager/password_store_factory.cc
+++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -46,7 +46,7 @@
 #include "ui/base/ui_base_features.h"
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "chrome/browser/password_manager/password_store_signin_notifier_impl.h"
 #endif
 
@@ -59,7 +59,7 @@
     kMigrationToLoginDBNotAttempted = PasswordStoreX::NOT_ATTEMPTED;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 std::string GetSyncUsername(Profile* profile) {
   auto* identity_manager =
       IdentityManagerFactory::GetForProfileIfExists(profile);
@@ -68,7 +68,7 @@
 }
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 bool IsSignedIn(Profile* profile) {
   auto* identity_manager =
       IdentityManagerFactory::GetForProfileIfExists(profile);
@@ -121,7 +121,7 @@
           "PasswordStore",
           BrowserContextDependencyManager::GetInstance()) {
   DependsOn(WebDataServiceFactory::GetInstance());
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // TODO(crbug.com/715987). Remove when PasswordReuseDetector is decoupled
   // from PasswordStore.
   DependsOn(IdentityManagerFactory::GetInstance());
@@ -172,7 +172,7 @@
     return nullptr;
   }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Prepare password hash data for reuse detection.
   ps->PreparePasswordHashData(GetSyncUsername(profile), IsSignedIn(profile));
 #endif
diff --git a/chrome/browser/payments/android/payment_app_service_bridge.cc b/chrome/browser/payments/android/payment_app_service_bridge.cc
index 11ed9fd..ea6fc8d 100644
--- a/chrome/browser/payments/android/payment_app_service_bridge.cc
+++ b/chrome/browser/payments/android/payment_app_service_bridge.cc
@@ -331,4 +331,8 @@
   PaymentAppServiceBridgeStorage::GetInstance()->Remove(this);
 }
 
+void PaymentAppServiceBridge::SetCanMakePaymentEvenWithoutApps() {
+  NOTREACHED();
+}
+
 }  // namespace payments
diff --git a/chrome/browser/payments/android/payment_app_service_bridge.h b/chrome/browser/payments/android/payment_app_service_bridge.h
index c4b7e7e..d954ebd 100644
--- a/chrome/browser/payments/android/payment_app_service_bridge.h
+++ b/chrome/browser/payments/android/payment_app_service_bridge.h
@@ -84,6 +84,7 @@
   void OnPaymentAppCreationError(const std::string& error_message) override;
   bool SkipCreatingNativePaymentApps() const override;
   void OnDoneCreatingPaymentApps() override;
+  void SetCanMakePaymentEvenWithoutApps() override;
 
  private:
   // Prevents direct instantiation. Callers should use Create() instead.
diff --git a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
index 5b46baa..378e1ab 100644
--- a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
+++ b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
@@ -2,10 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
 #include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_data_service_factory.h"
 #include "chrome/test/payments/payment_request_platform_browsertest_base.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/payments/content/payment_manifest_web_data_service.h"
+#include "components/payments/core/secure_payment_confirmation_instrument.h"
+#include "components/webdata/common/web_data_service_consumer.h"
 #include "content/public/browser/authenticator_environment.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
@@ -21,8 +35,8 @@
     "  supportedMethods: 'secure-payment-confirmation',"
     "  data: {"
     "    action: 'authenticate',"
-    "    instrumentId: 'x',"
-    "    networkData: Uint8Array.from('x', c => c.charCodeAt(0)),"
+    "    credentialIds: [Uint8Array.from('cred', c => c.charCodeAt(0))],"
+    "    networkData: Uint8Array.from('network_data', c => c.charCodeAt(0)),"
     "    timeout: 60000,"
     "    fallbackUrl: 'https://fallback.example/url'"
     "}}]";
@@ -59,13 +73,25 @@
 #endif
 
 class SecurePaymentConfirmationTest
-    : public PaymentRequestPlatformBrowserTestBase {
+    : public PaymentRequestPlatformBrowserTestBase,
+      public WebDataServiceConsumer {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     PaymentRequestPlatformBrowserTestBase::SetUpCommandLine(command_line);
     command_line->AppendSwitch(
         switches::kEnableExperimentalWebPlatformFeatures);
   }
+
+  void OnWebDataServiceRequestDone(
+      WebDataServiceBase::Handle h,
+      std::unique_ptr<WDTypedResult> result) override {
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ(BOOL_RESULT, result->GetType());
+    EXPECT_TRUE(static_cast<WDResult<bool>*>(result.get())->GetValue());
+    databse_write_responded_ = true;
+  }
+
+  bool databse_write_responded_ = false;
 };
 
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationTest, NoAuthenticator) {
@@ -82,14 +108,39 @@
 #if defined(OS_ANDROID)
 // TODO(https://crbug.com/1110320): Implement SetHasAuthenticator() for Android,
 // so this behavior can be tested on Android as well.
+#define MAYBE_NoInstrumentInStorage DISABLED_NoInstrumentInStorage
 #define MAYBE_PaymentSheetShowsApp DISABLED_PaymentSheetShowsApp
 #else
+#define MAYBE_NoInstrumentInStorage NoInstrumentInStorage
 #define MAYBE_PaymentSheetShowsApp PaymentSheetShowsApp
 #endif  // OS_ANDROID
+
+IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationTest,
+                       MAYBE_NoInstrumentInStorage) {
+  test_controller()->SetHasAuthenticator(true);
+  NavigateTo("a.com", "/payment_handler_status.html");
+
+  // EvalJs waits for JavaScript promise to resolve.
+  EXPECT_EQ(
+      "The payment method \"secure-payment-confirmation\" is not supported.",
+      content::EvalJs(GetActiveWebContents(),
+                      getInvokePaymentRequestSnippet()));
+}
+
 IN_PROC_BROWSER_TEST_F(SecurePaymentConfirmationTest,
                        MAYBE_PaymentSheetShowsApp) {
   test_controller()->SetHasAuthenticator(true);
   NavigateTo("a.com", "/payment_handler_status.html");
+  std::vector<uint8_t> credential_id = {'c', 'r', 'e', 'd'};
+  std::vector<uint8_t> icon = {0, 1, 2, 3};
+  WebDataServiceFactory::GetPaymentManifestWebDataForProfile(
+      Profile::FromBrowserContext(GetActiveWebContents()->GetBrowserContext()),
+      ServiceAccessType::EXPLICIT_ACCESS)
+      ->AddSecurePaymentConfirmationInstrument(
+          std::make_unique<SecurePaymentConfirmationInstrument>(
+              std::move(credential_id), "relying-party.example",
+              base::ASCIIToUTF16("Stub label"), std::move(icon)),
+          /*consumer=*/this);
   ResetEventWaiterForSingleEvent(TestEvent::kAppListReady);
 
   // ExecJs starts executing JavaScript and immediately returns, not waiting for
@@ -98,6 +149,7 @@
                               getInvokePaymentRequestSnippet()));
 
   WaitForObservedEvent();
+  EXPECT_TRUE(databse_write_responded_);
   ASSERT_FALSE(test_controller()->app_descriptions().empty());
   EXPECT_EQ(1u, test_controller()->app_descriptions().size());
   EXPECT_EQ("Stub label", test_controller()->app_descriptions().front().label);
diff --git a/chrome/browser/profiles/profile_activity_metrics_recorder.cc b/chrome/browser/profiles/profile_activity_metrics_recorder.cc
index fac55348..0e0b318 100644
--- a/chrome/browser/profiles/profile_activity_metrics_recorder.cc
+++ b/chrome/browser/profiles/profile_activity_metrics_recorder.cc
@@ -71,6 +71,13 @@
   }
 }
 
+void RecordProfileSwitch() {
+  int profiles_count =
+      g_browser_process->profile_manager()->GetNumberOfProfiles();
+  UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfProfilesAtProfileSwitch",
+                           profiles_count);
+}
+
 void RecordUserAction(const Profile* profile) {
   if (!profile)
     return;
@@ -124,32 +131,37 @@
   RecordBrowserActivation(active_profile);
   RecordAccountMetrics(active_profile);
 
-  if (last_active_profile_ != active_profile) {
-    // No-op, if starting a new session (|last_active_profile_| is nullptr).
+  if (running_session_profile_ != active_profile) {
+    // No-op, if starting a new session (|running_session_profile_| is nullptr).
     RecordProfileSessionDuration(
-        last_active_profile_, base::TimeTicks::Now() - profile_session_start_);
+        running_session_profile_,
+        base::TimeTicks::Now() - running_session_start_);
 
-    last_active_profile_ = active_profile;
-    profile_session_start_ = base::TimeTicks::Now();
+    running_session_profile_ = active_profile;
+    running_session_start_ = base::TimeTicks::Now();
     profile_observer_.RemoveAll();
-    profile_observer_.Add(last_active_profile_);
+    profile_observer_.Add(running_session_profile_);
 
-    // Record state at startup (when last_profile_session_end_ is 0) and
-    // whenever the user starts browsing after a longer time of inactivity. Do
-    // it asynchronously because active_time of the just activated profile is
-    // also updated from OnBrowserSetLastActive() in another BrowserListObserver
-    // and we have no guarantee if this happens before or after this function
-    // call.
-    if (last_profile_session_end_.is_null() ||
-        (profile_session_start_ - last_profile_session_end_ >
-         kLongTimeOfInactivity)) {
+    // Record state at startup (when |last_session_end_| is 0) and whenever the
+    // user starts browsing after a longer time of inactivity. Do it
+    // asynchronously because active_time of the just activated profile is also
+    // updated from OnBrowserSetLastActive() in another BrowserListObserver and
+    // we have no guarantee if this happens before or after this function call.
+    if (last_session_end_.is_null() ||
+        (running_session_start_ - last_session_end_ > kLongTimeOfInactivity)) {
       base::SequencedTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(&RecordProfilesState));
     }
   }
 
+  if (last_active_profile_ != active_profile) {
+    if (last_active_profile_ != nullptr)
+      RecordProfileSwitch();
+    last_active_profile_ = active_profile;
+  }
+
   // This browsing session is still lasting.
-  last_profile_session_end_ = base::TimeTicks::Now();
+  last_session_end_ = base::TimeTicks::Now();
 }
 
 void ProfileActivityMetricsRecorder::OnSessionEnded(
@@ -157,21 +169,21 @@
     base::TimeTicks session_end) {
   // If this call is emitted after OnProfileWillBeDestroyed, return
   // early. We already logged the session duration there.
-  if (!last_active_profile_)
+  if (!running_session_profile_)
     return;
 
   // |session_length| can't be used here because it was measured across all
   // profiles.
-  RecordProfileSessionDuration(last_active_profile_,
-                               session_end - profile_session_start_);
-  profile_observer_.Remove(last_active_profile_);
-  last_active_profile_ = nullptr;
-  last_profile_session_end_ = base::TimeTicks::Now();
+  RecordProfileSessionDuration(running_session_profile_,
+                               session_end - running_session_start_);
+  profile_observer_.Remove(running_session_profile_);
+  running_session_profile_ = nullptr;
+  last_session_end_ = base::TimeTicks::Now();
 }
 
 void ProfileActivityMetricsRecorder::OnProfileWillBeDestroyed(
     Profile* profile) {
-  DCHECK_EQ(profile, last_active_profile_);
+  DCHECK_EQ(profile, running_session_profile_);
 
   // The profile may be deleted without an OnSessionEnded call if, for
   // example, the browser shuts down.
@@ -179,9 +191,10 @@
   // TODO(crbug.com/1096145): explore having
   // DesktopSessionDurationTracker call OnSessionEnded() when the
   // profile is destroyed. Remove this workaround if this is done.
-  profile_observer_.Remove(last_active_profile_);
+  profile_observer_.Remove(running_session_profile_);
+  running_session_profile_ = nullptr;
   last_active_profile_ = nullptr;
-  last_profile_session_end_ = base::TimeTicks::Now();
+  last_session_end_ = base::TimeTicks::Now();
 }
 
 ProfileActivityMetricsRecorder::ProfileActivityMetricsRecorder() {
@@ -200,5 +213,5 @@
 
 void ProfileActivityMetricsRecorder::OnUserAction(const std::string& action,
                                                   base::TimeTicks action_time) {
-  RecordUserAction(last_active_profile_);
+  RecordUserAction(running_session_profile_);
 }
diff --git a/chrome/browser/profiles/profile_activity_metrics_recorder.h b/chrome/browser/profiles/profile_activity_metrics_recorder.h
index 96c3ff20..cbcbc0f 100644
--- a/chrome/browser/profiles/profile_activity_metrics_recorder.h
+++ b/chrome/browser/profiles/profile_activity_metrics_recorder.h
@@ -50,9 +50,14 @@
 
   void OnUserAction(const std::string& action, base::TimeTicks action_time);
 
+  // The profile of the last active window.
   Profile* last_active_profile_ = nullptr;
-  base::TimeTicks profile_session_start_;
-  base::TimeTicks last_profile_session_end_;
+
+  // Profile of the currently running session, if there is any. Reset after
+  // inactivity.
+  Profile* running_session_profile_ = nullptr;
+  base::TimeTicks running_session_start_;
+  base::TimeTicks last_session_end_;
 
   base::ActionCallback action_callback_;
 
diff --git a/chrome/browser/profiles/profile_activity_metrics_recorder_unittest.cc b/chrome/browser/profiles/profile_activity_metrics_recorder_unittest.cc
index e216a88..9b283a7 100644
--- a/chrome/browser/profiles/profile_activity_metrics_recorder_unittest.cc
+++ b/chrome/browser/profiles/profile_activity_metrics_recorder_unittest.cc
@@ -111,6 +111,8 @@
   histograms()->ExpectBucketCount("Profile.BrowserActive.PerProfile",
                                   /*bucket=*/1, /*count=*/1);
   SimulateUserActionAndExpectRecording(/*bucket=*/1);
+  histograms()->ExpectTotalCount("Profile.NumberOfProfilesAtProfileSwitch",
+                                 /*count=*/0);
 
   // Activate an incognito browser instance of the guest profile.
   // Note: Creating a non-incognito guest browser instance is not possible.
@@ -118,6 +120,8 @@
   histograms()->ExpectBucketCount("Profile.BrowserActive.PerProfile",
                                   /*bucket=*/0, /*count=*/1);
   SimulateUserActionAndExpectRecording(/*bucket=*/0);
+  histograms()->ExpectUniqueSample("Profile.NumberOfProfilesAtProfileSwitch",
+                                   /*bucket=*/1, /*count=*/1);
 
   histograms()->ExpectTotalCount("Profile.BrowserActive.PerProfile", 2);
 }
@@ -135,6 +139,8 @@
                                   /*bucket=*/1, /*count=*/2);
 
   histograms()->ExpectTotalCount("Profile.BrowserActive.PerProfile", 2);
+  histograms()->ExpectTotalCount("Profile.NumberOfProfilesAtProfileSwitch",
+                                 /*count=*/0);
 }
 
 TEST_F(ProfileActivityMetricsRecorderTest, MultipleProfiles) {
@@ -160,6 +166,9 @@
   histograms()->ExpectBucketCount("Profile.BrowserActive.PerProfile",
                                   /*bucket=*/1, /*count=*/2);
   SimulateUserActionAndExpectRecording(/*bucket=*/1);
+  // No profile switch, so far.
+  histograms()->ExpectTotalCount("Profile.NumberOfProfilesAtProfileSwitch",
+                                 /*count=*/0);
 
   // Profile 1: Session lasts 2 minutes.
   task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(2));
@@ -170,6 +179,8 @@
   histograms()->ExpectBucketCount("Profile.BrowserActive.PerProfile",
                                   /*bucket=*/2, /*count=*/1);
   SimulateUserActionAndExpectRecording(/*bucket=*/2);
+  histograms()->ExpectUniqueSample("Profile.NumberOfProfilesAtProfileSwitch",
+                                   /*bucket=*/3, /*count=*/1);
 
   // Profile 1: Session ended. The duration(2 minutes) is recorded.
   histograms()->ExpectBucketCount("Profile.SessionDuration.PerProfile",
@@ -184,6 +195,8 @@
   histograms()->ExpectBucketCount("Profile.BrowserActive.PerProfile",
                                   /*bucket=*/3, /*count=*/1);
   SimulateUserActionAndExpectRecording(/*bucket=*/3);
+  histograms()->ExpectUniqueSample("Profile.NumberOfProfilesAtProfileSwitch",
+                                   /*bucket=*/3, /*count=*/2);
 
   // Profile 3: Session ended. The duration(2 minutes) is recorded.
   histograms()->ExpectBucketCount("Profile.SessionDuration.PerProfile",
diff --git a/chrome/browser/profiles/profile_avatar_icon_util.cc b/chrome/browser/profiles/profile_avatar_icon_util.cc
index 23758537..57cfedd8 100644
--- a/chrome/browser/profiles/profile_avatar_icon_util.cc
+++ b/chrome/browser/profiles/profile_avatar_icon_util.cc
@@ -623,7 +623,7 @@
   gfx::ImageSkia icon_with_background(
       std::make_unique<ImageWithBackgroundSource>(icon_without_background,
                                                   fill_color),
-      size);
+      gfx::Size(size, size));
   return gfx::Image(icon_with_background);
 }
 
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index 9d12f7f..d0b71412 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -1682,5 +1682,12 @@
     this.clickPrimaryActionButtonForTesting_ = false;
     button.click();
   },
+
+  /**
+   * Called when focus is returned.
+   */
+  onFocusReturned() {
+    this.focusActiveFrame_();
+  },
 });
 })();
diff --git a/chrome/browser/resources/nearby_share/app.html b/chrome/browser/resources/nearby_share/app.html
index d671fcd..d84118ca 100644
--- a/chrome/browser/resources/nearby_share/app.html
+++ b/chrome/browser/resources/nearby_share/app.html
@@ -1,12 +1,12 @@
 <cr-view-manager id="viewManager">
   <nearby-confirmation-page id="[[Page.CONFIRMATION]]" slot="view"
       confirmation-manager="[[confirmationManager_]]"
-      confirmation-token="[[confirmationToken_]]"
+      transfer-update-listener="[[transferUpdateListener_]]"
       share-target="[[selectedShareTarget_]]">
   </nearby-confirmation-page>
   <nearby-discovery-page id="[[Page.DISCOVERY]]" slot="view"
       confirmation-manager="{{confirmationManager_}}"
-      confirmation-token="{{confirmationToken_}}"
+      transfer-update-listener="{{transferUpdateListener_}}"
       selected-share-target="{{selectedShareTarget_}}">
   </nearby-discovery-page>
   <nearby-onboarding-page id="[[Page.ONBOARDING]]" settings="{{settings}}"
diff --git a/chrome/browser/resources/nearby_share/app.js b/chrome/browser/resources/nearby_share/app.js
index c2f3ca4..bd44d86d 100644
--- a/chrome/browser/resources/nearby_share/app.js
+++ b/chrome/browser/resources/nearby_share/app.js
@@ -53,11 +53,11 @@
     /**
      * Set by the nearby-discovery-page component when switching to the
      * nearby-confirmation-page.
-     * @type {?String}
+     * @type {?nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
      * @private
      */
-    confirmationToken_: {
-      type: String,
+    transferUpdateListener_: {
+      type: Object,
       value: null,
     },
 
diff --git a/chrome/browser/resources/nearby_share/nearby_confirmation_page.html b/chrome/browser/resources/nearby_share/nearby_confirmation_page.html
index 6ff74f3..08080b79 100644
--- a/chrome/browser/resources/nearby_share/nearby_confirmation_page.html
+++ b/chrome/browser/resources/nearby_share/nearby_confirmation_page.html
@@ -78,7 +78,9 @@
   <div id="process-row">
     <nearby-preview title="Doggo.jpg"></nearby-preview>
     <div id="confirmation-token">
-      [[i18n('secureConnectionId', confirmationToken)]]
+      <template is="dom-if" if="[[confirmationToken_]]">
+        [[i18n('secureConnectionId', confirmationToken_)]]
+      </template>
     </div>
     <nearby-progress share-target="[[shareTarget]]"></nearby-progress>
   </div>
@@ -93,11 +95,21 @@
   </cr-checkbox>
 
   <div id="actions">
-    <cr-button id="cancel-button" class="cancel-button" on-click="onCancelTap_">
-      Cancel
-    </cr-button>
-    <cr-button id="accept-button" class="action-button" on-click="onAcceptTap_">
-      Confirm
-    </cr-button>
+    <template is="dom-if" if="[[needsConfirmation_]]">
+      <cr-button id="reject-button" class="cancel-button"
+          on-click="onRejectTap_">
+        Reject
+      </cr-button>
+      <cr-button id="accept-button" class="action-button"
+          on-click="onAcceptTap_">
+        Confirm
+      </cr-button>
+    </template>
+    <template is="dom-if" if="[[!needsConfirmation_]]">
+      <cr-button id="cancel-button" class="action-button"
+          on-click="onCancelTap_">
+        Cancel
+      </cr-button>
+    </template>
   </div>
 </div>
diff --git a/chrome/browser/resources/nearby_share/nearby_confirmation_page.js b/chrome/browser/resources/nearby_share/nearby_confirmation_page.js
index 0b9ee9a4..cefed54 100644
--- a/chrome/browser/resources/nearby_share/nearby_confirmation_page.js
+++ b/chrome/browser/resources/nearby_share/nearby_confirmation_page.js
@@ -21,6 +21,32 @@
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+/** @implements {nearbyShare.mojom.TransferUpdateListenerInterface} */
+class TransferUpdateListener {
+  /**
+   * @param {!NearbyConfirmationPageElement} page
+   * @param {!nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
+   *     transferUpdateListener
+   */
+  constructor(page, transferUpdateListener) {
+    this.page_ = page;
+    this.transferUpdateListenerReceiver_ =
+        new nearbyShare.mojom.TransferUpdateListenerReceiver(this);
+    this.transferUpdateListenerReceiver_.$.bindHandle(
+        transferUpdateListener.handle);
+  }
+
+  /**
+   * @param {!nearbyShare.mojom.TransferStatus} status The status update.
+   * @param {?string} token The optional token to show to the user.
+   * @private
+   * @override
+   */
+  onTransferUpdate(status, token) {
+    this.page_.onTransferUpdate(status, token);
+  }
+}
+
 Polymer({
   is: 'nearby-confirmation-page',
 
@@ -41,14 +67,15 @@
     },
 
     /**
-     * Token to show to the user to confirm the selected share target. Expected
-     * to start as null, then change to a valid object before this component is
-     * shown.
-     * @type {?string}
+     * TransferUpdateListener interface for the currently selected share target.
+     * Expected to start as null, then change to a valid object before this
+     * component is shown.
+     * @type {?nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
      */
-    confirmationToken: {
-      type: String,
+    transferUpdateListener: {
+      type: Object,
       value: null,
+      observer: 'onTransferUpdateListenerChanged_'
     },
 
     /**
@@ -60,18 +87,85 @@
       type: Object,
       value: null,
     },
+
+    /**
+     * Token to show to the user to confirm the selected share target. Expected
+     * to start as null, then change to a valid object via updates from the
+     * transferUpdateListener.
+     * @private {?string}
+     */
+    confirmationToken_: {
+      type: String,
+      value: null,
+    },
+
+    /**
+     * Whether the user needs to confirm this transfer on the local device.
+     * @private
+     * */
+    needsConfirmation_: {
+      type: Boolean,
+      value: false,
+    },
+  },
+
+  /** @private {?TransferUpdateListener} */
+  transferUpdateListener_: null,
+
+  /**
+   * @param {?nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
+   *     transferUpdateListener
+   * @private
+   */
+  onTransferUpdateListenerChanged_(transferUpdateListener) {
+    if (!transferUpdateListener) {
+      return;
+    }
+
+    this.transferUpdateListener_ =
+        new TransferUpdateListener(this, transferUpdateListener);
+  },
+
+  /**
+   * @param {!nearbyShare.mojom.TransferStatus} status The status update.
+   * @param {?string} token The optional token to show to the user.
+   */
+  onTransferUpdate(status, token) {
+    if (token) {
+      this.confirmationToken_ = token;
+    }
+
+    switch (status) {
+      case nearbyShare.mojom.TransferStatus.kAwaitingLocalConfirmation:
+        this.needsConfirmation_ = true;
+        break;
+      case nearbyShare.mojom.TransferStatus.kAwaitingRemoteAcceptance:
+        this.needsConfirmation_ = false;
+        break;
+      case nearbyShare.mojom.TransferStatus.kInProgress:
+        this.fire('close');
+        break;
+    }
   },
 
   /** @private */
   onAcceptTap_() {
-    this.confirmationManager.accept().then(result => {
+    this.confirmationManager.accept().then(
+        result => {
+            // TODO(knollr): Show error if !result.success
+        });
+  },
+
+  /** @private */
+  onRejectTap_() {
+    this.confirmationManager.reject().then(result => {
       this.fire('close');
     });
   },
 
   /** @private */
   onCancelTap_() {
-    this.confirmationManager.reject().then(result => {
+    this.confirmationManager.cancel().then(result => {
       this.fire('close');
     });
   },
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.js b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
index e920da6..56c9504 100644
--- a/chrome/browser/resources/nearby_share/nearby_discovery_page.js
+++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
@@ -56,12 +56,12 @@
     },
 
     /**
-     * Token to show to the user to confirm the selected share target.
-     * @type {?string}
+     * TransferUpdateListener interface for the currently selected share target.
+     * @type {?nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
      */
-    confirmationToken: {
+    transferUpdateListener: {
       notify: true,
-      type: String,
+      type: Object,
       value: null,
     },
 
@@ -187,19 +187,16 @@
     getDiscoveryManager()
         .selectShareTarget(this.selectedShareTarget.id)
         .then(response => {
-          const {result, token, confirmationManager} = response;
+          const {result, transferUpdateListener, confirmationManager} =
+              response;
           if (result !== nearbyShare.mojom.SelectShareTargetResult.kOk) {
             // TODO(knollr): Show error.
             return;
           }
 
-          if (confirmationManager) {
-            this.confirmationManager = confirmationManager;
-            this.confirmationToken = token;
-            this.fire('change-page', {page: 'confirmation'});
-          } else {
-            this.fire('close');
-          }
+          this.confirmationManager = confirmationManager;
+          this.transferUpdateListener = transferUpdateListener;
+          this.fire('change-page', {page: 'confirmation'});
         });
   },
 
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 80ce647..3111f58d 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -71,7 +71,6 @@
     "appearance_page:closure_compile",
     "controls:closure_compile",
     "languages_page:closure_compile",
-    "nearby_share_page:closure_compile",
     "people_page:closure_compile",
     "prefs:closure_compile",
     "privacy_page:closure_compile",
@@ -157,7 +156,6 @@
     "controls:closure_compile_module",
     "downloads_page:closure_compile_module",
     "languages_page:closure_compile_module",
-    "nearby_share_page:closure_compile_module",
     "on_startup_page:closure_compile_module",
     "people_page:closure_compile_module",
     "prefs:closure_compile_module",
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index f500e43..da5bc370 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -200,6 +200,7 @@
     "internet_page:closure_compile",
     "localized_link:closure_compile",
     "multidevice_page:closure_compile",
+    "nearby_share_page:closure_compile",
     "os_a11y_page:closure_compile",
     "os_apps_page:closure_compile",
     "os_files_page:closure_compile",
@@ -296,6 +297,7 @@
     #"internet_page:closure_compile_module",
     "localized_link:closure_compile_module",
     "multidevice_page:closure_compile_module",
+    "nearby_share_page:closure_compile_module",
 
     #"os_a11y_page:closure_compile_module",
     "os_about_page:closure_compile_module",
@@ -433,6 +435,7 @@
     "internet_page:polymer3_elements",
     "localized_link:polymer3_elements",
     "multidevice_page:polymer3_elements",
+    "nearby_share_page:polymer3_elements",
     "os_a11y_page:polymer3_elements",
     "os_about_page:polymer3_elements",
     "os_apps_page:polymer3_elements",
@@ -464,7 +467,6 @@
     "..:settings_vars_css_module",
     "../../settings:settings_page_css_module",
     "../about_page:modulize",
-    "../nearby_share_page:polymer3_elements",
     "../prefs:modulize",
     "../prefs:prefs_module",
     "../settings_page:settings_animated_pages_module",
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.html
index dbc0995d..b6c5eff 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.html
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.html
@@ -12,11 +12,11 @@
 <link rel="import" href="../os_route.html">
 <link rel="import" href="../../router.html">
 <link rel="import" href="../../controls/password_prompt_dialog.html">
-<link rel="import" href="../../nearby_share_page/nearby_share_subpage.html">
 <link rel="import" href="../../settings_page/settings_animated_pages.html">
 <link rel="import" href="../../settings_page/settings_subpage.html">
 <link rel="import" href="../../prefs/prefs_behavior.html">
 <link rel="import" href="../../settings_shared_css.html">
+<link rel="import" href="../nearby_share_page/nearby_share_subpage.html">
 <link rel="import" href="../localized_link/localized_link.html">
 <link rel="import" href="../metrics_recorder.html">
 <link rel="import" href="multidevice_browser_proxy.html">
diff --git a/chrome/browser/resources/settings/nearby_share_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
similarity index 72%
rename from chrome/browser/resources/settings/nearby_share_page/BUILD.gn
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
index 56e0fea..41823ad 100644
--- a/chrome/browser/resources/settings/nearby_share_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
@@ -5,8 +5,8 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/polymer.gni")
 import("//ui/webui/resources/tools/js_modulizer.gni")
-import("../../nearby_share/shared/nearby_shared.gni")
-import("../settings.gni")
+import("../../../nearby_share/shared/nearby_shared.gni")
+import("../os_settings.gni")
 
 js_type_check("closure_compile") {
   deps = [
@@ -30,9 +30,9 @@
 js_library("nearby_share_data_usage_dialog") {
   deps = [
     ":types",
-    "../prefs",
-    "../prefs:prefs_behavior",
-    "../prefs:prefs_types",
+    "../../prefs",
+    "../../prefs:prefs_behavior",
+    "../../prefs:prefs_types",
     "//ui/webui/resources/cr_elements/cr_button:cr_button",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
     "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
@@ -43,9 +43,9 @@
 
 js_library("nearby_share_device_name_dialog") {
   deps = [
-    "../prefs",
-    "../prefs:prefs_behavior",
-    "../prefs:prefs_types",
+    "../../prefs",
+    "../../prefs:prefs_behavior",
+    "../../prefs:prefs_types",
     "//ui/webui/resources/cr_elements/cr_button:cr_button",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
     "//ui/webui/resources/cr_elements/cr_input:cr_input",
@@ -59,10 +59,10 @@
     ":nearby_share_data_usage_dialog",
     ":nearby_share_device_name_dialog",
     ":types",
-    "..:router",
-    "../prefs",
-    "../prefs:prefs_behavior",
-    "../prefs:prefs_types",
+    "../..:router",
+    "../../prefs",
+    "../../prefs:prefs_behavior",
+    "../../prefs:prefs_types",
     "//chrome/browser/resources/nearby_share/shared:nearby_onboarding_page",
     "//chrome/browser/resources/nearby_share/shared:nearby_share_settings_behavior",
     "//chrome/browser/resources/nearby_share/shared:nearby_visibility_page",
@@ -81,8 +81,8 @@
     ":nearby_share_data_usage_dialog_module",
     ":nearby_share_device_name_dialog_module",
     ":nearby_share_subpage_module",
-    "../controls:polymer3_elements",
-    "../prefs:polymer3_elements",
+    "../../controls:polymer3_elements",
+    "../../prefs:polymer3_elements",
   ]
 }
 
@@ -90,9 +90,9 @@
   is_polymer3 = true
 
   # TODO(crbug.com/1121865): browser_resolver_prefix_replacements allows path
-  # from ../shared/* to resolve to ../../nearby_share/shared/* for closure
+  # from ../../shared/* to resolve to ../../../nearby_share/shared/* for closure
   # purposes.
-  closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"../shared/=../../nearby_share/shared/\"" ]
+  closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"../../shared/=../../../nearby_share/shared/\"" ]
   deps = [
     ":nearby_share_contact_visibility_dialog.m",
     ":nearby_share_data_usage_dialog.m",
@@ -102,7 +102,7 @@
 }
 
 js_library("nearby_share_contact_visibility_dialog.m") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.m.js" ]
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.m.js" ]
   deps = [
     "//chrome/browser/resources/nearby_share/shared:nearby_contact_visibility.m",
     "//chrome/browser/resources/nearby_share/shared:nearby_share_settings_behavior.m",
@@ -113,12 +113,12 @@
 }
 
 js_library("nearby_share_data_usage_dialog.m") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.m.js" ]
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.m.js" ]
   deps = [
     ":types.m",
-    "../prefs:prefs.m",
-    "../prefs:prefs_behavior.m",
-    "../prefs:prefs_types.m",
+    "../../prefs:prefs.m",
+    "../../prefs:prefs_behavior.m",
+    "../../prefs:prefs_types.m",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
     "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m",
@@ -129,11 +129,11 @@
 }
 
 js_library("nearby_share_device_name_dialog.m") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.m.js" ]
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.m.js" ]
   deps = [
-    "../prefs:prefs.m",
-    "../prefs:prefs_behavior.m",
-    "../prefs:prefs_types.m",
+    "../../prefs:prefs.m",
+    "../../prefs:prefs_behavior.m",
+    "../../prefs:prefs_types.m",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
     "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
     "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
@@ -143,16 +143,16 @@
 }
 
 js_library("nearby_share_subpage.m") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.m.js" ]
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.m.js" ]
   deps = [
     ":nearby_share_contact_visibility_dialog.m",
     ":nearby_share_data_usage_dialog.m",
     ":nearby_share_device_name_dialog.m",
     ":types.m",
-    "..:router.m",
-    "../prefs:prefs.m",
-    "../prefs:prefs_behavior.m",
-    "../prefs:prefs_types.m",
+    "../..:router.m",
+    "../../prefs:prefs.m",
+    "../../prefs:prefs_behavior.m",
+    "../../prefs:prefs_types.m",
     "//chrome/browser/resources/nearby_share/shared:nearby_onboarding_page.m",
     "//chrome/browser/resources/nearby_share/shared:nearby_share_settings_behavior.m",
     "//chrome/browser/resources/nearby_share/shared:nearby_visibility_page.m",
@@ -163,21 +163,22 @@
 }
 
 js_library("types.m") {
-  sources = [ "$root_gen_dir/chrome/browser/resources/settings/nearby_share_page/types.m.js" ]
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/nearby_share_page/types.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_modulizer("modulize") {
   input_files = [ "types.js" ]
-  namespace_rewrites = settings_namespace_rewrites
+  namespace_rewrites = os_settings_namespace_rewrites
 }
 
 nearby_shared_auto_imports_closure_fix = [
   # TODO(crbug.com/1121865): polymer.py normalizes the relative paths to shared
-  # nearby resources like ../shared/* against c/b/r/settings/nearby_share_page
-  # genreating paths with the prefix c/b/r/settings/shared/*. It uses the
-  # normalized path to look up relative references for auto import. In order get
-  # the auto import to match, we need to use this path prefix even though it
+  # nearby resources like ../../shared/* against
+  # c/b/r/settings/chromeos/nearby_share_page
+  # generating paths with the prefix c/b/r/settings/shared/*. It uses the
+  # normalized path to look up relative references for auto import. In order to
+  # get the auto import to match, we need to use this path prefix even though it
   # does not exist on disk there. The actual resources are in
   # c/b/r/nearby_share/shared and are re-hosted in the chrome://os-settings
   # webui at the chrome://os-settings/shared/* prefix.
@@ -189,24 +190,25 @@
   html_file = "nearby_share_contact_visibility_dialog.html"
   html_type = "dom-module"
   namespace_rewrites =
-      settings_namespace_rewrites + nearby_shared_namespace_rewrites
-  auto_imports = settings_auto_imports + nearby_shared_auto_imports_closure_fix
+      os_settings_namespace_rewrites + nearby_shared_namespace_rewrites
+  auto_imports =
+      os_settings_auto_imports + nearby_shared_auto_imports_closure_fix
 }
 
 polymer_modulizer("nearby_share_data_usage_dialog") {
   js_file = "nearby_share_data_usage_dialog.js"
   html_file = "nearby_share_data_usage_dialog.html"
   html_type = "dom-module"
-  namespace_rewrites = settings_namespace_rewrites
-  auto_imports = settings_auto_imports
+  namespace_rewrites = os_settings_namespace_rewrites
+  auto_imports = os_settings_auto_imports
 }
 
 polymer_modulizer("nearby_share_device_name_dialog") {
   js_file = "nearby_share_device_name_dialog.js"
   html_file = "nearby_share_device_name_dialog.html"
   html_type = "dom-module"
-  namespace_rewrites = settings_namespace_rewrites
-  auto_imports = settings_auto_imports
+  namespace_rewrites = os_settings_namespace_rewrites
+  auto_imports = os_settings_auto_imports
 }
 
 polymer_modulizer("nearby_share_subpage") {
@@ -214,8 +216,8 @@
   html_file = "nearby_share_subpage.html"
   html_type = "dom-module"
   namespace_rewrites =
-      settings_namespace_rewrites + nearby_shared_namespace_rewrites
+      os_settings_namespace_rewrites + nearby_shared_namespace_rewrites
   auto_imports =
-      settings_auto_imports + nearby_shared_auto_imports_closure_fix +
+      os_settings_auto_imports + nearby_shared_auto_imports_closure_fix +
       [ "chrome/browser/resources/settings/chromeos/os_route.html|routes" ]
 }
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.html b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.html
similarity index 79%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.html
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.html
index bb8d0c2..50c532c 100644
--- a/chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.html
@@ -2,10 +2,10 @@
 
 <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="../shared/nearby_contact_visibility.html">
-<link rel="import" href="../shared/nearby_onboarding_page.html">
-<link rel="import" href="../shared/nearby_share_settings_behavior.html">
-<link rel="import" href="../shared/nearby_visibility_page.html">
+<link rel="import" href="../../shared/nearby_contact_visibility.html">
+<link rel="import" href="../../shared/nearby_onboarding_page.html">
+<link rel="import" href="../../shared/nearby_share_settings_behavior.html">
+<link rel="import" href="../../shared/nearby_visibility_page.html">
 
 <!-- TODO(vecore): The two imports above for onboarding and visibility pages are
          temporary. They are need to ensure the pages are included in the
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.js
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.html b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.html
similarity index 96%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.html
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.html
index 06667c5..b1af600 100644
--- a/chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.html
@@ -5,8 +5,8 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="../prefs/prefs.html">
-<link rel="import" href="../prefs/prefs_behavior.html">
+<link rel="import" href="../../prefs/prefs.html">
+<link rel="import" href="../../prefs/prefs_behavior.html">
 <link rel="import" href="types.html">
 
 <dom-module id="nearby-share-data-usage-dialog">
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.js
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.html b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.html
similarity index 92%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.html
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.html
index e43401e9..edd8bf1 100644
--- a/chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.html
@@ -5,8 +5,8 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="../prefs/prefs.html">
-<link rel="import" href="../prefs/prefs_behavior.html">
+<link rel="import" href="../../prefs/prefs.html">
+<link rel="import" href="../../prefs/prefs_behavior.html">
 
 <dom-module id="nearby-share-device-name-dialog">
   <template>
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.js
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.js
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.html b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.html
similarity index 90%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.html
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.html
index 45f6728..8b91a88 100644
--- a/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.html
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.html
@@ -2,13 +2,13 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="../chromeos/os_route.html">
-<link rel="import" href="../controls/settings_toggle_button.html">
-<link rel="import" href="../prefs/prefs.html">
-<link rel="import" href="../prefs/prefs_behavior.html">
-<link rel="import" href="../router.html">
-<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="../shared/nearby_share_settings_behavior.html">
+<link rel="import" href="../../controls/settings_toggle_button.html">
+<link rel="import" href="../../prefs/prefs.html">
+<link rel="import" href="../../prefs/prefs_behavior.html">
+<link rel="import" href="../../router.html">
+<link rel="import" href="../../settings_shared_css.html">
+<link rel="import" href="../../shared/nearby_share_settings_behavior.html">
+<link rel="import" href="../os_route.html">
 <link rel="import" href="nearby_share_contact_visibility_dialog.html">
 <link rel="import" href="nearby_share_device_name_dialog.html">
 <link rel="import" href="nearby_share_data_usage_dialog.html">
diff --git a/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.js
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.js
diff --git a/chrome/browser/resources/settings/nearby_share_page/types.html b/chrome/browser/resources/settings/chromeos/nearby_share_page/types.html
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/types.html
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/types.html
diff --git a/chrome/browser/resources/settings/nearby_share_page/types.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/types.js
similarity index 100%
rename from chrome/browser/resources/settings/nearby_share_page/types.js
rename to chrome/browser/resources/settings/chromeos/nearby_share_page/types.js
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 8f867c8f..56fce64 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -90,6 +90,7 @@
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.html|MultiDeviceSettingsMode,MultiDeviceFeature,MultiDeviceFeatureState,MultiDevicePageContentData,SmartLockSignInEnabledState",
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_behavior.html|MultiDeviceFeatureBehavior",
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.html|MultiDeviceBrowserProxy,MultiDeviceBrowserProxyImpl",
+                             "chrome/browser/resources/settings/chromeos/nearby_share_page/types.html|NearbyShareDataUsage,dataUsageStringToEnum",
                              "chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.html|generateOptions,getFirstPartyInputMethodEngineId,getOptionLabelName,getOptionMenuItems,getOptionUiType,getOptionUrl,hasOptionsPageInSettings,InputToolCode,isNumberValue,OPTION_DEFAULT,OptionType,UiType",
                              "chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.html|LanguagesMetricsProxy, LanguagesMetricsProxyImpl, LanguagesPageInteraction",
                              "chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.html|FingerprintInfo,FingerprintBrowserProxy,FingerprintResultType,FingerprintBrowserProxyImpl,FingerprintAttempt,FingerprintScan",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index 0b98f37..ccb61e6 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -7,7 +7,7 @@
 import './bluetooth_page/bluetooth_page.m.js';
 import './bluetooth_page/bluetooth_subpage.m.js';
 import './bluetooth_page/bluetooth_device_list_item.m.js';
-import '../nearby_share_page/nearby_share_subpage.m.js';
+import './nearby_share_page/nearby_share_subpage.m.js';
 import './multidevice_page/multidevice_page.m.js';
 import '../prefs/prefs.m.js';
 import './personalization_page/personalization_page.m.js';
@@ -23,7 +23,6 @@
 
 export {AboutPageBrowserProxyImpl, BrowserChannel, UpdateStatus} from '../about_page/about_page_browser_proxy.m.js';
 export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.m.js';
-export {dataUsageStringToEnum, NearbyShareDataUsage} from '../nearby_share_page/types.m.js';
 export {pageVisibility} from '../page_visibility.js';
 export {AccountManagerBrowserProxy, AccountManagerBrowserProxyImpl} from '../people_page/account_manager_browser_proxy.m.js';
 export {ProfileInfoBrowserProxy, ProfileInfoBrowserProxyImpl} from '../people_page/profile_info_browser_proxy.m.js';
@@ -37,6 +36,7 @@
 export {bluetoothApis} from './bluetooth_page/bluetooth_page.m.js';
 export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.m.js';
 export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.m.js';
+export {dataUsageStringToEnum, NearbyShareDataUsage} from './nearby_share_page/types.m.js';
 export {KerberosAccountsBrowserProxyImpl, KerberosConfigErrorCode, KerberosErrorType} from './os_people_page/kerberos_accounts_browser_proxy.m.js';
 export {OsResetBrowserProxyImpl} from './os_reset_page/os_reset_browser_proxy.m.js';
 export {routes} from './os_route.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
index 93bd224..f71646b 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
+++ b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
@@ -644,27 +644,27 @@
            compress="false"
            type="BINDATA"/>
   <include name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_M_JS"
-           file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/nearby_share_subpage.m.js"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_subpage.m.js"
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
   <include name="IDR_OS_SETTINGS_NEARBY_SHARE_CONTACT_VISIBILITY_DIALOG_M_JS"
-           file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/nearby_share_contact_visibility_dialog.m.js"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.m.js"
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
   <include name="IDR_OS_SETTINGS_NEARBY_SHARE_DEVICE_NAME_DIALOG_M_JS"
-           file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/nearby_share_device_name_dialog.m.js"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_device_name_dialog.m.js"
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
   <include name="IDR_OS_SETTINGS_NEARBY_SHARE_DATA_USAGE_DIALOG_M_JS"
-           file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/nearby_share_data_usage_dialog.m.js"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.m.js"
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
   <include name="IDR_OS_SETTINGS_NEARBY_SHARE_TYPES_M_JS"
-           file="${root_gen_dir}/chrome/browser/resources/settings/nearby_share_page/types.m.js"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/nearby_share_page/types.m.js"
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
diff --git a/chrome/browser/resources/settings/os_settings_resources.grd b/chrome/browser/resources/settings/os_settings_resources.grd
index 3e2f2dd..66b1409 100644
--- a/chrome/browser/resources/settings/os_settings_resources.grd
+++ b/chrome/browser/resources/settings/os_settings_resources.grd
@@ -1311,34 +1311,34 @@
                  file="chromeos/multidevice_page/multidevice_tether_item.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_CONTACT_VISIBILITY_DIALOG_HTML"
-                 file="nearby_share_page/nearby_share_contact_visibility_dialog.html"
+                 file="chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.html"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_CONTACT_VISIBILITY_DIALOG_JS"
-                 file="nearby_share_page/nearby_share_contact_visibility_dialog.js"
+                 file="chromeos/nearby_share_page/nearby_share_contact_visibility_dialog.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_DEVICE_NAME_DIALOG_HTML"
-                 file="nearby_share_page/nearby_share_device_name_dialog.html"
+                 file="chromeos/nearby_share_page/nearby_share_device_name_dialog.html"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_DEVICE_NAME_DIALOG_JS"
-                 file="nearby_share_page/nearby_share_device_name_dialog.js"
+                 file="chromeos/nearby_share_page/nearby_share_device_name_dialog.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_DATA_USAGE_DIALOG_HTML"
-                 file="nearby_share_page/nearby_share_data_usage_dialog.html"
+                 file="chromeos/nearby_share_page/nearby_share_data_usage_dialog.html"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_DATA_USAGE_DIALOG_JS"
-                 file="nearby_share_page/nearby_share_data_usage_dialog.js"
+                 file="chromeos/nearby_share_page/nearby_share_data_usage_dialog.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_TYPES_HTML"
-                 file="nearby_share_page/types.html"
+                 file="chromeos/nearby_share_page/types.html"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_TYPES_JS"
-                 file="nearby_share_page/types.js"
+                 file="chromeos/nearby_share_page/types.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_HTML"
-                 file="nearby_share_page/nearby_share_subpage.html"
+                 file="chromeos/nearby_share_page/nearby_share_subpage.html"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NEARBY_SHARE_SUBPAGE_JS"
-                 file="nearby_share_page/nearby_share_subpage.js"
+                 file="chromeos/nearby_share_page/nearby_share_subpage.js"
                  compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_NETWORK_PROXY_SECTION_HTML"
                  file="chromeos/internet_page/network_proxy_section.html"
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni
index daf863b..8dad7c0 100644
--- a/chrome/browser/resources/settings/settings.gni
+++ b/chrome/browser/resources/settings/settings.gni
@@ -134,7 +134,6 @@
   "chrome/browser/resources/settings/extension_control_browser_proxy.html|ExtensionControlBrowserProxyImpl,ExtensionControlBrowserProxy",
   "chrome/browser/resources/settings/global_scroll_target_behavior.html|GlobalScrollTargetBehavior",
   "chrome/browser/resources/settings/i18n_setup.html|loadTimeData",
-  "chrome/browser/resources/settings/nearby_share_page/types.html|NearbyShareDataUsage,dataUsageStringToEnum",
   "chrome/browser/resources/settings/prefs/prefs_behavior.html|PrefsBehavior",
   "chrome/browser/resources/settings/prefs/prefs_types.html|CrSettingsPrefs",
   "chrome/browser/resources/settings/printing_page/printing_browser_proxy.html|PrintingBrowserProxyImpl",
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index ec79341..dcbd85a 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -120,7 +120,7 @@
 // allowlist for users opted into extended reporting, from non-incognito window.
 const float kProbabilityForSendingReportsFromSafeURLs = 0.01;
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 // If user specifically mark a site as legitimate, we will keep this decision
 // for 2 days.
 const int kOverrideVerdictCacheDurationSec = 2 * 24 * 60 * 60;
@@ -239,7 +239,7 @@
       cache_manager_(VerdictCacheManagerFactory::GetForProfile(profile)) {
   pref_change_registrar_->Init(profile_->GetPrefs());
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   scoped_refptr<password_manager::PasswordStore> password_store =
       GetProfilePasswordStore();
   // Password store can be null in tests.
@@ -320,7 +320,7 @@
   return nullptr;
 }
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 // static
 bool ChromePasswordProtectionService::ShouldShowPasswordReusePageInfoBubble(
     content::WebContents* web_contents,
@@ -1265,7 +1265,7 @@
 }
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 bool ChromePasswordProtectionService::HasUnhandledEnterprisePasswordReuse(
     content::WebContents* web_contents) const {
   return web_contents_with_unhandled_enterprise_reuses_.find(web_contents) !=
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index 98248a67..6429f12 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -103,7 +103,7 @@
   static ChromePasswordProtectionService* GetPasswordProtectionService(
       Profile* profile);
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   // Called by SecurityStateTabHelper to determine if page info bubble should
   // show password reuse warning.
   static bool ShouldShowPasswordReusePageInfoBubble(
@@ -203,7 +203,7 @@
   void ReportPasswordChanged() override;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   // Returns true if there's any enterprise password reuses unhandled in
   // |web_contents|. "Unhandled" is defined as user hasn't clicked on
   // "Change Password" button in modal warning dialog.
@@ -340,7 +340,7 @@
   // If Safe browsing endpoint is not enabled in the country.
   bool IsInExcludedCountry() override;
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   void MaybeLogPasswordReuseDetectedEvent(
       content::WebContents* web_contents) override;
 
@@ -467,7 +467,7 @@
   // Returns whether the profile is valid and has safe browsing service enabled.
   bool IsSafeBrowsingEnabled();
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   void MaybeLogPasswordReuseLookupResult(
       content::WebContents* web_contents,
       sync_pb::GaiaPasswordReuse::PasswordReuseLookup::LookupResult result);
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc
index 252e7f59..bb00997 100644
--- a/chrome/browser/signin/dice_browsertest.cc
+++ b/chrome/browser/signin/dice_browsertest.cc
@@ -703,8 +703,8 @@
   EXPECT_EQ(0, reconcilor_unblocked_count_);
   task_runner->FastForwardBy(
       base::TimeDelta::FromHours((kLockAccountReconcilorTimeoutHours + 1) / 2));
-  // Check that the reconcilor was unblocked.
-  EXPECT_EQ(1, reconcilor_unblocked_count_);
+  // Wait until reconcilor is unblocked.
+  WaitForReconcilorUnblockedCount(1);
 }
 
 // Checks that re-auth on Gaia triggers the fetch for a refresh token.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 0c024643..0fe15b66 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1503,6 +1503,7 @@
       "//chrome/browser:theme_properties",
       "//chrome/browser/media/kaleidoscope/mojom",
       "//chrome/browser/media/router",
+      "//chrome/browser/nearby_sharing:share_target",
       "//chrome/browser/nearby_sharing/certificates",
       "//chrome/browser/nearby_sharing/client",
       "//chrome/browser/nearby_sharing/contacts",
@@ -1952,6 +1953,7 @@
       "ash/launcher/shelf_spinner_item_controller.h",
       "ash/login_screen_client.cc",
       "ash/login_screen_client.h",
+      "ash/login_screen_shown_observer.h",
       "ash/media_client_impl.cc",
       "ash/media_client_impl.h",
       "ash/media_notification_provider_impl.cc",
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index c961b06..6738589 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -77,6 +77,16 @@
   system_tray_focus_observers_.RemoveObserver(observer);
 }
 
+void LoginScreenClient::AddLoginScreenShownObserver(
+    LoginScreenShownObserver* observer) {
+  login_screen_shown_observers_.AddObserver(observer);
+}
+
+void LoginScreenClient::RemoveLoginScreenShownObserver(
+    LoginScreenShownObserver* observer) {
+  login_screen_shown_observers_.RemoveObserver(observer);
+}
+
 chromeos::LoginAuthRecorder* LoginScreenClient::auth_recorder() {
   return auth_recorder_.get();
 }
@@ -234,6 +244,11 @@
     observer.OnFocusLeavingSystemTray(reverse);
 }
 
+void LoginScreenClient::OnLoginScreenShown() {
+  for (LoginScreenShownObserver& observer : login_screen_shown_observers_)
+    observer.OnLoginScreenShown();
+}
+
 void LoginScreenClient::LoadWallpaper(const AccountId& account_id) {
   WallpaperControllerClient::Get()->ShowUserWallpaper(account_id);
 }
diff --git a/chrome/browser/ui/ash/login_screen_client.h b/chrome/browser/ui/ash/login_screen_client.h
index 8ead2a3..eea56d9 100644
--- a/chrome/browser/ui/ash/login_screen_client.h
+++ b/chrome/browser/ui/ash/login_screen_client.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/ui/ash/login_screen_shown_observer.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 
 namespace base {
@@ -77,6 +78,9 @@
   void AddSystemTrayFocusObserver(ash::SystemTrayFocusObserver* observer);
   void RemoveSystemTrayFocusObserver(ash::SystemTrayFocusObserver* observer);
 
+  void AddLoginScreenShownObserver(LoginScreenShownObserver* observer);
+  void RemoveLoginScreenShownObserver(LoginScreenShownObserver* observer);
+
   // ash::LoginScreenClient:
   void AuthenticateUserWithPasswordOrPin(
       const AccountId& account_id,
@@ -113,6 +117,7 @@
   void ShowParentAccessHelpApp(gfx::NativeWindow parent_window) override;
   void ShowLockScreenNotificationSettings() override;
   void OnFocusLeavingSystemTray(bool reverse) override;
+  void OnLoginScreenShown() override;
   void OnUserActivity() override;
 
  private:
@@ -136,6 +141,8 @@
   base::ObserverList<ash::SystemTrayFocusObserver>::Unchecked
       system_tray_focus_observers_;
 
+  base::ObserverList<LoginScreenShownObserver> login_screen_shown_observers_;
+
   base::WeakPtrFactory<LoginScreenClient> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(LoginScreenClient);
diff --git a/chrome/browser/ui/ash/login_screen_shown_observer.h b/chrome/browser/ui/ash/login_screen_shown_observer.h
new file mode 100644
index 0000000..aad0c2a
--- /dev/null
+++ b/chrome/browser/ui/ash/login_screen_shown_observer.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_ASH_LOGIN_SCREEN_SHOWN_OBSERVER_H_
+#define CHROME_BROWSER_UI_ASH_LOGIN_SCREEN_SHOWN_OBSERVER_H_
+
+#include "base/macros.h"
+#include "base/observer_list_types.h"
+
+// A class that observes when the login screen is shown.
+class LoginScreenShownObserver : public base::CheckedObserver {
+ public:
+  LoginScreenShownObserver() {}
+  LoginScreenShownObserver(const LoginScreenShownObserver&) = delete;
+  LoginScreenShownObserver& operator=(const LoginScreenShownObserver&) = delete;
+
+  virtual void OnLoginScreenShown() = 0;
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_LOGIN_SCREEN_SHOWN_OBSERVER_H_
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 0c581c91..21f68f7 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -215,8 +215,11 @@
   // Use the original profile here, which is the same profile unless this is an
   // OffTheRecord profile. The help app is not installed into the incognito /
   // OffTheRecord profile.
-  apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(
-      profile->GetOriginalProfile());
+  if (profile->IsOffTheRecord() && !profile->IsGuestSession()) {
+    profile = profile->GetOriginalProfile();
+  }
+  apps::AppServiceProxy* proxy =
+      apps::AppServiceProxyFactory::GetForProfile(profile);
   proxy->Launch(chromeos::default_web_apps::kHelpAppId, ui::EventFlags::EF_NONE,
                 app_launch_source, display::kDefaultDisplayId);
 #else
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index 402af15..8d5927f 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -152,6 +152,9 @@
                                             : IDS_REENABLE_UPDATES))
           .AddBodyText(l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TEXT),
                        ui::DialogModelBodyText::Params().SetIsSecondary())
+          .SetWindowClosingCallback(
+              base::BindOnce(&OutdatedUpgradeBubbleDelegate::OnWindowClosing,
+                             base::Unretained(g_upgrade_bubble)))
           .SetCloseCallback(base::BindOnce(
               &base::RecordAction,
               base::UserMetricsAction("OutdatedUpgradeBubble.Later")))
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 793b401..03979210 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1948,8 +1948,8 @@
 void TabStrip::UpdateHoverCard(Tab* tab) {
   if (!base::FeatureList::IsEnabled(features::kTabHoverCards))
     return;
-  // We don't want to show a hover card for a tab while it is animating.
-  if (tab && bounds_animator_.IsAnimating(tab)) {
+  // We don't want to show a hover card while the tabstrip is animating.
+  if (bounds_animator_.IsAnimating()) {
     return;
   }
 
diff --git a/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui_trigger_handler.cc b/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui_trigger_handler.cc
index 3169462..26215fcf 100644
--- a/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui_trigger_handler.cc
+++ b/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui_trigger_handler.cc
@@ -4,10 +4,15 @@
 
 #include "chrome/browser/ui/webui/nearby_internals/nearby_internals_ui_trigger_handler.h"
 
+#include <memory>
+#include <vector>
+
 #include "base/bind.h"
 #include "base/time/time.h"
+#include "chrome/browser/nearby_sharing/attachment.h"
 #include "chrome/browser/nearby_sharing/logging/logging.h"
 #include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
+#include "chrome/browser/nearby_sharing/text_attachment.h"
 #include "chrome/services/sharing/public/mojom/nearby_share_target_types.mojom.h"
 
 namespace {
@@ -414,11 +419,16 @@
     return;
   }
 
+  std::vector<std::unique_ptr<Attachment>> attachments;
+  attachments.push_back(std::make_unique<TextAttachment>(
+      TextAttachment::Type::kText, kPayloadExample));
+
   const base::Value& callback_id = args->GetList()[0];
   ResolveJavascriptCallback(
       callback_id,
-      StatusCodeToDictionary(service_->SendText(it->second, kPayloadExample),
-                             TriggerEvent::kSendText));
+      StatusCodeToDictionary(
+          service_->SendAttachments(it->second, std::move(attachments)),
+          TriggerEvent::kSendText));
 }
 
 void NearbyInternalsUiTriggerHandler::Accept(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share.mojom b/chrome/browser/ui/webui/nearby_share/nearby_share.mojom
index 986dcd08..fd2fccf 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share.mojom
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share.mojom
@@ -40,6 +40,29 @@
   OnShareTargetLost(ShareTarget share_target);
 };
 
+// Status of the current transfer.
+enum TransferStatus {
+  // The user of the local device needs to accept or reject the transfer. This
+  // involves showing a token on both devices to be compared by the user.
+  kAwaitingLocalConfirmation,
+  // The remote device needs to accept the transfer. We still need to show the
+  // token on this device so the other user can compare it.
+  kAwaitingRemoteAcceptance,
+  // The current transfer is now in progress after both users accepted the
+  // tranfer on their devices.
+  kInProgress,
+};
+
+// Interface to be notified about transfer updates. Includes an optional token
+// that needs to be shown to the user to confirm with the remote device. The
+// token verification can be skipped for trusted devices in the contacts list
+// but must be shown when sending to unknown devices. This interface is
+// implemented in UI surfaces and called from the browser process.
+interface TransferUpdateListener {
+  // Called when the status of the current transfer changes.
+  OnTransferUpdate(TransferStatus status, string? token);
+};
+
 // Manager interface for nearby device discovery. Implemented on the browser
 // process and used by UI surfaces.
 interface DiscoveryManager {
@@ -48,14 +71,13 @@
   StartDiscovery(pending_remote<ShareTargetListener> listener)
       => (bool success);
 
-  // Select a previously discovered |share_target_id| to send data to. If the
-  // selected target requires an additional confirmation of a shared connection
-  // id by the user it will return a valid ConfirmationManager interface to be
-  // used to accept or reject the transfer. |token| will contain the string to
-  // show to the user in that case.
+  // Select a previously discovered |share_target_id| to send data to. On
+  // success this will return valid ConfirmationManager and
+  // TransferUpdateListener interfaces to be used to show an additional
+  // confirmation screen to accept or reject the transfer.
   SelectShareTarget(mojo_base.mojom.UnguessableToken share_target_id)
       => (SelectShareTargetResult result,
-          string? token,
+          pending_receiver<TransferUpdateListener>? transfer_update_listener,
           pending_remote<ConfirmationManager>? confirmation_manager);
 };
 
@@ -67,4 +89,7 @@
 
   // Rejects a connection to the current Share Target.
   Reject() => (bool success);
+
+  // Cancels a connection to the current Share Target.
+  Cancel() => (bool success);
 };
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
index 1ab78de8..147c7a92 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
@@ -72,16 +72,19 @@
   observers_.RemoveObserver(observer);
 }
 
-void NearbyShareDialogUI::SetShareIntent(apps::mojom::IntentPtr intent) {
-  intent_ = std::move(intent);
+void NearbyShareDialogUI::SetAttachments(
+    std::vector<std::unique_ptr<Attachment>> attachments) {
+  attachments_ = std::move(attachments);
 }
 
 void NearbyShareDialogUI::BindInterface(
     mojo::PendingReceiver<mojom::DiscoveryManager> manager) {
   mojo::MakeSelfOwnedReceiver(
-      std::make_unique<NearbyPerSessionDiscoveryManager>(nearby_service_),
+      std::make_unique<NearbyPerSessionDiscoveryManager>(
+          nearby_service_, std::move(attachments_)),
       std::move(manager));
 }
+
 void NearbyShareDialogUI::BindInterface(
     mojo::PendingReceiver<mojom::NearbyShareSettings> receiver) {
   NearbySharingService* nearby_sharing_service =
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h
index 598a04d9..72a61cb 100644
--- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h
+++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h
@@ -5,11 +5,14 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_
 #define CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_
 
+#include <memory>
+#include <vector>
+
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "chrome/browser/nearby_sharing/attachment.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
 #include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h"
-#include "components/services/app_service/public/mojom/types.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 
@@ -32,7 +35,7 @@
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
-  void SetShareIntent(apps::mojom::IntentPtr intent);
+  void SetAttachments(std::vector<std::unique_ptr<Attachment>> attachments);
 
   // Instantiates the implementor of the mojom::DiscoveryManager mojo
   // interface passing the pending receiver that will be internally bound.
@@ -43,7 +46,7 @@
 
  private:
   void HandleClose(const base::ListValue* args);
-  apps::mojom::IntentPtr intent_;
+  std::vector<std::unique_ptr<Attachment>> attachments_;
   base::ObserverList<Observer> observers_;
   NearbySharingService* nearby_service_;
 
diff --git a/chrome/browser/ui/webui/settings/about_handler_unittest.cc b/chrome/browser/ui/webui/settings/about_handler_unittest.cc
index ae3aad7b..bdfcdf6 100644
--- a/chrome/browser/ui/webui/settings/about_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/about_handler_unittest.cc
@@ -80,7 +80,15 @@
   FakeUpdateEngineClient* fake_update_engine_client_;
 };
 
-TEST_F(AboutHandlerTest, EndOfLifeMessageInAboutDetailsSubpage) {
+// Deterministic fail on CHROMEOS, crbug.com/1122584.
+#if defined(OS_CHROMEOS)
+#define MAYBE_EndOfLifeMessageInAboutDetailsSubpage \
+  DISABLED_EndOfLifeMessageInAboutDetailsSubpage
+#else
+#define MAYBE_EndOfLifeMessageInAboutDetailsSubpage \
+  EndOfLifeMessageInAboutDetailsSubpage
+#endif
+TEST_F(AboutHandlerTest, MAYBE_EndOfLifeMessageInAboutDetailsSubpage) {
   const base::Time eol_passed_date =
       base::Time::Now() - base::TimeDelta::FromDays(1000);
   fake_update_engine_client_->set_eol_date(eol_passed_date);
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index 2cd1a62..367193b 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -367,7 +367,7 @@
     LocalAuth::SetLocalAuthCredentials(profile_, password_);
   }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   if (!password_.empty()) {
     scoped_refptr<password_manager::PasswordStore> password_store =
         PasswordStoreFactory::GetForProfile(profile_,
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index f294ab7..33164fc 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -57,6 +57,7 @@
 
 #if !defined(OFFICIAL_BUILD)
 #include "chrome/browser/chromeos/web_applications/sample_system_web_app_info.h"
+#include "chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h"
 #endif  // !defined(OFFICIAL_BUILD)
 
 #endif  // defined(OS_CHROMEOS)
@@ -172,9 +173,11 @@
 
 #if !defined(OFFICIAL_BUILD)
   if (SystemWebAppManager::IsAppEnabled(SystemAppType::TELEMETRY)) {
-    infos.emplace(SystemAppType::TELEMETRY,
-                  SystemAppInfo("Telemetry",
-                                GURL("chrome://telemetry-extension/pwa.html")));
+    infos.emplace(
+        SystemAppType::TELEMETRY,
+        SystemAppInfo(
+            "Telemetry", GURL("chrome://telemetry-extension"),
+            base::BindRepeating(&CreateWebAppInfoForTelemetryExtension)));
   }
 
   infos.emplace(
diff --git a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
index d5a4bd3..fbadee0 100644
--- a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
@@ -1127,10 +1127,7 @@
 #if defined(OFFICIAL_BUILD)
     return 8;
 #else
-    // TODO(http://crbug.com/1120208): Telemetry isn't available for install
-    // unless its flag is enabled. So it's not included here. Update this after
-    // Telemetry is available for install without a flag.
-    return 9;
+    return 10;
 #endif  // defined(OFFICIAL_BUILD)
   }
 
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
index 7dc19d2..83bc84b53 100644
--- a/chrome/browser/web_applications/web_app_database.cc
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -604,6 +604,10 @@
   switch (user_display_mode) {
     case ::sync_pb::WebAppSpecifics::BROWSER:
       return DisplayMode::kBrowser;
+    // New display modes will most likely be of the window variety than the
+    // browser tab variety so default to windowed if it's an enum value we don't
+    // know about.
+    case ::sync_pb::WebAppSpecifics::UNSPECIFIED:
     case ::sync_pb::WebAppSpecifics::STANDALONE:
       return DisplayMode::kStandalone;
   }
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 35f58c2..8f81761c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1598313565-08e05b737624bbbe76926e73b436a35f99d64175.profdata
+chrome-mac-master-1598529464-36870a872fe98f9e50202a2a325506fd4bcc24c9.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 7bd048c..1d2dedf4 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2545,6 +2545,8 @@
         "../browser/chromeos/web_applications/settings_app_integration_browsertest.cc",
         "../browser/chromeos/web_applications/system_web_app_integration_test.cc",
         "../browser/chromeos/web_applications/system_web_app_integration_test.h",
+        "../browser/chromeos/web_applications/test/profile_test_helper.cc",
+        "../browser/chromeos/web_applications/test/profile_test_helper.h",
         "../browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_web_request_service_browsertest.cc",
         "../browser/download/notification/download_notification_browsertest.cc",
         "../browser/drive/drive_notification_manager_factory_browsertest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
index 1a4e02d29..d3d88bdd 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -49,7 +49,7 @@
             SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
                     Profile.getLastUsedRegularProfile());
             signinManager.onFirstRunCheckDone(); // Allow sign-in
-            signinManager.signIn(
+            signinManager.signinAndEnableSync(
                     SigninAccessPoint.UNKNOWN, account, new SigninManager.SignInCallback() {
                         @Override
                         public void onSignInComplete() {
diff --git a/chrome/test/data/extensions/api_test/input_method/settings/background.js b/chrome/test/data/extensions/api_test/input_method/settings/background.js
index 46c6e73..1f1f80d7 100644
--- a/chrome/test/data/extensions/api_test/input_method/settings/background.js
+++ b/chrome/test/data/extensions/api_test/input_method/settings/background.js
@@ -56,15 +56,15 @@
   // Test OnSettingsChanged event gets raised when settings are updated.
   function eventRaisedWhenSettingToInitialValue() {
     const settings = { 'enableDoubleSpacePeriod': true };
-    const listener = (ime, value) => {
+    const listener = (ime) => {
       chrome.test.assertEq('ime', ime);
-      chrome.test.assertEq(settings, value);
       chrome.test.succeed();
 
-      chrome.inputMethodPrivate.onSettingsChanged.removeListener(listener);
+      chrome.inputMethodPrivate.onInputMethodOptionsChanged
+          .removeListener(listener);
     };
 
-    chrome.inputMethodPrivate.onSettingsChanged.addListener(listener);
+    chrome.inputMethodPrivate.onInputMethodOptionsChanged.addListener(listener);
     chrome.inputMethodPrivate.setSettings('ime', settings);
   }
 ]);
diff --git a/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js b/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
index aa8da7a..ad151ee 100644
--- a/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
+++ b/chrome/test/data/webui/nearby_share/fake_mojo_interfaces.js
@@ -15,6 +15,7 @@
     super([
       'accept',
       'reject',
+      'cancel',
     ]);
   }
 
@@ -27,6 +28,11 @@
     this.methodCalled('reject');
     return {success: true};
   }
+
+  async cancel() {
+    this.methodCalled('cancel');
+    return {success: true};
+  }
 }
 
 /**
@@ -42,7 +48,7 @@
 
     this.selectShareTargetResult = {
       result: nearbyShare.mojom.SelectShareTargetResult.kOk,
-      token: null,
+      transferUpdateListener: null,
       confirmationManager: null,
     };
   }
@@ -62,3 +68,15 @@
     return {success: true};
   }
 }
+
+/**
+ * @extends {nearbyShare.mojom.TransferUpdateListenerPendingReceiver}
+ */
+export class FakeTransferUpdateListenerPendingReceiver extends
+    nearbyShare.mojom.TransferUpdateListenerPendingReceiver {
+  constructor() {
+    const {handle0, handle1} = Mojo.createMessagePipe();
+    super(handle0);
+    this.remote_ = new nearbyShare.mojom.TransferUpdateListenerRemote(handle1);
+  }
+}
diff --git a/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js b/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
index 7a51488..7d7701f 100644
--- a/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
+++ b/chrome/test/data/webui/nearby_share/nearby_confirmation_page_test.js
@@ -8,15 +8,25 @@
 import 'chrome://nearby/nearby_confirmation_page.js';
 
 import {assertEquals, assertTrue} from '../chai_assert.js';
-import {FakeConfirmationManagerRemote} from './fake_mojo_interfaces.js';
+import {FakeConfirmationManagerRemote, FakeTransferUpdateListenerPendingReceiver} from './fake_mojo_interfaces.js';
 
 suite('ConfirmatonPageTest', function() {
   /** @type {!NearbyConfirmationPageElement} */
   let confirmationPageElement;
 
+  /** @type {!FakeConfirmationManagerRemote} */
+  let confirmationManager;
+
+  /** @type {!FakeTransferUpdateListenerPendingReceiver} */
+  let transferUpdateListener;
+
   setup(function() {
+    confirmationManager = new FakeConfirmationManagerRemote();
+    transferUpdateListener = new FakeTransferUpdateListenerPendingReceiver();
     confirmationPageElement = /** @type {!NearbyConfirmationPageElement} */ (
         document.createElement('nearby-confirmation-page'));
+    confirmationPageElement.confirmationManager = confirmationManager;
+    confirmationPageElement.transferUpdateListener = transferUpdateListener;
     document.body.appendChild(confirmationPageElement);
   });
 
@@ -29,22 +39,41 @@
   });
 
   test('calls accept on click', async function() {
-    const confirmationManager = new FakeConfirmationManagerRemote();
-    confirmationPageElement.confirmationManager = confirmationManager;
+    transferUpdateListener.remote_.onTransferUpdate(
+        nearbyShare.mojom.TransferStatus.kAwaitingLocalConfirmation,
+        /*token=*/ null);
+    await transferUpdateListener.remote_.$.flushForTesting();
+
     confirmationPageElement.$$('#accept-button').click();
     await confirmationManager.whenCalled('accept');
   });
 
   test('calls reject on click', async function() {
-    const confirmationManager = new FakeConfirmationManagerRemote();
-    confirmationPageElement.confirmationManager = confirmationManager;
-    confirmationPageElement.$$('#cancel-button').click();
+    transferUpdateListener.remote_.onTransferUpdate(
+        nearbyShare.mojom.TransferStatus.kAwaitingLocalConfirmation,
+        /*token=*/ null);
+    await transferUpdateListener.remote_.$.flushForTesting();
+
+    confirmationPageElement.$$('#reject-button').click();
     await confirmationManager.whenCalled('reject');
   });
 
-  test('renders confirmation token', function() {
+  test('calls cancel on click', async function() {
+    transferUpdateListener.remote_.onTransferUpdate(
+        nearbyShare.mojom.TransferStatus.kAwaitingRemoteAcceptance,
+        /*token=*/ null);
+    await transferUpdateListener.remote_.$.flushForTesting();
+
+    confirmationPageElement.$$('#cancel-button').click();
+    await confirmationManager.whenCalled('cancel');
+  });
+
+  test('renders confirmation token', async function() {
     const token = 'TestToken1234';
-    confirmationPageElement.confirmationToken = token;
+    transferUpdateListener.remote_.onTransferUpdate(
+        nearbyShare.mojom.TransferStatus.kAwaitingLocalConfirmation, token);
+    await transferUpdateListener.remote_.$.flushForTesting();
+
     const renderedToken =
         confirmationPageElement.$$('#confirmation-token').textContent;
     assertTrue(renderedToken.includes(token));
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index a8cb079..9075336c 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -1054,7 +1054,8 @@
 var OSSettingsNearbyShareSubPageTest = class extends OSSettingsBrowserTest {
   /** @override */
   get browsePreload() {
-    return super.browsePreload + 'nearby_share_page/nearby_share_subpage.html';
+    return super.browsePreload +
+        'chromeos/nearby_share_page/nearby_share_subpage.html';
   }
 
   /** @override */
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index df345be..da4904e 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-13431.0.0
\ No newline at end of file
+13433.0.0
\ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js b/chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js
index 1692759..80f4b79 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js
@@ -121,7 +121,13 @@
    */
   async openPhoto(blob) {
     const img = await util.blobToImage(blob);
-    this.reviewPhotoResult_.src = img.src;
+
+    await new Promise((resolve, reject) => {
+      this.reviewPhotoResult_.onload = resolve;
+      this.reviewPhotoResult_.onerror = reject;
+      this.reviewPhotoResult_.src = img.src;
+    });
+
     state.set(state.State.REVIEW_PHOTO_RESULT, true);
     state.set(state.State.REVIEW_RESULT, true);
     this.confirmResultButton_.focus();
@@ -138,7 +144,14 @@
    *     with the video result.
    */
   async openVideo(fileEntry) {
-    this.reviewVideoResult_.src = await pictureURL(fileEntry);
+    await new Promise((resolve, reject) => {
+      this.reviewVideoResult_.oncanplay = resolve;
+      this.reviewVideoResult_.onerror = reject;
+      pictureURL(fileEntry).then((url) => {
+        this.reviewVideoResult_.src = url;
+      });
+    });
+
     state.set(state.State.REVIEW_VIDEO_RESULT, true);
     state.set(state.State.REVIEW_RESULT, true);
     this.confirmResultButton_.focus();
diff --git a/chromeos/components/sample_system_web_app_ui/resources/manifest.json b/chromeos/components/sample_system_web_app_ui/resources/manifest.json
deleted file mode 100644
index 5ad53d8..0000000
--- a/chromeos/components/sample_system_web_app_ui/resources/manifest.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "name": "Sample System Web App",
-  "short_name": "Sample App",
-  "start_url": "/",
-  "display": "standalone",
-  "theme_color": "#4285F4",
-  "background_color": "#ffffff",
-  "scope": "./",
-  "icons": [
-    {
-      "src": "app_icon_192.png",
-      "sizes": "192x192",
-      "type": "image/png"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/chromeos/components/sample_system_web_app_ui/resources/pwa.html b/chromeos/components/sample_system_web_app_ui/resources/pwa.html
deleted file mode 100644
index 8cb86f24..0000000
--- a/chromeos/components/sample_system_web_app_ui/resources/pwa.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- Copyright 2019 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-<!-- TODO(crbug/896575): Delete when manifest URL installs are implemented. -->
-<!DOCTYPE html>
-<link rel="manifest" href="manifest.json">
diff --git a/chromeos/components/sample_system_web_app_ui/resources/sample_system_web_app_resources.grd b/chromeos/components/sample_system_web_app_ui/resources/sample_system_web_app_resources.grd
index 8c41e4a..d1a2566c 100644
--- a/chromeos/components/sample_system_web_app_ui/resources/sample_system_web_app_resources.grd
+++ b/chromeos/components/sample_system_web_app_ui/resources/sample_system_web_app_resources.grd
@@ -15,9 +15,7 @@
       <if expr="is_official_build == false">
         <!-- Privileged app host contents. -->
         <include name="IDR_SAMPLE_SYSTEM_WEB_APP_INDEX_HTML" file="index.html" type="BINDATA" />
-        <include name="IDR_SAMPLE_SYSTEM_WEB_APP_PWA_HTML" file="pwa.html" type="BINDATA" />
         <include name="IDR_SAMPLE_SYSTEM_WEB_APP_SANDBOX_HTML" file="sandbox.html" type="BINDATA" />
-        <include name="IDR_SAMPLE_SYSTEM_WEB_APP_MANIFEST" file="manifest.json" type="BINDATA" compress="gzip" />
         <include name="IDR_SAMPLE_SYSTEM_WEB_APP_ICON_192" file="app_icon_192.png" type="BINDATA" />
 
         <!-- Untrusted app contents. -->
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 0cef708..a58054d4 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
@@ -36,12 +36,8 @@
       content::WebUIDataSource::Create(kChromeUISampleSystemWebAppHost));
 
   trusted_source->AddResourcePath("", IDR_SAMPLE_SYSTEM_WEB_APP_INDEX_HTML);
-  trusted_source->AddResourcePath("pwa.html",
-                                  IDR_SAMPLE_SYSTEM_WEB_APP_PWA_HTML);
   trusted_source->AddResourcePath("sandbox.html",
                                   IDR_SAMPLE_SYSTEM_WEB_APP_SANDBOX_HTML);
-  trusted_source->AddResourcePath("manifest.json",
-                                  IDR_SAMPLE_SYSTEM_WEB_APP_MANIFEST);
   trusted_source->AddResourcePath("app_icon_192.png",
                                   IDR_SAMPLE_SYSTEM_WEB_APP_ICON_192);
 
diff --git a/chromeos/components/telemetry_extension_ui/resources/manifest.json b/chromeos/components/telemetry_extension_ui/resources/manifest.json
deleted file mode 100644
index 3891042..0000000
--- a/chromeos/components/telemetry_extension_ui/resources/manifest.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "name": "Telemetry Extension",
-  "short_name": "Telemetry Extension",
-  "start_url": "/",
-  "display": "standalone",
-  "theme_color": "#4285F4",
-  "background_color": "#ffffff",
-  "scope": "./",
-  "icons": [
-    {
-      "src": "app_icon_96.png",
-      "sizes": "96x96",
-      "type": "image/png"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/chromeos/components/telemetry_extension_ui/resources/pwa.html b/chromeos/components/telemetry_extension_ui/resources/pwa.html
deleted file mode 100644
index 9c99cdde..0000000
--- a/chromeos/components/telemetry_extension_ui/resources/pwa.html
+++ /dev/null
@@ -1,6 +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. -->
-<!-- TODO(crbug/896575): Delete when manifest URL installs are implemented. -->
-<!DOCTYPE html>
-<link rel="manifest" href="manifest.json">
diff --git a/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd b/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd
index dc9f2f4c..d3abe60 100644
--- a/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd
+++ b/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd
@@ -15,9 +15,7 @@
       <if expr="telemetry_extension == true">
         <!-- Privileged app host contents. -->
         <include name="IDR_TELEMETRY_EXTENSION_INDEX_HTML" file="index.html" type="BINDATA" />
-        <include name="IDR_TELEMETRY_EXTENSION_PWA_HTML" file="pwa.html" type="BINDATA" />
-        <include name="IDR_TELEMETRY_EXTENSION_MANIFEST" file="manifest.json" type="BINDATA" compress="gzip" />
-        <include name="IDR_TELEMETRY_EXTENSION_ICON_96" file="app_icon_96.png" type="BINDATA" compress="gzip" />
+        <include name="IDR_TELEMETRY_EXTENSION_ICON_96" file="app_icon_96.png" type="BINDATA" />
         <include name="IDR_TELEMETRY_EXTENSION_TRUSTED_SCRIPTS_JS" file="trusted_scripts.js" flattenhtml="true" type="BINDATA" compress="gzip" />
         <include name="IDR_TELEMETRY_EXTENSION_DIAGNOSTICS_SERVICE_MOJO_LITE_JS" file="${root_gen_dir}/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
         <include name="IDR_TELEMETRY_EXTENSION_PROBE_SERVICE_MOJO_LITE_JS" file="${root_gen_dir}/chromeos/components/telemetry_extension_ui/mojom/probe_service.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
diff --git a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
index 54052a7f..d4ce67c 100644
--- a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
+++ b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
@@ -30,9 +30,6 @@
       content::WebUIDataSource::Create(kChromeUITelemetryExtensionHost));
 
   trusted_source->AddResourcePath("", IDR_TELEMETRY_EXTENSION_INDEX_HTML);
-  trusted_source->AddResourcePath("pwa.html", IDR_TELEMETRY_EXTENSION_PWA_HTML);
-  trusted_source->AddResourcePath("manifest.json",
-                                  IDR_TELEMETRY_EXTENSION_MANIFEST);
   trusted_source->AddResourcePath("app_icon_96.png",
                                   IDR_TELEMETRY_EXTENSION_ICON_96);
   trusted_source->AddResourcePath("trusted_scripts.js",
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index f77fe82f..7e0ab10 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -396,7 +396,7 @@
 
 // Controls whether the PIN auto submit feature is enabled.
 const base::Feature kQuickUnlockPinAutosubmit{
-    "QuickUnlockPinAutosubmit", base::FEATURE_DISABLED_BY_DEFAULT};
+    "QuickUnlockPinAutosubmit", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // TODO(crbug.com/1104164) - Remove this once most
 // users have their preferences backfilled.
@@ -558,6 +558,10 @@
   return base::FeatureList::IsEnabled(kOsSettingsDeepLinking);
 }
 
+bool IsDiagnosticsAppEnabled() {
+  return base::FeatureList::IsEnabled(kDiagnosticsApp);
+}
+
 bool IsImeSandboxEnabled() {
   return base::FeatureList::IsEnabled(kEnableImeSandbox);
 }
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 9e6dd85..57fbfb6 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -241,6 +241,7 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsBetterUpdateEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsChildSpecificSigninEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsDeepLinkingEnabled();
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsDiagnosticsAppEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsImeSandboxEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 bool IsInstantTetheringBackgroundAdvertisingSupported();
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 36fbbf8..7919756a 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -3205,10 +3205,6 @@
 // Test that if a company is of a format of a birthyear and the relevant feature
 // is enabled, we would not fill it.
 TEST_P(AutofillManagerStructuredProfileTest, FillAddressForm_CompanyBirthyear) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      features::kAutofillRejectCompanyBirthyear);
-
   // Set up our form data.
   FormData address_form;
   address_form.name = ASCIIToUTF16("MyForm");
diff --git a/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc b/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
index 02c6844..86cd442 100644
--- a/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
@@ -1005,12 +1005,6 @@
 }
 
 TEST_P(AutofillProfileComparatorTest, MergeCompanyNames) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{autofill::features::
-                                kAutofillRejectCompanyBirthyear},
-      /*disabled_features=*/{});
-
   static const char kCompanyA[] = "Some Company";
   static const char kCompanyB[] = "SÔMÈ ÇÖMPÁÑÝ";
   static const char kCompanyC[] = "SÔMÈ ÇÖMPÁÑÝ A.G.";
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc
index c4029d3..8464c16 100644
--- a/components/autofill/core/browser/data_model/contact_info.cc
+++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -346,26 +346,16 @@
 }
 
 bool CompanyInfo::IsValidOrVerified(const base::string16& value) const {
-  if (profile_ && profile_->IsVerified()) {
-    return true;
-  }
-  // |value| is a birthyear:
-  if (base::FeatureList::IsEnabled(
-          autofill::features::kAutofillRejectCompanyBirthyear) &&
-      MatchesPattern(value, base::UTF8ToUTF16("^(19|20)\\d{2}$"))) {
-    return false;
-  }
-  // |value| is a social title:
-  if (base::FeatureList::IsEnabled(
-          autofill::features::kAutofillRejectCompanySocialTitle) &&
-      MatchesPattern(value, base::UTF8ToUTF16(
-                                "^(Ms\\.?|Mrs\\.?|Mr\\.?|Miss|Mistress|Mister|"
-                                "Frau|Herr|"
-                                "Mlle|Mme|M\\.|"
-                                "Dr\\.?|Prof\\.?)$"))) {
-    return false;
-  }
-  return true;
+  // TODO(crbug/1117296): retrieve regular expressions dynamically.
+  static const char* kBirthyearRe = "^(19|20)\\d{2}$";
+  static const char* kSocialTitleRe =
+      "^(Ms\\.?|Mrs\\.?|Mr\\.?|Miss|Mistress|Mister|"
+      "Frau|Herr|"
+      "Mlle|Mme|M\\.|"
+      "Dr\\.?|Prof\\.?)$";
+  return (profile_ && profile_->IsVerified()) ||
+         (!MatchesPattern(value, base::UTF8ToUTF16(kBirthyearRe)) &&
+          !MatchesPattern(value, base::UTF8ToUTF16(kSocialTitleRe)));
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/data_model/contact_info_unittest.cc b/components/autofill/core/browser/data_model/contact_info_unittest.cc
index fd7384f7..b600471 100644
--- a/components/autofill/core/browser/data_model/contact_info_unittest.cc
+++ b/components/autofill/core/browser/data_model/contact_info_unittest.cc
@@ -260,296 +260,97 @@
             name.GetInfo(AutofillType(NAME_FULL), "en-US"));
 }
 
-TEST(CompanyTest, CompanyNameYear) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanyBirthyear},
-      /*disabled_features=*/{});
-
+TEST(CompanyTest, CompanyName) {
   AutofillProfile profile;
   CompanyInfo company(&profile);
   ASSERT_FALSE(profile.IsVerified());
 
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
-  EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
+  auto SetAndGetCompany = [&company](const char* company_name) mutable {
+    company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(company_name));
+    return base::UTF16ToUTF8(company.GetRawInfo(COMPANY_NAME));
+  };
 
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("It was 1987."));
-  EXPECT_EQ(UTF8ToUTF16("It was 1987."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987 was the year."));
-  EXPECT_EQ(UTF8ToUTF16("1987 was the year."),
-            company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Yes, 1987 was the year."));
-  EXPECT_EQ(UTF8ToUTF16("Yes, 1987 was the year."),
-            company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
-  EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
-  EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
-  EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
-  EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
-  EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
-  EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
-  EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
-  EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
+  EXPECT_EQ(SetAndGetCompany("Google"), "Google");
+  EXPECT_EQ(SetAndGetCompany("1818"), "1818");
+  EXPECT_EQ(SetAndGetCompany("1987"), "");
+  EXPECT_EQ(SetAndGetCompany("2019"), "");
+  EXPECT_EQ(SetAndGetCompany("2345"), "2345");
+  EXPECT_EQ(SetAndGetCompany("It was 1987."), "It was 1987.");
+  EXPECT_EQ(SetAndGetCompany("1987 was the year."), "1987 was the year.");
+  EXPECT_EQ(SetAndGetCompany("Mr"), "");
+  EXPECT_EQ(SetAndGetCompany("Mr."), "");
+  EXPECT_EQ(SetAndGetCompany("Mrs"), "");
+  EXPECT_EQ(SetAndGetCompany("Mrs."), "");
+  EXPECT_EQ(SetAndGetCompany("Mr. & Mrs."), "Mr. & Mrs.");
+  EXPECT_EQ(SetAndGetCompany("Mr. & Mrs. Smith"), "Mr. & Mrs. Smith");
+  EXPECT_EQ(SetAndGetCompany("Frau"), "");
+  EXPECT_EQ(SetAndGetCompany("Frau Doktor"), "Frau Doktor");
+  EXPECT_EQ(SetAndGetCompany("Herr"), "");
+  EXPECT_EQ(SetAndGetCompany("Mme"), "");
+  EXPECT_EQ(SetAndGetCompany("Ms"), "");
+  EXPECT_EQ(SetAndGetCompany("Dr"), "");
+  EXPECT_EQ(SetAndGetCompany("Dr."), "");
+  EXPECT_EQ(SetAndGetCompany("Prof"), "");
+  EXPECT_EQ(SetAndGetCompany("Prof."), "");
 
   profile.set_origin("Not empty");
   ASSERT_TRUE(profile.IsVerified());
 
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
-  EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
-  EXPECT_EQ(UTF8ToUTF16("1987"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
-  EXPECT_EQ(UTF8ToUTF16("2019"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
-  EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
-  EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
-  EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
-  EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
-  EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
-  EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
-  EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
-  EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
+  EXPECT_EQ(SetAndGetCompany("Google"), "Google");
+  EXPECT_EQ(SetAndGetCompany("1818"), "1818");
+  EXPECT_EQ(SetAndGetCompany("1987"), "1987");
+  EXPECT_EQ(SetAndGetCompany("2019"), "2019");
+  EXPECT_EQ(SetAndGetCompany("2345"), "2345");
+  EXPECT_EQ(SetAndGetCompany("It was 1987."), "It was 1987.");
+  EXPECT_EQ(SetAndGetCompany("1987 was the year."), "1987 was the year.");
+  EXPECT_EQ(SetAndGetCompany("Mr"), "Mr");
+  EXPECT_EQ(SetAndGetCompany("Mr."), "Mr.");
+  EXPECT_EQ(SetAndGetCompany("Mrs"), "Mrs");
+  EXPECT_EQ(SetAndGetCompany("Mrs."), "Mrs.");
+  EXPECT_EQ(SetAndGetCompany("Mr. & Mrs."), "Mr. & Mrs.");
+  EXPECT_EQ(SetAndGetCompany("Mr. & Mrs. Smith"), "Mr. & Mrs. Smith");
+  EXPECT_EQ(SetAndGetCompany("Frau"), "Frau");
+  EXPECT_EQ(SetAndGetCompany("Frau Doktor"), "Frau Doktor");
+  EXPECT_EQ(SetAndGetCompany("Herr"), "Herr");
+  EXPECT_EQ(SetAndGetCompany("Mme"), "Mme");
+  EXPECT_EQ(SetAndGetCompany("Ms"), "Ms");
+  EXPECT_EQ(SetAndGetCompany("Dr"), "Dr");
+  EXPECT_EQ(SetAndGetCompany("Dr."), "Dr.");
+  EXPECT_EQ(SetAndGetCompany("Prof"), "Prof");
+  EXPECT_EQ(SetAndGetCompany("Prof."), "Prof.");
 }
 
-TEST(CompanyTest, CompanyNameSocialTitle) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
-      /*disabled_features=*/{});
-
+TEST(CompanyTest, CompanyNameSocialTitleCopy) {
   AutofillProfile profile;
   CompanyInfo company(&profile);
   ASSERT_FALSE(profile.IsVerified());
 
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
-  EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
-  EXPECT_EQ(UTF8ToUTF16("1987"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("It was 1987."));
-  EXPECT_EQ(UTF8ToUTF16("It was 1987."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987 was the year."));
-  EXPECT_EQ(UTF8ToUTF16("1987 was the year."),
-            company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Yes, 1987 was the year."));
-  EXPECT_EQ(UTF8ToUTF16("Yes, 1987 was the year."),
-            company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
-  EXPECT_EQ(UTF8ToUTF16("2019"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
-  EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
-  EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
-  EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
-  EXPECT_EQ(UTF8ToUTF16(""), company.GetRawInfo(COMPANY_NAME));
-
-  profile.set_origin("Not empty");
-  ASSERT_TRUE(profile.IsVerified());
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
-  EXPECT_EQ(UTF8ToUTF16("Google"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
-  EXPECT_EQ(UTF8ToUTF16("1987"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
-  EXPECT_EQ(UTF8ToUTF16("2019"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1818"));
-  EXPECT_EQ(UTF8ToUTF16("1818"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2345"));
-  EXPECT_EQ(UTF8ToUTF16("2345"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr"));
-  EXPECT_EQ(UTF8ToUTF16("Mr"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr."));
-  EXPECT_EQ(UTF8ToUTF16("Mr."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs"));
-  EXPECT_EQ(UTF8ToUTF16("Mrs"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs."));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs."), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Mr. & Mrs. Smith"));
-  EXPECT_EQ(UTF8ToUTF16("Mr. & Mrs. Smith"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau"));
-  EXPECT_EQ(UTF8ToUTF16("Frau"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Frau Doktor"));
-  EXPECT_EQ(UTF8ToUTF16("Frau Doktor"), company.GetRawInfo(COMPANY_NAME));
-
-  company.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Herr"));
-  EXPECT_EQ(UTF8ToUTF16("Herr"), company.GetRawInfo(COMPANY_NAME));
-}
-
-TEST(CompanyTest, CompanyNameYearCopy) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanyBirthyear},
-      /*disabled_features=*/{});
-
-  AutofillProfile profile;
-  ASSERT_FALSE(profile.IsVerified());
 
   CompanyInfo company_google(&profile);
   CompanyInfo company_year(&profile);
+  CompanyInfo company_social_title(&profile);
 
   company_google.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
   company_year.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
+  company_social_title.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Dr"));
 
   company_google = company_year;
   EXPECT_EQ(UTF8ToUTF16(""), company_google.GetRawInfo(COMPANY_NAME));
+  company_google = company_social_title;
+  EXPECT_EQ(UTF8ToUTF16(""), company_google.GetRawInfo(COMPANY_NAME));
 }
 
 TEST(CompanyTest, CompanyNameYearIsEqual) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanyBirthyear},
-      /*disabled_features=*/{});
-
   AutofillProfile profile;
   ASSERT_FALSE(profile.IsVerified());
 
-  CompanyInfo company_old(&profile);
-  CompanyInfo company_young(&profile);
-
-  company_old.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("2019"));
-  company_young.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
-
-  EXPECT_EQ(company_old, company_young);
-}
-
-TEST(CompanyTest, CompanyNameSocialTitleCopy) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
-      /*disabled_features=*/{});
-
-  AutofillProfile profile;
-  ASSERT_FALSE(profile.IsVerified());
-
-  CompanyInfo company_google(&profile);
   CompanyInfo company_year(&profile);
+  CompanyInfo company_social_title(&profile);
 
-  company_google.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Google"));
-  company_year.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Prof."));
+  company_year.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("1987"));
+  company_social_title.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Dr"));
 
-  company_google = company_year;
-  EXPECT_EQ(UTF8ToUTF16(""), company_google.GetRawInfo(COMPANY_NAME));
-}
-
-TEST(CompanyTest, CompanyNameSocialTitleIsEqual) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillRejectCompanySocialTitle},
-      /*disabled_features=*/{});
-
-  AutofillProfile profile;
-  ASSERT_FALSE(profile.IsVerified());
-
-  CompanyInfo company_old(&profile);
-  CompanyInfo company_young(&profile);
-
-  company_old.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Dr"));
-  company_young.SetRawInfo(COMPANY_NAME, UTF8ToUTF16("Prof"));
-
-  EXPECT_EQ(company_old, company_young);
+  EXPECT_EQ(company_year, company_social_title);
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index f502606..34a8fad 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -210,16 +210,6 @@
 const base::Feature kAutofillProfileServerValidation{
     "AutofillProfileServerValidation", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether autofill rejects using non-verified company names that are
-// in the format of a birthyear.
-const base::Feature kAutofillRejectCompanyBirthyear{
-    "AutofillRejectCompanyBirthyear", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Controls whether autofill rejects using non-verified company names that are
-// social titles (e.g., "Mrs.") in some languages.
-const base::Feature kAutofillRejectCompanySocialTitle{
-    "AutofillRejectCompanySocialTitle", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether or not a group of fields not enclosed in a form can be
 // considered a form. If this is enabled, unowned fields will only constitute
 // a form if there are signals to suggest that this might a checkout page.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index fef87b6..a28ae24 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -57,8 +57,6 @@
 extern const base::Feature kAutofillProfileImportFromUnfocusableFields;
 extern const base::Feature kAutofillProfileImportFromUnifiedSection;
 extern const base::Feature kAutofillProfileServerValidation;
-extern const base::Feature kAutofillRejectCompanyBirthyear;
-extern const base::Feature kAutofillRejectCompanySocialTitle;
 extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
 extern const base::Feature kAutofillRichMetadataQueries;
 extern const base::Feature kAutofillSaveAndFillVPA;
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index a328d3f..8c5333b8 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -1933,14 +1933,14 @@
 }
 
 bool Controller::StateNeedsUI(AutofillAssistantState state) {
-  if (!trigger_context_ || !trigger_context_->is_lite_script()) {
-    return StateNeedsUiInRegularScript(state, browse_mode_invisible_);
+  if (IsRunningLiteScript()) {
+    return StateNeedsUiInLiteScript(state);
   }
-  return StateNeedsUiInLiteScript(state);
+  return StateNeedsUiInRegularScript(state, browse_mode_invisible_);
 }
 
 bool Controller::IsRunningLiteScript() const {
-  return trigger_context_ ? trigger_context_->is_lite_script() : false;
+  return service_ ? service_->IsLiteService() : false;
 }
 
 ElementArea* Controller::touchable_element_area() {
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index 129d8d4..bca09dd1 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -239,6 +239,7 @@
   const GenericUserInterfaceProto* GetGenericUiProto() const override;
   bool ShouldShowOverlay() const override;
   void ShutdownIfNecessary() override;
+  bool IsRunningLiteScript() const override;
 
  private:
   friend ControllerTest;
@@ -341,7 +342,6 @@
   void PerformDelayedShutdownIfNecessary();
 
   bool StateNeedsUI(AutofillAssistantState state);
-  bool IsRunningLiteScript() const;
 
   ClientSettings settings_;
   Client* const client_;
diff --git a/components/autofill_assistant/browser/java_service.cc b/components/autofill_assistant/browser/java_service.cc
index d9d12923c..358f2f7 100644
--- a/components/autofill_assistant/browser/java_service.cc
+++ b/components/autofill_assistant/browser/java_service.cc
@@ -27,6 +27,10 @@
 
 JavaService::~JavaService() {}
 
+bool JavaService::IsLiteService() const {
+  return false;
+}
+
 void JavaService::GetScriptsForUrl(const GURL& url,
                                    const TriggerContext& trigger_context,
                                    ResponseCallback callback) {
diff --git a/components/autofill_assistant/browser/java_service.h b/components/autofill_assistant/browser/java_service.h
index 34d8547..eb5d81c 100644
--- a/components/autofill_assistant/browser/java_service.h
+++ b/components/autofill_assistant/browser/java_service.h
@@ -24,6 +24,8 @@
       const base::android::JavaParamRef<jobject>& java_service);
   ~JavaService() override;
 
+  bool IsLiteService() const override;
+
   // Get scripts for a given |url|, which should be a valid URL.
   void GetScriptsForUrl(const GURL& url,
                         const TriggerContext& trigger_context,
diff --git a/components/autofill_assistant/browser/lite_service.cc b/components/autofill_assistant/browser/lite_service.cc
index a397fcf..54aab20f 100644
--- a/components/autofill_assistant/browser/lite_service.cc
+++ b/components/autofill_assistant/browser/lite_service.cc
@@ -31,6 +31,10 @@
   }
 }
 
+bool LiteService::IsLiteService() const {
+  return true;
+}
+
 void LiteService::GetScriptsForUrl(const GURL& url,
                                    const TriggerContext& trigger_context,
                                    ResponseCallback callback) {
diff --git a/components/autofill_assistant/browser/lite_service.h b/components/autofill_assistant/browser/lite_service.h
index e1a6911..145f5da 100644
--- a/components/autofill_assistant/browser/lite_service.h
+++ b/components/autofill_assistant/browser/lite_service.h
@@ -35,6 +35,8 @@
   LiteService(const LiteService&) = delete;
   LiteService& operator=(const LiteService&) = delete;
 
+  bool IsLiteService() const override;
+
   // |LiteService| will return the hard-coded response without communicating
   // with the backend.
   void GetScriptsForUrl(const GURL& url,
diff --git a/components/autofill_assistant/browser/service.h b/components/autofill_assistant/browser/service.h
index 4611121..02baead 100644
--- a/components/autofill_assistant/browser/service.h
+++ b/components/autofill_assistant/browser/service.h
@@ -22,6 +22,10 @@
  public:
   virtual ~Service() = default;
 
+  // Whether this service is a lite service with limited capabilities, or a
+  // regular service that is allowed to communicate with the backend.
+  virtual bool IsLiteService() const = 0;
+
   using ResponseCallback =
       base::OnceCallback<void(bool result, const std::string&)>;
   // Get scripts for a given |url|, which should be a valid URL.
diff --git a/components/autofill_assistant/browser/service_impl.cc b/components/autofill_assistant/browser/service_impl.cc
index f3fc2a98..8dcc2c85 100644
--- a/components/autofill_assistant/browser/service_impl.cc
+++ b/components/autofill_assistant/browser/service_impl.cc
@@ -148,6 +148,10 @@
       std::move(callback)));
 }
 
+bool ServiceImpl::IsLiteService() const {
+  return false;
+}
+
 void ServiceImpl::GetActions(const std::string& script_path,
                              const GURL& url,
                              const TriggerContext& trigger_context,
diff --git a/components/autofill_assistant/browser/service_impl.h b/components/autofill_assistant/browser/service_impl.h
index 9c6d965..fe6718b 100644
--- a/components/autofill_assistant/browser/service_impl.h
+++ b/components/autofill_assistant/browser/service_impl.h
@@ -41,6 +41,8 @@
   static std::unique_ptr<ServiceImpl> Create(content::BrowserContext* context,
                                              Client* client);
 
+  bool IsLiteService() const override;
+
   // |context| and |access_token_fetcher| must remain valid for the lifetime of
   // the service instance.
   ServiceImpl(content::BrowserContext* context,
diff --git a/components/autofill_assistant/browser/trigger_context.cc b/components/autofill_assistant/browser/trigger_context.cc
index f6e6c7c..83c3a03 100644
--- a/components/autofill_assistant/browser/trigger_context.cc
+++ b/components/autofill_assistant/browser/trigger_context.cc
@@ -16,10 +16,6 @@
 // TODO(b/151401974): Eliminate duplicate parameter definitions.
 const char kPasswordChangeUsernameParameterName[] = "PASSWORD_CHANGE_USERNAME";
 
-// Parameter that contains the path of the lite script currently being run, if
-// any.
-const char kLiteScriptPathParamaterName[] = "TRIGGER_SCRIPT_USED";
-
 // static
 std::unique_ptr<TriggerContext> TriggerContext::CreateEmpty() {
   return std::make_unique<TriggerContextImpl>();
@@ -38,10 +34,6 @@
   return std::make_unique<MergedTriggerContext>(contexts);
 }
 
-bool TriggerContext::is_lite_script() const {
-  return GetParameter(kLiteScriptPathParamaterName).has_value();
-}
-
 TriggerContext::TriggerContext() {}
 TriggerContext::~TriggerContext() {}
 
diff --git a/components/autofill_assistant/browser/trigger_context.h b/components/autofill_assistant/browser/trigger_context.h
index 91129216..aab8dca6 100644
--- a/components/autofill_assistant/browser/trigger_context.h
+++ b/components/autofill_assistant/browser/trigger_context.h
@@ -40,9 +40,6 @@
   // Returns all parameters as a map.
   virtual std::map<std::string, std::string> GetParameters() const = 0;
 
-  // Returns true if this is a lite script run.
-  bool is_lite_script() const;
-
   // Returns the value of a specific parameter, if present.
   virtual base::Optional<std::string> GetParameter(
       const std::string& name) const = 0;
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h
index acc2859f..1c9d3b9 100644
--- a/components/autofill_assistant/browser/ui_delegate.h
+++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -241,9 +241,12 @@
   // hidden.
   virtual bool ShouldShowOverlay() const = 0;
 
-  // Notifies the UI deleagate that it should shut down.
+  // Notifies the UI delegate that it should shut down.
   virtual void ShutdownIfNecessary() = 0;
 
+  // Returns whether the UI delegate is currently running a lite script or not.
+  virtual bool IsRunningLiteScript() const = 0;
+
  protected:
   UiDelegate() = default;
 };
diff --git a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
index b2ab8bf..c4b0c87 100644
--- a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
+++ b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -161,6 +161,13 @@
     /** A means of checking whether accessibility is currently enabled. */
     private AccessibilityUtil mAccessibilityUtil;
 
+    /**
+     * This is the height that the sheet is capable of scrolling through. It extends past the top of
+     * the screen so that the opaque part of the sheet reaches the top of the screen as the shadow
+     * scrolls off.
+     */
+    private int mScrollableHeight;
+
     @Override
     public boolean shouldGestureMoveSheet(MotionEvent initialEvent, MotionEvent currentEvent) {
         // If the sheet is scrolling off-screen or in the process of hiding, gestures should not
@@ -296,6 +303,7 @@
 
         mContainerWidth = root.getWidth();
         mContainerHeight = root.getHeight();
+        mScrollableHeight = mContainerHeight + mToolbarShadowHeight;
 
         // Listen to height changes on the root.
         root.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@@ -310,6 +318,7 @@
                 int previousHeight = mContainerHeight;
                 mContainerWidth = right - left;
                 mContainerHeight = bottom - top;
+                mScrollableHeight = mContainerHeight + mToolbarShadowHeight;
 
                 if (previousWidth != mContainerWidth || previousHeight != mContainerHeight) {
                     if (mCurrentState == SheetState.HALF && !isHalfStateEnabled()) {
@@ -411,7 +420,7 @@
 
     @Override
     public float getMinOffsetPx() {
-        return (swipeToDismissEnabled() ? getHiddenRatio() : getPeekRatio()) * mContainerHeight;
+        return (swipeToDismissEnabled() ? getHiddenRatio() : getPeekRatio()) * mScrollableHeight;
     }
 
     /**
@@ -475,7 +484,7 @@
 
     @Override
     public float getMaxOffsetPx() {
-        return getFullRatio() * mContainerHeight;
+        return getFullRatio() * mScrollableHeight;
     }
 
     /**
@@ -616,7 +625,7 @@
             return 0;
         }
 
-        return getPeekRatio() * mContainerHeight * mBrowserControlsHiddenRatio;
+        return getPeekRatio() * mScrollableHeight * mBrowserControlsHiddenRatio;
     }
 
     /**
@@ -718,7 +727,7 @@
         if (mSheetContent != null && mSheetContent.getPeekHeight() != HeightMode.DEFAULT) {
             assert mSheetContent.getPeekHeight()
                     != HeightMode.WRAP_CONTENT : "The peek mode can't wrap content.";
-            float ratio = mSheetContent.getPeekHeight() / (float) mContainerHeight;
+            float ratio = mSheetContent.getPeekHeight() / (float) mScrollableHeight;
             assert ratio > 0 && ratio <= 1 : "Custom peek ratios must be in the range of (0, 1].";
             return ratio;
         }
@@ -737,12 +746,12 @@
                     toolbarView.measure(
                             MeasureSpec.makeMeasureSpec(mContainerWidth, MeasureSpec.EXACTLY),
                             MeasureSpec.makeMeasureSpec(
-                                    (int) mContainerHeight, MeasureSpec.AT_MOST));
+                                    getMaxContentHeight(), MeasureSpec.AT_MOST));
                     toolbarHeight = toolbarView.getMeasuredHeight();
                 }
             }
         }
-        return (toolbarHeight + mToolbarShadowHeight) / (float) mContainerHeight;
+        return (toolbarHeight + mToolbarShadowHeight) / (float) mScrollableHeight;
     }
 
     private View getToolbarView() {
@@ -779,13 +788,11 @@
         if (isFullHeightWrapContent()) {
             ensureContentDesiredHeightIsComputed();
             float heightPx =
-                    Math.min(mContainerHeight, mContentDesiredHeight + mToolbarShadowHeight);
-            return heightPx / mContainerHeight;
+                    Math.min(getMaxContentHeight(), mContentDesiredHeight) + mToolbarShadowHeight;
+            return heightPx / mScrollableHeight;
         }
 
-        return customFullRatio == HeightMode.DEFAULT
-                ? (mContainerHeight + mToolbarShadowHeight) / (float) mContainerHeight
-                : customFullRatio;
+        return customFullRatio == HeightMode.DEFAULT ? 1 : customFullRatio;
     }
 
     /**
@@ -970,10 +977,14 @@
     private float getSheetHeightForState(@SheetState int state) {
         if (isFullHeightWrapContent() && state == SheetState.FULL) {
             ensureContentDesiredHeightIsComputed();
-            return mContentDesiredHeight + mToolbarShadowHeight;
         }
 
-        return getRatioForState(state) * mContainerHeight;
+        return getRatioForState(state) * mScrollableHeight;
+    }
+
+    /** @return The max possible height that the content can be. */
+    private int getMaxContentHeight() {
+        return mContainerHeight;
     }
 
     private void ensureContentDesiredHeightIsComputed() {
@@ -983,7 +994,7 @@
 
         mSheetContent.getContentView().measure(
                 MeasureSpec.makeMeasureSpec(mContainerWidth, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(mContainerHeight, MeasureSpec.AT_MOST));
+                MeasureSpec.makeMeasureSpec(getMaxContentHeight(), MeasureSpec.AT_MOST));
         mContentDesiredHeight = mSheetContent.getContentView().getMeasuredHeight();
     }
 
@@ -1147,9 +1158,7 @@
         if (sIsSmallScreenForTesting != null) return sIsSmallScreenForTesting;
 
         // A small screen is defined by there being less than 160dp between half and full states.
-        float fullHeightRatio =
-                (mContainerHeight + mToolbarShadowHeight) / (float) mContainerHeight;
-        float fullToHalfDiff = (fullHeightRatio - HALF_HEIGHT_RATIO) * mContainerHeight;
+        float fullToHalfDiff = (1 - HALF_HEIGHT_RATIO) * mScrollableHeight;
         return fullToHalfDiff < mMinHalfFullDistance;
     }
 
diff --git a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
index 88dd095a..3885cfbe 100644
--- a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
+++ b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
@@ -35,12 +35,6 @@
     /** The initial capacity for the priority queue handling pending content show requests. */
     private static final int INITIAL_QUEUE_CAPACITY = 1;
 
-    /** The height of the shadow that sits above the toolbar. */
-    private int mToolbarShadowHeight;
-
-    /** The offset of the toolbar shadow from the top that remains empty. */
-    private int mShadowTopOffset;
-
     /** A handle to the {@link BottomSheet} that this class controls. */
     private BottomSheet mBottomSheet;
 
@@ -114,10 +108,6 @@
 
         mBottomSheet.init(window, keyboardDelegate);
         mBottomSheet.setAccssibilityUtil(mAccessibilityUtil);
-        mToolbarShadowHeight = mBottomSheet.getResources().getDimensionPixelOffset(
-                BottomSheet.getTopShadowResourceId());
-        mShadowTopOffset = mBottomSheet.getResources().getDimensionPixelOffset(
-                BottomSheet.getShadowTopOffsetResourceId());
 
         // Initialize the queue with a comparator that checks content priority.
         mContentQueue = new PriorityQueue<>(INITIAL_QUEUE_CAPACITY,
@@ -296,7 +286,7 @@
 
     @Override
     public int getTopShadowHeight() {
-        return mToolbarShadowHeight + mShadowTopOffset;
+        return mBottomSheet != null ? (int) mBottomSheet.getToolbarShadowHeight() : 0;
     }
 
     @Override
diff --git a/components/embedder_support/BUILD.gn b/components/embedder_support/BUILD.gn
index d17f211..3010fbe7 100644
--- a/components/embedder_support/BUILD.gn
+++ b/components/embedder_support/BUILD.gn
@@ -33,7 +33,6 @@
       "android/util/android_stream_reader_url_loader_unittest.cc",
       "android/util/input_stream_reader_unittest.cc",
       "android/util/input_stream_unittest.cc",
-      "android/util/url_utilities_unittest.cc",
     ]
 
     deps += [
diff --git a/components/embedder_support/android/BUILD.gn b/components/embedder_support/android/BUILD.gn
index 3ebad27..120bd0d 100644
--- a/components/embedder_support/android/BUILD.gn
+++ b/components/embedder_support/android/BUILD.gn
@@ -242,10 +242,7 @@
     "//base:base_java",
     "//third_party/junit",
   ]
-  sources = [
-    "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java",
-    "native_java_unittests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java",
-  ]
+  sources = [ "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java" ]
 
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
@@ -254,10 +251,7 @@
 # can't put 'java' in the name here.
 generate_jni("native_j_unittests_jni_headers") {
   testonly = true
-  sources = [
-    "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java",
-    "native_java_unittests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java",
-  ]
+  sources = [ "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java" ]
 }
 
 android_library("junit_test_support") {
@@ -287,11 +281,15 @@
   ]
 }
 
-android_library("web_contents_delegate_javatests") {
+android_library("embedder_support_javatests") {
   testonly = true
 
-  sources = [ "java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java" ]
+  sources = [
+    "javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java",
+    "javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java",
+  ]
   deps = [
+    ":util_java",
     ":web_contents_delegate_java",
     ":web_contents_delegate_java_resources",
     "//base:base_java",
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
similarity index 100%
rename from components/embedder_support/android/java/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
rename to components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
diff --git a/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
similarity index 92%
rename from components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
rename to components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
index 7330501..078fc2a3 100644
--- a/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
+++ b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
@@ -4,20 +4,31 @@
 
 package org.chromium.components.embedder_support.util;
 
-import org.junit.Assert;
+import androidx.test.filters.SmallTest;
 
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.CalledByNativeJavaTest;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
+import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 
 /**
  * Unit tests for {@link UrlUtilities}.
  */
+@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
 @SuppressWarnings(value = "AuthLeak")
 public class UrlUtilitiesUnitTest {
-    @CalledByNative
-    private UrlUtilitiesUnitTest() {}
+    @Before
+    public void setUp() {
+        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
+    }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testIsHttpOrHttps() {
         Assert.assertTrue(
                 UrlUtilities.isHttpOrHttps("https://user:pass@awesome.com:9000/bad-scheme/#fake"));
@@ -47,7 +58,8 @@
         Assert.assertFalse(UrlUtilities.isHttpOrHttps(""));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testStripPath() {
         Assert.assertEquals("https://example.com:9000",
                 UrlUtilities.stripPath("https://user:pass@example.com:9000/path/#extra"));
@@ -57,7 +69,8 @@
         Assert.assertEquals("http://", UrlUtilities.stripPath("http:"));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testStripScheme() {
         // Only scheme gets stripped.
         Assert.assertEquals("cs.chromium.org", UrlUtilities.stripScheme("https://cs.chromium.org"));
@@ -73,7 +86,8 @@
                 "cs.chromium.org", UrlUtilities.stripScheme("  https://cs.chromium.org  "));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testIsAcceptedScheme() {
         Assert.assertTrue(UrlUtilities.isAcceptedScheme("about:awesome"));
         Assert.assertTrue(UrlUtilities.isAcceptedScheme("data:data"));
@@ -95,7 +109,8 @@
         Assert.assertFalse(UrlUtilities.isAcceptedScheme(""));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testIsDownloadableScheme() {
         Assert.assertTrue(UrlUtilities.isDownloadableScheme("data:data"));
         Assert.assertTrue(UrlUtilities.isDownloadableScheme(
@@ -119,7 +134,8 @@
         Assert.assertFalse(UrlUtilities.isDownloadableScheme(""));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testIsValidForIntentFallbackUrl() {
         Assert.assertTrue(UrlUtilities.isValidForIntentFallbackNavigation(
                 "https://user:pass@awesome.com:9000/bad-scheme:#fake:"));
@@ -134,7 +150,8 @@
         Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation(""));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testIsUrlWithinScope() {
         String scope = "http://www.example.com/sub";
         Assert.assertTrue(UrlUtilities.isUrlWithinScope(scope, scope));
@@ -150,7 +167,8 @@
                 "https://www.google.com.evil.com", "https://www.google.com"));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testUrlsMatchIgnoringFragments() {
         String url = "http://www.example.com/path";
         Assert.assertTrue(UrlUtilities.urlsMatchIgnoringFragments(url, url));
@@ -164,7 +182,8 @@
                 url + "#fragment", "http://example.com:443/path#fragment"));
     }
 
-    @CalledByNativeJavaTest
+    @Test
+    @SmallTest
     public void testUrlsFragmentsDiffer() {
         String url = "http://www.example.com/path";
         Assert.assertFalse(UrlUtilities.urlsFragmentsDiffer(url, url));
diff --git a/components/embedder_support/android/util/url_utilities_unittest.cc b/components/embedder_support/android/util/url_utilities_unittest.cc
deleted file mode 100644
index 26968f5..0000000
--- a/components/embedder_support/android/util/url_utilities_unittest.cc
+++ /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.
-
-#include "base/android/jni_android.h"
-#include "components/embedder_support/android/native_j_unittests_jni_headers/UrlUtilitiesUnitTest_jni.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::android::AttachCurrentThread;
-
-class UrlUtilitiesUnitTest : public ::testing::Test {
- public:
-  UrlUtilitiesUnitTest()
-      : j_test_(Java_UrlUtilitiesUnitTest_Constructor(AttachCurrentThread())) {}
-
-  const base::android::ScopedJavaGlobalRef<jobject>& j_test() {
-    return j_test_;
-  }
-
- private:
-  base::android::ScopedJavaGlobalRef<jobject> j_test_;
-};
-
-JAVA_TESTS(UrlUtilitiesUnitTest, j_test())
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java
index d1a51aa5..e591be97 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java
@@ -32,6 +32,7 @@
     }
 
     private void launchSubpage() {
+        mMainController.recordAction(PageInfoAction.PAGE_INFO_SECURITY_DETAILS_OPENED);
         mMainController.launchSubpage(this);
     }
 
@@ -63,7 +64,7 @@
         rowParams.title = mTitle;
         rowParams.subtitle = params.message != null ? params.message.toString() : null;
         rowParams.visible = rowParams.title != null || rowParams.subtitle != null;
-        rowParams.clickCallback = this::launchSubpage;
+        if (params.clickCallback != null) rowParams.clickCallback = this::launchSubpage;
         mRowView.setParams(rowParams);
     }
 
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
index f844d3ea..fa1272a 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -404,7 +404,7 @@
             messageBuilder.append(details);
         }
 
-        if (isConnectionDetailsLinkVisible()) {
+        if (!mIsV2Enabled && isConnectionDetailsLinkVisible()) {
             messageBuilder.append(" ");
             SpannableString detailsText =
                     new SpannableString(mContext.getString(R.string.details_link));
@@ -480,7 +480,8 @@
         mContext = null;
     }
 
-    private void recordAction(int action) {
+    @Override
+    public void recordAction(@PageInfoAction int action) {
         if (mNativePageInfoController != 0) {
             PageInfoControllerJni.get().recordPageInfoAction(
                     mNativePageInfoController, PageInfoController.this, action);
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java
index 3682cf5..8e5a4b2 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java
@@ -22,6 +22,13 @@
     void exitSubpage();
 
     /**
+     * Record a user action.
+     *
+     * @param action The action to record.
+     */
+    void recordAction(@PageInfoAction int action);
+
+    /**
      * @return A BrowserContext for this dialog.
      */
     BrowserContextHandle getBrowserContext();
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index e5d0b5e..58457c0 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -18,12 +18,10 @@
 config("password_reuse_detection_config") {
   defines = []
   if (password_reuse_detection_support) {
-    # TODO(crbug.com/1036042): Rename it to PASSWORD_REUSE_DETECTION_ENABLED.
-    defines += [ "SYNC_PASSWORD_REUSE_DETECTION_ENABLED" ]
+    defines += [ "PASSWORD_REUSE_DETECTION_ENABLED" ]
   }
   if (password_reuse_warning_support) {
-    # TODO(crbug.com/1036042): Rename it to PASSWORD_REUSE_WARNING_ENABLED.
-    defines += [ "SYNC_PASSWORD_REUSE_WARNING_ENABLED" ]
+    defines += [ "PASSWORD_REUSE_WARNING_ENABLED" ]
   }
   if (password_on_focus_ping_support) {
     defines += [ "ON_FOCUS_PING_ENABLED" ]
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h
index 26ebe0a4..90687a7 100644
--- a/components/password_manager/core/browser/mock_password_store.h
+++ b/components/password_manager/core/browser/mock_password_store.h
@@ -102,7 +102,7 @@
 
   MOCK_CONST_METHOD0(IsAbleToSavePasswords, bool());
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   MOCK_METHOD3(CheckReuse,
                void(const base::string16&,
                     const std::string&,
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 12231c2..d123f6c 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -65,9 +65,9 @@
 using base::NumberToString;
 using BlacklistedStatus =
     password_manager::OriginCredentialStore::BlacklistedStatus;
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 using password_manager::metrics_util::GaiaPasswordHashChange;
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 namespace password_manager {
 
@@ -989,7 +989,7 @@
 
 void PasswordManager::MaybeSavePasswordHash(
     PasswordFormManager* submitted_manager) {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
   // When |username_value| is empty, it's not clear whether the submitted
   // credentials are really Gaia or enterprise credentials. Don't save
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h
index 165d8b5..30cf37a5 100644
--- a/components/password_manager/core/browser/password_manager_client.h
+++ b/components/password_manager/core/browser/password_manager_client.h
@@ -328,8 +328,7 @@
   // Returns the current best guess as to the page's display language.
   virtual std::string GetPageLanguage() const;
 
-#if defined(ON_FOCUS_PING_ENABLED) || \
-    defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Return the PasswordProtectionService associated with this instance.
   virtual safe_browsing::PasswordProtectionService*
   GetPasswordProtectionService() const = 0;
@@ -343,7 +342,7 @@
                                            const GURL& frame_url) = 0;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Checks the safe browsing reputation of the webpage where password reuse
   // happens. This is called by the PasswordReuseDetectionManager when a
   // protected password is typed on the wrong domain. This may trigger a
@@ -358,7 +357,7 @@
       bool password_field_exists) = 0;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   // Records a Chrome Sync event that GAIA password reuse was detected.
   virtual void LogPasswordReuseDetectedEvent() = 0;
 #endif
diff --git a/components/password_manager/core/browser/password_manager_features_util.cc b/components/password_manager/core/browser/password_manager_features_util.cc
index 4447bbd6..7f03692b 100644
--- a/components/password_manager/core/browser/password_manager_features_util.cc
+++ b/components/password_manager/core/browser/password_manager_features_util.cc
@@ -305,7 +305,9 @@
 
 bool ShouldShowAccountStorageBubbleUi(const PrefService* pref_service,
                                       const syncer::SyncService* sync_service) {
-  return !sync_service->IsSyncFeatureEnabled() &&
+  // `sync_service` is null in incognito mode, or if --disable-sync was
+  // specified on the command-line.
+  return sync_service && !sync_service->IsSyncFeatureEnabled() &&
          (IsOptedInForAccountStorage(pref_service, sync_service) ||
           IsUserEligibleForAccountStorage(sync_service));
 }
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc
index 5bb73efc..a9d424ee 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.cc
+++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -286,7 +286,7 @@
   };
 }  // namespace metrics_util
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void LogGaiaPasswordHashChange(GaiaPasswordHashChange event,
                                bool is_sync_password) {
   if (is_sync_password) {
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h
index 6dfc5ca..96a20e2 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.h
+++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -259,7 +259,7 @@
   kMaxValue = kEncryptionUnavailable,
 };
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 enum class GaiaPasswordHashChange {
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused.
@@ -567,7 +567,7 @@
     GenerationDialogChoice choice,
     autofill::password_generation::PasswordGenerationType type);
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 // Log a save gaia password change event.
 void LogGaiaPasswordHashChange(GaiaPasswordHashChange event,
                                bool is_sync_password);
diff --git a/components/password_manager/core/browser/password_manager_test_utils.cc b/components/password_manager/core/browser/password_manager_test_utils.cc
index c07d493..a67c72a 100644
--- a/components/password_manager/core/browser/password_manager_test_utils.cc
+++ b/components/password_manager/core/browser/password_manager_test_utils.cc
@@ -123,7 +123,7 @@
 
 MockPasswordStoreObserver::~MockPasswordStoreObserver() = default;
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 MockPasswordReuseDetectorConsumer::MockPasswordReuseDetectorConsumer() =
     default;
 
diff --git a/components/password_manager/core/browser/password_manager_test_utils.h b/components/password_manager/core/browser/password_manager_test_utils.h
index e53078c0..3acccc4 100644
--- a/components/password_manager/core/browser/password_manager_test_utils.h
+++ b/components/password_manager/core/browser/password_manager_test_utils.h
@@ -16,7 +16,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "components/password_manager/core/browser/password_hash_data.h"  // nogncheck
 #include "components/password_manager/core/browser/password_reuse_detector_consumer.h"  // nogncheck
 #endif
@@ -111,7 +111,7 @@
   MOCK_METHOD1(OnLoginsChanged, void(const PasswordStoreChangeList& changes));
 };
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 class MockPasswordReuseDetectorConsumer : public PasswordReuseDetectorConsumer {
  public:
   MockPasswordReuseDetectorConsumer();
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index bf6a589..3a18c20 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -1353,7 +1353,7 @@
   // User should not be prompted and password should not be saved.
   EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
   EXPECT_CALL(*store_, AddLogin(_)).Times(0);
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
       .WillByDefault(Return(true));
   ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
@@ -1375,7 +1375,7 @@
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 TEST_P(PasswordManagerTest, HashSavedOnGaiaFormWithSkipSavePassword) {
   for (bool did_stop_loading : {false, true}) {
     SCOPED_TRACE(testing::Message("did_stop_loading = ") << did_stop_loading);
@@ -1512,7 +1512,7 @@
   EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
       .WillRepeatedly(Return(true));
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
       .WillByDefault(Return(true));
   ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
@@ -2389,7 +2389,7 @@
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 // Check that no sync password hash is saved when no username is available,
 // because we it's not clear whether the submitted credentials are sync
 // credentials.
@@ -2585,7 +2585,7 @@
   EXPECT_CALL(client_, IsSavingAndFillingEnabled(form_data.url))
       .WillRepeatedly(Return(true));
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
       .WillByDefault(Return(true));
   ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
@@ -2604,7 +2604,7 @@
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 // Non-Sync Gaia password hash should be saved upon submission of Gaia login
 // page.
 TEST_P(PasswordManagerTest, SaveOtherGaiaPasswordHash) {
diff --git a/components/password_manager/core/browser/password_reuse_detection_manager.cc b/components/password_manager/core/browser/password_reuse_detection_manager.cc
index bb4dcd1..d20577388 100644
--- a/components/password_manager/core/browser/password_reuse_detection_manager.cc
+++ b/components/password_manager/core/browser/password_reuse_detection_manager.cc
@@ -152,13 +152,13 @@
   metrics_util::LogPasswordReuse(password_length, saved_passwords,
                                  matching_reused_credentials.size(),
                                  password_field_detected, reused_password_type);
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   if (reused_password_type ==
       metrics_util::PasswordType::PRIMARY_ACCOUNT_PASSWORD)
     client_->LogPasswordReuseDetectedEvent();
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   std::string username = reused_protected_password_hash.has_value()
                              ? reused_protected_password_hash->username
                              : "";
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index 56b8483..fd47c9a 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -41,7 +41,7 @@
 #include "components/sync/model_impl/client_tag_based_model_type_processor.h"
 #include "components/sync/model_impl/proxy_model_type_controller_delegate.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "base/strings/string16.h"
 #include "components/password_manager/core/browser/password_store_signin_notifier.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
@@ -94,7 +94,7 @@
   OnCompromisedCredentialsChanged();
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 PasswordStore::CheckReuseRequest::CheckReuseRequest(
     PasswordReuseDetectorConsumer* consumer)
     : origin_task_runner_(base::SequencedTaskRunnerHandle::Get()),
@@ -157,7 +157,7 @@
   DCHECK(background_task_runner_);
   sync_enabled_or_disabled_cb_ = std::move(sync_enabled_or_disabled_cb);
   prefs_ = prefs;
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   hash_password_manager_.set_prefs(prefs);
 #endif
   if (background_task_runner_) {
@@ -340,7 +340,7 @@
                                              base::TimeDelta::FromSeconds(30));
   }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   if (!sync_username.empty()) {
     auto hash_password_state =
         hash_password_manager_.HasPasswordHash(sync_username,
@@ -516,7 +516,7 @@
   // The AffiliationService must be destroyed from the main sequence.
   affiliated_match_helper_.reset();
   shutdown_called_ = true;
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   if (notifier_)
     notifier_->UnsubscribeFromSigninEvents();
 #endif
@@ -548,7 +548,7 @@
   sync_task_timeout_ = timeout;
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void PasswordStore::CheckReuse(const base::string16& input,
                                const std::string& domain,
                                PasswordReuseDetectorConsumer* consumer) {
@@ -558,7 +558,7 @@
 }
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void PasswordStore::PreparePasswordHashData(const std::string& sync_username,
                                             const bool is_signed_in) {
   SchedulePasswordHashUpdate(/*should_log_metrics=*/true,
@@ -692,7 +692,7 @@
           syncer::PASSWORDS, base::DoNothing()),
       /*password_store_sync=*/this, sync_enabled_or_disabled_cb_));
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   reuse_detector_ = new PasswordReuseDetector;
 
   base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -747,7 +747,7 @@
     if (sync_bridge_)
       sync_bridge_->ActOnPasswordStoreChanges(changes);
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
     if (reuse_detector_)
       reuse_detector_->OnLoginsChanged(changes);
 #endif
@@ -812,7 +812,7 @@
   }
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void PasswordStore::CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
                                    const base::string16& input,
                                    const std::string& domain) {
@@ -1376,7 +1376,7 @@
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   sync_bridge_.reset();
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   delete reuse_detector_;
   reuse_detector_ = nullptr;
 #endif
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index d43b170..7d445ca 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -27,7 +27,7 @@
 #include "components/password_manager/core/browser/password_store_change.h"
 #include "components/password_manager/core/browser/password_store_sync.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "components/password_manager/core/browser/hash_password_manager.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_reuse_detector.h"
@@ -53,7 +53,7 @@
 
 using IsAccountStore = util::StrongAlias<class IsAccountStoreTag, bool>;
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 using metrics_util::GaiaPasswordHashChange;
 #endif
 
@@ -66,7 +66,7 @@
 struct InteractionsStats;
 struct CompromisedCredentials;
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 using PasswordHashDataList = base::Optional<std::vector<PasswordHashData>>;
 #endif
 
@@ -379,7 +379,7 @@
 
   void SetSyncTaskTimeoutForTest(base::TimeDelta timeout);
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Immediately called after |Init()| to retrieve password hash data for
   // reuse detection.
   void PreparePasswordHashData(const std::string& sync_username,
@@ -453,7 +453,7 @@
  protected:
   friend class base::RefCountedThreadSafe<PasswordStore>;
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Represents a single CheckReuse() request. Implements functionality to
   // listen to reuse events and propagate them to |consumer| on the sequence on
   // which CheckReuseRequest is created.
@@ -631,7 +631,7 @@
   void InvokeAndNotifyAboutCompromisedPasswordsChange(
       base::OnceCallback<bool()> callback);
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // Saves |username| and a hash of |password| for password reuse checking.
   // |is_gaia_password| indicates if it is a Gaia account. |event| is used for
   // metric logging. |is_primary_account| is whether account belong to the
@@ -901,7 +901,7 @@
   std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_;
 
   PrefService* prefs_ = nullptr;
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   // PasswordReuseDetector can be only destroyed on the background sequence. It
   // can't be owned by PasswordStore because PasswordStore can be destroyed on
   // the UI thread and DestroyOnBackgroundThread isn't guaranteed to be called.
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index b4f6e8e4..4dc1ed8 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -1180,7 +1180,7 @@
   store->ShutdownOnUIThread();
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 TEST_F(PasswordStoreTest, CheckPasswordReuse) {
   static constexpr PasswordFormData kTestCredentials[] = {
       {PasswordForm::Scheme::kHtml, "https://www.google.com",
diff --git a/components/password_manager/core/browser/password_sync_util.cc b/components/password_manager/core/browser/password_sync_util.cc
index 6d903aee..064eb4d7 100644
--- a/components/password_manager/core/browser/password_sync_util.cc
+++ b/components/password_manager/core/browser/password_sync_util.cc
@@ -14,9 +14,9 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "url/origin.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 using autofill::PasswordForm;
 using url::Origin;
@@ -88,13 +88,13 @@
 
 bool ShouldSaveEnterprisePasswordHash(const autofill::PasswordForm& form,
                                       const PrefService& prefs) {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   return safe_browsing::MatchesPasswordProtectionLoginURL(form.url, prefs) ||
          safe_browsing::MatchesPasswordProtectionChangePasswordURL(form.url,
                                                                    prefs);
 #else
   return false;
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 }
 
 }  // namespace sync_util
diff --git a/components/password_manager/core/browser/password_sync_util_unittest.cc b/components/password_manager/core/browser/password_sync_util_unittest.cc
index 6bcea0fc..b18a853e 100644
--- a/components/password_manager/core/browser/password_sync_util_unittest.cc
+++ b/components/password_manager/core/browser/password_sync_util_unittest.cc
@@ -15,9 +15,9 @@
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"  // nogncheck
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 using autofill::PasswordForm;
 using base::ASCIIToUTF16;
@@ -135,7 +135,7 @@
   }
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 class PasswordSyncUtilEnterpriseTest : public SyncUsernameTestBase {
  public:
   void SetUp() override {
@@ -149,7 +149,7 @@
   TestingPrefServiceSimple prefs_;
 };
 
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 }  // namespace sync_util
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/site_affiliation/affiliation_service_impl.cc b/components/password_manager/core/browser/site_affiliation/affiliation_service_impl.cc
index 57ff5d7..d8799358 100644
--- a/components/password_manager/core/browser/site_affiliation/affiliation_service_impl.cc
+++ b/components/password_manager/core/browser/site_affiliation/affiliation_service_impl.cc
@@ -4,6 +4,7 @@
 
 #include "components/password_manager/core/browser/site_affiliation/affiliation_service_impl.h"
 
+#include "base/util/ranges/algorithm.h"
 #include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher.h"
 #include "components/password_manager/core/browser/password_store_factory_util.h"
 #include "components/sync/driver/sync_service.h"
@@ -13,6 +14,37 @@
 
 namespace password_manager {
 
+namespace {
+
+// Creates a look-up (Facet URI : change password URL) map for facets from
+// requested |groupings|. If a facet does not have change password URL it gets
+// paired with another facet's URL, which belongs to the same group. In case
+// none of the group's facets have change password URLs then those facets are
+// not inserted to the map.
+std::map<FacetURI, GURL> CreateFacetUriToChangePasswordUrlMap(
+    const std::vector<GroupedFacets>& groupings) {
+  std::map<FacetURI, GURL> uri_to_url;
+  for (const auto& grouped_facets : groupings) {
+    std::vector<FacetURI> uris_without_urls;
+    GURL fallback_url;
+    for (const auto& facet : grouped_facets) {
+      if (!facet.change_password_url.is_valid()) {
+        uris_without_urls.push_back(facet.uri);
+        continue;
+      }
+      uri_to_url[facet.uri] = facet.change_password_url;
+      fallback_url = facet.change_password_url;
+    }
+    if (fallback_url.is_valid()) {
+      for (const auto& uri : uris_without_urls)
+        uri_to_url[uri] = fallback_url;
+    }
+  }
+  return uri_to_url;
+}
+
+}  // namespace
+
 AffiliationServiceImpl::AffiliationServiceImpl(
     syncer::SyncService* sync_service,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
@@ -42,11 +74,30 @@
 }
 
 void AffiliationServiceImpl::OnFetchSucceeded(
-    std::unique_ptr<AffiliationFetcherDelegate::Result> result) {}
+    std::unique_ptr<AffiliationFetcherDelegate::Result> result) {
+  fetcher_.reset();
 
-void AffiliationServiceImpl::OnFetchFailed() {}
+  std::map<FacetURI, GURL> uri_to_url =
+      CreateFacetUriToChangePasswordUrlMap(result->groupings);
+  for (const url::SchemeHostPort& requested_tuple : requested_tuple_origins_) {
+    auto it = uri_to_url.find(
+        FacetURI::FromPotentiallyInvalidSpec(requested_tuple.Serialize()));
+    if (it != uri_to_url.end())
+      change_password_urls_[requested_tuple] = it->second;
+  }
 
-void AffiliationServiceImpl::OnMalformedResponse() {}
+  requested_tuple_origins_.clear();
+}
+
+void AffiliationServiceImpl::OnFetchFailed() {
+  fetcher_.reset();
+  requested_tuple_origins_.clear();
+}
+
+void AffiliationServiceImpl::OnMalformedResponse() {
+  fetcher_.reset();
+  requested_tuple_origins_.clear();
+}
 
 std::vector<FacetURI>
 AffiliationServiceImpl::ConvertMissingSchemeHostPortsToFacets(
diff --git a/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc b/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
index c65f68c8..d372a54 100644
--- a/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
+++ b/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
@@ -23,15 +23,18 @@
 
 namespace {
 
-constexpr char kTestUrlChar1[] = "https://1.example.com";
-constexpr char kTestUrlChar2[] = "https://2.example.com";
-constexpr char kTestUrlChar3[] = "https://3.example.com";
-constexpr char kTestUrlChar4[] = "https://4.example.com";
-constexpr char kTestUrlChar5[] = "https://5.example.com";
-
-url::SchemeHostPort ToSchemeHostPort(const std::string& url) {
-  return url::SchemeHostPort(GURL(url));
-}
+constexpr char kEmptyURL[] = "";
+constexpr char k1ExampleURL[] = "https://1.example.com";
+constexpr char k1ExampleChangePasswordURL[] =
+    "https://1.example.com/.well-known/change-password";
+constexpr char kM1ExampleURL[] = "https://m.1.example.com";
+constexpr char kOneExampleURL[] = "https://one.example.com";
+constexpr char kOneExampleChangePasswordURL[] =
+    "https://one.example.com/settings/passwords";
+constexpr char k2ExampleURL[] = "https://2.example.com";
+constexpr char k3ExampleURL[] = "https://3.example.com";
+constexpr char k4ExampleURL[] = "https://4.example.com";
+constexpr char k5ExampleURL[] = "https://5.example.com";
 
 std::vector<FacetURI> SchemeHostPortsToFacetsURIs(
     const std::vector<url::SchemeHostPort>& scheme_host_ports) {
@@ -91,18 +94,18 @@
 };
 
 TEST_F(AffiliationServiceImplTest, GetChangePasswordURLReturnsEmpty) {
-  auto scheme_host_port = ToSchemeHostPort(kTestUrlChar1);
-
-  EXPECT_EQ(GURL(), service()->GetChangePasswordURL(scheme_host_port));
+  EXPECT_EQ(GURL(), service()->GetChangePasswordURL(
+                        url::SchemeHostPort(GURL(k1ExampleURL))));
 }
 
 TEST_F(AffiliationServiceImplTest, ClearStopsOngoingAffiliationFetcherRequest) {
-  auto tuple_origins = {ToSchemeHostPort(kTestUrlChar1),
-                        ToSchemeHostPort(kTestUrlChar2)};
   MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
-
   EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
       .WillOnce(Return(mock_fetcher));
+
+  const std::vector<url::SchemeHostPort> tuple_origins = {
+      url::SchemeHostPort(GURL(k1ExampleURL)),
+      url::SchemeHostPort(GURL(k2ExampleURL))};
   EXPECT_CALL(*mock_fetcher,
               StartRequest(SchemeHostPortsToFacetsURIs(tuple_origins),
                            AffiliationFetcherInterface::RequestInfo{
@@ -116,17 +119,149 @@
 }
 
 TEST_F(AffiliationServiceImplTest,
-       EachPrefetchCallCreatesNewAffiliationFetcherInstance) {
-  auto scheme_host_port1 = ToSchemeHostPort(kTestUrlChar1);
-  auto scheme_host_port2 = ToSchemeHostPort(kTestUrlChar2);
-  auto scheme_host_port3 = ToSchemeHostPort(kTestUrlChar3);
-  auto scheme_host_port4 = ToSchemeHostPort(kTestUrlChar4);
-  auto scheme_host_port5 = ToSchemeHostPort(kTestUrlChar5);
+       OnFetchSuccededInsertsChangePasswordURLOfRequestedSiteIfFound) {
+  const url::SchemeHostPort scheme_host_port{GURL(k1ExampleURL)};
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
 
-  auto tuple_origins_1 = {scheme_host_port1, scheme_host_port2,
-                          scheme_host_port3};
-  auto tuple_origins_2 = {scheme_host_port3, scheme_host_port4,
-                          scheme_host_port5};
+  EXPECT_CALL(*mock_fetcher,
+              StartRequest(SchemeHostPortsToFacetsURIs({scheme_host_port}),
+                           AffiliationFetcherInterface::RequestInfo{
+                               .change_password_info = true}));
+  EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
+      .WillOnce(Return(mock_fetcher));
+
+  service()->PrefetchChangePasswordURLs({scheme_host_port});
+
+  const GroupedFacets group = {
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(k1ExampleURL),
+       .change_password_url = GURL(k1ExampleChangePasswordURL)},
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(kM1ExampleURL),
+       .change_password_url = GURL(kEmptyURL)},
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(kOneExampleURL),
+       .change_password_url = GURL(kOneExampleChangePasswordURL)}};
+  auto test_result = std::make_unique<AffiliationFetcherDelegate::Result>();
+  test_result->groupings.push_back(group);
+  AffiliationFetcherDelegate* service_delegate = service();
+  service_delegate->OnFetchSucceeded(std::move(test_result));
+
+  // Expect Change Password URL of requested site.
+  EXPECT_EQ(GURL(k1ExampleChangePasswordURL),
+            service()->GetChangePasswordURL(scheme_host_port));
+}
+
+TEST_F(AffiliationServiceImplTest,
+       OnFetchSuccededInsertsChangePasswordURLOfAnotherSiteFromAGroup) {
+  const url::SchemeHostPort scheme_host_port{GURL(kM1ExampleURL)};
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
+
+  EXPECT_CALL(*mock_fetcher,
+              StartRequest(SchemeHostPortsToFacetsURIs({scheme_host_port}),
+                           AffiliationFetcherInterface::RequestInfo{
+                               .change_password_info = true}));
+  EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
+      .WillOnce(Return(mock_fetcher));
+
+  service()->PrefetchChangePasswordURLs({scheme_host_port});
+
+  const GroupedFacets group = {
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(k1ExampleURL),
+       .change_password_url = GURL(k1ExampleChangePasswordURL)},
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(kM1ExampleURL),
+       .change_password_url = GURL(kEmptyURL)}};
+  auto test_result = std::make_unique<AffiliationFetcherDelegate::Result>();
+  test_result->groupings.push_back(group);
+  AffiliationFetcherDelegate* service_delegate = service();
+  service_delegate->OnFetchSucceeded(std::move(test_result));
+
+  // Expect Change Password URL of another site from a grouping.
+  EXPECT_EQ(GURL(k1ExampleChangePasswordURL),
+            service()->GetChangePasswordURL(scheme_host_port));
+}
+
+TEST_F(AffiliationServiceImplTest,
+       OnFetchSucceedTakesNoActionWhenNoChangePasswordURLsAvailable) {
+  const url::SchemeHostPort scheme_host_port{GURL(k1ExampleURL)};
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
+
+  EXPECT_CALL(*mock_fetcher,
+              StartRequest(SchemeHostPortsToFacetsURIs({scheme_host_port}),
+                           AffiliationFetcherInterface::RequestInfo{
+                               .change_password_info = true}));
+  EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
+      .WillOnce(Return(mock_fetcher));
+
+  service()->PrefetchChangePasswordURLs({scheme_host_port});
+
+  const GroupedFacets group = {
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(k1ExampleURL),
+       .change_password_url = GURL()},
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(kM1ExampleURL),
+       .change_password_url = GURL()},
+      {.uri = FacetURI::FromPotentiallyInvalidSpec(kOneExampleURL),
+       .change_password_url = GURL()}};
+  auto test_result = std::make_unique<AffiliationFetcherDelegate::Result>();
+  test_result->groupings.push_back(group);
+  AffiliationFetcherDelegate* service_delegate = service();
+  service_delegate->OnFetchSucceeded(std::move(test_result));
+
+  EXPECT_EQ(GURL(), service()->GetChangePasswordURL(scheme_host_port));
+}
+
+TEST_F(AffiliationServiceImplTest, OnFetchFailedResetsFetcher) {
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
+  AffiliationFetcherDelegate* service_delegate = service();
+
+  EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
+      .WillOnce(Return(mock_fetcher));
+
+  std::vector<url::SchemeHostPort> tuple_origins = {
+      url::SchemeHostPort(GURL(k1ExampleURL)),
+      url::SchemeHostPort(GURL(k2ExampleURL))};
+  EXPECT_CALL(*mock_fetcher,
+              StartRequest(SchemeHostPortsToFacetsURIs(tuple_origins),
+                           AffiliationFetcherInterface::RequestInfo{
+                               .change_password_info = true}));
+
+  service()->PrefetchChangePasswordURLs(tuple_origins);
+  EXPECT_NE(nullptr, service()->GetFetcherForTesting());
+
+  service_delegate->OnFetchFailed();
+  EXPECT_EQ(nullptr, service()->GetFetcherForTesting());
+}
+
+TEST_F(AffiliationServiceImplTest, OnMalformedResponseResetsFetcher) {
+  std::vector<url::SchemeHostPort> tuple_origins = {
+      url::SchemeHostPort(GURL(k1ExampleURL)),
+      url::SchemeHostPort(GURL(k2ExampleURL))};
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
+  AffiliationFetcherDelegate* service_delegate = service();
+
+  EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
+      .WillOnce(Return(mock_fetcher));
+  EXPECT_CALL(*mock_fetcher,
+              StartRequest(SchemeHostPortsToFacetsURIs(tuple_origins),
+                           AffiliationFetcherInterface::RequestInfo{
+                               .change_password_info = true}));
+
+  service()->PrefetchChangePasswordURLs(tuple_origins);
+  EXPECT_NE(nullptr, service()->GetFetcherForTesting());
+
+  service_delegate->OnMalformedResponse();
+  EXPECT_EQ(nullptr, service()->GetFetcherForTesting());
+}
+
+TEST_F(AffiliationServiceImplTest,
+       EachPrefetchCallCreatesNewAffiliationFetcherInstance) {
+  const url::SchemeHostPort scheme_host_port1{GURL(k1ExampleURL)};
+  const url::SchemeHostPort scheme_host_port2{GURL(k2ExampleURL)};
+  const url::SchemeHostPort scheme_host_port3{GURL(k3ExampleURL)};
+  const url::SchemeHostPort scheme_host_port4{GURL(k4ExampleURL)};
+  const url::SchemeHostPort scheme_host_port5{GURL(k5ExampleURL)};
+
+  const std::vector<url::SchemeHostPort> tuple_origins_1 = {
+      scheme_host_port1, scheme_host_port2, scheme_host_port3};
+  const std::vector<url::SchemeHostPort> tuple_origins_2 = {
+      scheme_host_port3, scheme_host_port4, scheme_host_port5};
   MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
   MockAffiliationFetcher* new_mock_fetcher = new MockAffiliationFetcher();
   AffiliationFetcher::RequestInfo request_info{.change_password_info = true};
@@ -147,15 +282,16 @@
 
 TEST_F(AffiliationServiceImplTest,
        FetchRequiresCompleteSetupAndPassphraseDisabled) {
-  auto tuple_origins = {ToSchemeHostPort(kTestUrlChar1),
-                        ToSchemeHostPort(kTestUrlChar2)};
-  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
-
   // The only scenario when the StartRequest() should be called.
   // Setup is completed and secondary passphrase feature is disabled.
   SetSyncServiceStates(/*is_setup_completed=*/true,
                        /*is_passphrase_set=*/false);
 
+  const std::vector<url::SchemeHostPort> tuple_origins = {
+      url::SchemeHostPort(GURL(k1ExampleURL)),
+      url::SchemeHostPort(GURL(k2ExampleURL))};
+  MockAffiliationFetcher* mock_fetcher = new MockAffiliationFetcher();
+
   EXPECT_CALL(*mock_fetcher_factory(), CreateInstance)
       .WillOnce(Return(mock_fetcher));
   EXPECT_CALL(*mock_fetcher,
@@ -167,24 +303,24 @@
 }
 
 TEST_F(AffiliationServiceImplTest, SecondaryPassphraseSetPreventsFetch) {
-  auto tuple_origins = {ToSchemeHostPort(kTestUrlChar1),
-                        ToSchemeHostPort(kTestUrlChar2)};
   SetSyncServiceStates(/*is_setup_completed=*/true, /*is_passphrase_set=*/true);
 
   EXPECT_CALL(*mock_fetcher_factory(), CreateInstance).Times(0);
 
-  service()->PrefetchChangePasswordURLs(tuple_origins);
+  service()->PrefetchChangePasswordURLs(
+      {url::SchemeHostPort(GURL(k1ExampleURL)),
+       url::SchemeHostPort(GURL(k2ExampleURL))});
 }
 
 TEST_F(AffiliationServiceImplTest, SetupNotCompletedPreventsFetch) {
-  auto tuple_origins = {ToSchemeHostPort(kTestUrlChar1),
-                        ToSchemeHostPort(kTestUrlChar2)};
   SetSyncServiceStates(/*is_setup_completed=*/false,
                        /*is_passphrase_set=*/false);
 
   EXPECT_CALL(*mock_fetcher_factory(), CreateInstance).Times(0);
 
-  service()->PrefetchChangePasswordURLs(tuple_origins);
+  service()->PrefetchChangePasswordURLs(
+      {url::SchemeHostPort(GURL(k1ExampleURL)),
+       url::SchemeHostPort(GURL(k2ExampleURL))});
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/stub_password_manager_client.cc b/components/password_manager/core/browser/stub_password_manager_client.cc
index f4a1683..33205d9 100644
--- a/components/password_manager/core/browser/stub_password_manager_client.cc
+++ b/components/password_manager/core/browser/stub_password_manager_client.cc
@@ -103,8 +103,7 @@
   return &password_feature_manager_;
 }
 
-#if defined(ON_FOCUS_PING_ENABLED) || \
-    defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
 safe_browsing::PasswordProtectionService*
 StubPasswordManagerClient::GetPasswordProtectionService() const {
   return nullptr;
@@ -117,7 +116,7 @@
     const GURL& frame_url) {}
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void StubPasswordManagerClient::CheckProtectedPasswordEntry(
     metrics_util::PasswordType reused_password_type,
     const std::string& username,
@@ -125,7 +124,7 @@
     bool password_field_exists) {}
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 void StubPasswordManagerClient::LogPasswordReuseDetectedEvent() {}
 #endif
 
diff --git a/components/password_manager/core/browser/stub_password_manager_client.h b/components/password_manager/core/browser/stub_password_manager_client.h
index 129e34ee6..4ab3267f 100644
--- a/components/password_manager/core/browser/stub_password_manager_client.h
+++ b/components/password_manager/core/browser/stub_password_manager_client.h
@@ -66,8 +66,7 @@
   const MockPasswordFeatureManager* GetPasswordFeatureManager() const override;
   MockPasswordFeatureManager* GetPasswordFeatureManager();
 
-#if defined(ON_FOCUS_PING_ENABLED) || \
-    defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
   safe_browsing::PasswordProtectionService* GetPasswordProtectionService()
       const override;
 #endif
@@ -77,7 +76,7 @@
                                    const GURL& frame_url) override;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   void CheckProtectedPasswordEntry(
       metrics_util::PasswordType reused_password_type,
       const std::string& username,
@@ -85,7 +84,7 @@
       bool password_field_exists) override;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   void LogPasswordReuseDetectedEvent() override;
 #endif
 
diff --git a/components/password_manager/core/browser/sync_credentials_filter.cc b/components/password_manager/core/browser/sync_credentials_filter.cc
index eab37a3..ca3a657 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter.cc
@@ -69,12 +69,12 @@
 
 bool SyncCredentialsFilter::ShouldSaveGaiaPasswordHash(
     const autofill::PasswordForm& form) const {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   return !client_->IsIncognito() &&
          sync_util::IsGaiaCredentialPage(form.signon_realm);
 #else
   return false;
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 }
 
 bool SyncCredentialsFilter::ShouldSaveEnterprisePasswordHash(
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 9b5fbca..9aa7b68 100644
--- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -32,9 +32,9 @@
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"  // nogncheck
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 using autofill::PasswordForm;
 
@@ -45,15 +45,15 @@
 const char kFilledAndLoginActionName[] =
     "PasswordManager_SyncCredentialFilledAndLoginSuccessfull";
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 const char kEnterpriseURL[] = "https://enterprise.test/";
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 class FakePasswordManagerClient : public StubPasswordManagerClient {
  public:
   explicit FakePasswordManagerClient(signin::IdentityManager* identity_manager)
       : identity_manager_(identity_manager) {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
     // Initializes and configures prefs.
     prefs_ = std::make_unique<TestingPrefServiceSimple>();
     prefs_->registry()->RegisterStringPref(
@@ -61,7 +61,7 @@
     prefs_->registry()->RegisterListPref(prefs::kPasswordProtectionLoginURLs);
     prefs_->SetString(prefs::kPasswordProtectionChangePasswordURL,
                       kEnterpriseURL);
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
   }
 
   ~FakePasswordManagerClient() override {
@@ -83,7 +83,7 @@
     last_committed_origin_ = url::Origin::Create(GURL(url_spec));
   }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   PrefService* GetPrefs() const override { return prefs_.get(); }
 #endif
 
@@ -97,9 +97,9 @@
       new testing::NiceMock<MockPasswordStore>;
   bool is_incognito_ = false;
   signin::IdentityManager* identity_manager_;
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   std::unique_ptr<TestingPrefServiceSimple> prefs_;
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
   DISALLOW_COPY_AND_ASSIGN(FakePasswordManagerClient);
 };
@@ -269,7 +269,7 @@
     EXPECT_TRUE(filter_.ShouldSave(form));
 }
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 TEST_P(CredentialsFilterTest, ShouldSaveGaiaPasswordHash) {
   PasswordForm gaia_form = SimpleGaiaForm("user@gmail.org");
   EXPECT_TRUE(filter_.ShouldSaveGaiaPasswordHash(gaia_form));
@@ -332,7 +332,7 @@
   EXPECT_TRUE(filter_.IsSyncAccountEmail("us.er@gmail.com"));
   EXPECT_TRUE(filter_.IsSyncAccountEmail("user@googlemail.com"));
 }
-#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
+#endif  // PASSWORD_REUSE_DETECTION_ENABLED
 
 INSTANTIATE_TEST_SUITE_P(, CredentialsFilterTest, ::testing::Bool());
 
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn
index 08051f7..6a02d3e 100644
--- a/components/payments/content/BUILD.gn
+++ b/components/payments/content/BUILD.gn
@@ -61,6 +61,7 @@
     "//components/strings:components_strings_grit",
     "//components/ukm/content",
     "//components/url_formatter",
+    "//components/webdata/common",
     "//content/public/browser",
     "//device/fido",
     "//third_party/blink/public:blink_headers",
diff --git a/components/payments/content/android_payment_app_factory_unittest.cc b/components/payments/content/android_payment_app_factory_unittest.cc
index c540926..4f53c6a5 100644
--- a/components/payments/content/android_payment_app_factory_unittest.cc
+++ b/components/payments/content/android_payment_app_factory_unittest.cc
@@ -84,6 +84,7 @@
                void(const std::string& error_message));
   MOCK_CONST_METHOD0(SkipCreatingNativePaymentApps, bool());
   MOCK_METHOD0(OnDoneCreatingPaymentApps, void());
+  MOCK_METHOD0(SetCanMakePaymentEvenWithoutApps, void());
 
   base::WeakPtr<PaymentAppFactory::Delegate> GetWeakPtr() {
     return weak_ptr_factory_.GetWeakPtr();
diff --git a/components/payments/content/payment_app_factory.h b/components/payments/content/payment_app_factory.h
index 7169ac3..d31696a 100644
--- a/components/payments/content/payment_app_factory.h
+++ b/components/payments/content/payment_app_factory.h
@@ -91,6 +91,14 @@
 
     // Called when all apps of this factory have been created.
     virtual void OnDoneCreatingPaymentApps() = 0;
+
+    // Make both canMakePayment() and hasEnrolledInstrument() return true,
+    // regardless of presence of payment apps. This is used by secure payment
+    // confirmation method, which returns true for canMakePayment() and
+    // hasEnrolledInstrument() regardless of presence of credentials in user
+    // profile or the authenticator device, as long as a user-verifying platform
+    // authenticator device is available.
+    virtual void SetCanMakePaymentEvenWithoutApps() = 0;
   };
 
   explicit PaymentAppFactory(PaymentApp::Type type);
diff --git a/components/payments/content/payment_manifest_web_data_service.cc b/components/payments/content/payment_manifest_web_data_service.cc
index 8294b9e..7842bf4 100644
--- a/components/payments/content/payment_manifest_web_data_service.cc
+++ b/components/payments/content/payment_manifest_web_data_service.cc
@@ -4,10 +4,13 @@
 
 #include "components/payments/content/payment_manifest_web_data_service.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/location.h"
 #include "components/payments/content/payment_method_manifest_table.h"
 #include "components/payments/content/web_app_manifest_section_table.h"
+#include "components/payments/core/secure_payment_confirmation_instrument.h"
 #include "components/webdata/common/web_data_results.h"
 #include "components/webdata/common/web_database_service.h"
 
@@ -108,6 +111,51 @@
           payment_method));
 }
 
+WebDataServiceBase::Handle
+PaymentManifestWebDataService::AddSecurePaymentConfirmationInstrument(
+    std::unique_ptr<SecurePaymentConfirmationInstrument> instrument,
+    WebDataServiceConsumer* consumer) {
+  DCHECK(instrument);
+  return wdbs_->ScheduleDBTaskWithResult(
+      FROM_HERE,
+      base::BindOnce(&PaymentManifestWebDataService::
+                         AddSecurePaymentConfirmationInstrumentImpl,
+                     this, std::move(instrument)),
+      consumer);
+}
+
+std::unique_ptr<WDTypedResult>
+PaymentManifestWebDataService::AddSecurePaymentConfirmationInstrumentImpl(
+    std::unique_ptr<SecurePaymentConfirmationInstrument> instrument,
+    WebDatabase* db) {
+  return std::make_unique<WDResult<bool>>(
+      BOOL_RESULT, PaymentMethodManifestTable::FromWebDatabase(db)
+                       ->AddSecurePaymentConfirmationInstrument(*instrument));
+}
+
+WebDataServiceBase::Handle
+PaymentManifestWebDataService::GetSecurePaymentConfirmationInstruments(
+    std::vector<std::vector<uint8_t>> credential_ids,
+    WebDataServiceConsumer* consumer) {
+  return wdbs_->ScheduleDBTaskWithResult(
+      FROM_HERE,
+      base::BindOnce(&PaymentManifestWebDataService::
+                         GetSecurePaymentConfirmationInstrumentsImpl,
+                     this, std::move(credential_ids)),
+      consumer);
+}
+
+std::unique_ptr<WDTypedResult>
+PaymentManifestWebDataService::GetSecurePaymentConfirmationInstrumentsImpl(
+    std::vector<std::vector<uint8_t>> credential_ids,
+    WebDatabase* db) {
+  return std::make_unique<WDResult<
+      std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>>>(
+      SECURE_PAYMENT_CONFIRMATION,
+      PaymentMethodManifestTable::FromWebDatabase(db)
+          ->GetSecurePaymentConfirmationInstruments(std::move(credential_ids)));
+}
+
 void PaymentManifestWebDataService::RemoveExpiredData(WebDatabase* db) {
   PaymentMethodManifestTable::FromWebDatabase(db)->RemoveExpiredData();
   WebAppManifestSectionTable::FromWebDatabase(db)->RemoveExpiredData();
diff --git a/components/payments/content/payment_manifest_web_data_service.h b/components/payments/content/payment_manifest_web_data_service.h
index e81845e9..91ef2a42 100644
--- a/components/payments/content/payment_manifest_web_data_service.h
+++ b/components/payments/content/payment_manifest_web_data_service.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_MANIFEST_WEB_DATA_SERVICE_H_
 #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_MANIFEST_WEB_DATA_SERVICE_H_
 
+#include <stdint.h>
+
 #include <memory>
 #include <vector>
 
@@ -23,6 +25,8 @@
 
 namespace payments {
 
+struct SecurePaymentConfirmationInstrument;
+
 // Web data service to read/write data in WebAppManifestSectionTable and
 // PaymentMethodManifestTable.
 class PaymentManifestWebDataService : public WebDataServiceBase {
@@ -31,23 +35,40 @@
       scoped_refptr<WebDatabaseService> wdbs,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
 
-  // Adds the web app |manifest|.
+  // Adds the web app `manifest`.
   void AddPaymentWebAppManifest(std::vector<WebAppManifestSection> manifest);
 
-  // Adds the |payment_method|'s manifest.
+  // Adds the `payment_method`'s manifest.
   void AddPaymentMethodManifest(const std::string& payment_method,
                                 std::vector<std::string> app_package_names);
 
-  // Gets the |web_app|'s manifest.
+  // Gets the `web_app`'s manifest and  returns it to the `consumer`, which must
+  // outlive the DB operation, because DB tasks cannot be cancelled.
   WebDataServiceBase::Handle GetPaymentWebAppManifest(
       const std::string& web_app,
       WebDataServiceConsumer* consumer);
 
-  // Gets the |payment_method|'s manifest.
+  // Gets the `payment_method`'s manifest and returns it the `consumer`, which
+  // must outlive the DB operation, because DB tasks cannot be cancelled.
   WebDataServiceBase::Handle GetPaymentMethodManifest(
       const std::string& payment_method,
       WebDataServiceConsumer* consumer);
 
+  // Adds the secure payment confirmation `instrument` and returns a boolean
+  // status to the `consumer`, which must outlive the DB operation, because DB
+  // tasks cannot be cancelled. The `instrument` should not be null.
+  WebDataServiceBase::Handle AddSecurePaymentConfirmationInstrument(
+      std::unique_ptr<SecurePaymentConfirmationInstrument> instrument,
+      WebDataServiceConsumer* consumer);
+
+  // Gets the secure payment confirmation instrument information for the given
+  // `credential_ids` and returns it to the `consumer`, which must outlive the
+  // DB operation, because DB tasks cannot be cancelled. Please use
+  // `std::move()` for `credential_ids` parameter to avoid extra copies.
+  WebDataServiceBase::Handle GetSecurePaymentConfirmationInstruments(
+      std::vector<std::vector<uint8_t>> credential_ids,
+      WebDataServiceConsumer* consumer);
+
  private:
   ~PaymentManifestWebDataService() override;
 
@@ -60,6 +81,9 @@
       const std::string& payment_method,
       const std::vector<std::string>& app_package_names,
       WebDatabase* db);
+  std::unique_ptr<WDTypedResult> AddSecurePaymentConfirmationInstrumentImpl(
+      std::unique_ptr<SecurePaymentConfirmationInstrument> instrument,
+      WebDatabase* db);
 
   std::unique_ptr<WDTypedResult> GetPaymentWebAppManifestImpl(
       const std::string& web_app,
@@ -67,6 +91,9 @@
   std::unique_ptr<WDTypedResult> GetPaymentMethodManifestImpl(
       const std::string& payment_method,
       WebDatabase* db);
+  std::unique_ptr<WDTypedResult> GetSecurePaymentConfirmationInstrumentsImpl(
+      std::vector<std::vector<uint8_t>> credential_ids,
+      WebDatabase* db);
 
   DISALLOW_COPY_AND_ASSIGN(PaymentManifestWebDataService);
 };
diff --git a/components/payments/content/payment_method_manifest_table.cc b/components/payments/content/payment_method_manifest_table.cc
index cc0cb0f..03e9ce6 100644
--- a/components/payments/content/payment_method_manifest_table.cc
+++ b/components/payments/content/payment_method_manifest_table.cc
@@ -8,6 +8,7 @@
 
 #include "base/notreached.h"
 #include "base/time/time.h"
+#include "components/payments/core/secure_payment_confirmation_instrument.h"
 #include "components/webdata/common/web_database.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
@@ -27,9 +28,9 @@
 
 }  // namespace
 
-PaymentMethodManifestTable::PaymentMethodManifestTable() {}
+PaymentMethodManifestTable::PaymentMethodManifestTable() = default;
 
-PaymentMethodManifestTable::~PaymentMethodManifestTable() {}
+PaymentMethodManifestTable::~PaymentMethodManifestTable() = default;
 
 PaymentMethodManifestTable* PaymentMethodManifestTable::FromWebDatabase(
     WebDatabase* db) {
@@ -45,7 +46,20 @@
   if (!db_->Execute("CREATE TABLE IF NOT EXISTS payment_method_manifest ( "
                     "expire_date INTEGER NOT NULL DEFAULT 0, "
                     "method_name VARCHAR, "
-                    "web_app_id VARCHAR) ")) {
+                    "web_app_id VARCHAR)")) {
+    NOTREACHED();
+    return false;
+  }
+
+  // The `credential_id` column is 20 bytes for UbiKey on Linux, but the size
+  // can vary for different authenticators. The relatively small sizes make it
+  // OK to make `credential_id` the primary key.
+  if (!db_->Execute(
+          "CREATE TABLE IF NOT EXISTS secure_payment_confirmation_instrument ( "
+          "credential_id BLOB NOT NULL PRIMARY KEY, "
+          "relying_party_id VARCHAR NOT NULL, "
+          "label VARCHAR NOT NULL, "
+          "icon BLOB NOT NULL)")) {
     NOTREACHED();
     return false;
   }
@@ -66,7 +80,7 @@
 void PaymentMethodManifestTable::RemoveExpiredData() {
   const time_t now_date_in_seconds = base::Time::NowFromSystemTime().ToTimeT();
   sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM payment_method_manifest WHERE expire_date < ? "));
+      "DELETE FROM payment_method_manifest WHERE expire_date < ?"));
   s.BindInt64(0, now_date_in_seconds);
   s.Run();
 }
@@ -79,7 +93,7 @@
     return false;
 
   sql::Statement s1(db_->GetUniqueStatement(
-      "DELETE FROM payment_method_manifest WHERE method_name=? "));
+      "DELETE FROM payment_method_manifest WHERE method_name=?"));
   s1.BindString(0, payment_method);
   if (!s1.Run())
     return false;
@@ -87,7 +101,7 @@
   sql::Statement s2(
       db_->GetUniqueStatement("INSERT INTO payment_method_manifest "
                               "(expire_date, method_name, web_app_id) "
-                              "VALUES (?, ?, ?) "));
+                              "VALUES (?, ?, ?)"));
   const time_t expire_date_in_seconds =
       base::Time::NowFromSystemTime().ToTimeT() +
       PAYMENT_METHOD_MANIFEST_VALID_TIME_IN_SECONDS;
@@ -123,4 +137,112 @@
   return web_app_ids;
 }
 
+bool PaymentMethodManifestTable::AddSecurePaymentConfirmationInstrument(
+    const SecurePaymentConfirmationInstrument& instrument) {
+  if (!instrument.IsValid())
+    return false;
+
+  sql::Transaction transaction(db_);
+  if (!transaction.Begin())
+    return false;
+
+  {
+    // Check for credential identifier reuse by a different relying party.
+    sql::Statement s0(
+        db_->GetUniqueStatement("SELECT label "
+                                "FROM secure_payment_confirmation_instrument "
+                                "WHERE credential_id=? "
+                                "AND relying_party_id<>?"));
+    int index = 0;
+    if (!s0.BindBlob(index++, instrument.credential_id.data(),
+                     instrument.credential_id.size()))
+      return false;
+
+    if (!s0.BindString(index++, instrument.relying_party_id))
+      return false;
+
+    if (s0.Step())
+      return false;
+  }
+
+  {
+    sql::Statement s1(db_->GetUniqueStatement(
+        "DELETE FROM secure_payment_confirmation_instrument "
+        "WHERE credential_id=?"));
+    if (!s1.BindBlob(0, instrument.credential_id.data(),
+                     instrument.credential_id.size()))
+      return false;
+
+    if (!s1.Run())
+      return false;
+  }
+
+  {
+    sql::Statement s2(db_->GetUniqueStatement(
+        "INSERT INTO secure_payment_confirmation_instrument "
+        "(credential_id, relying_party_id, label, icon) "
+        "VALUES (?, ?, ?, ?)"));
+    int index = 0;
+    if (!s2.BindBlob(index++, instrument.credential_id.data(),
+                     instrument.credential_id.size()))
+      return false;
+
+    if (!s2.BindString(index++, instrument.relying_party_id))
+      return false;
+
+    if (!s2.BindString16(index++, instrument.label))
+      return false;
+
+    if (!s2.BindBlob(index++, instrument.icon.data(), instrument.icon.size()))
+      return false;
+
+    if (!s2.Run())
+      return false;
+  }
+
+  if (!transaction.Commit())
+    return false;
+
+  return true;
+}
+
+std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>
+PaymentMethodManifestTable::GetSecurePaymentConfirmationInstruments(
+    std::vector<std::vector<uint8_t>> credential_ids) {
+  std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>> instruments;
+  sql::Statement s(
+      db_->GetUniqueStatement("SELECT relying_party_id, label, icon "
+                              "FROM secure_payment_confirmation_instrument "
+                              "WHERE credential_id=?"));
+  // The `credential_id` temporary variable is not `const` because of the
+  // `std::move()` on line 231.
+  for (auto& credential_id : credential_ids) {
+    s.Reset(true);
+    if (credential_id.empty())
+      continue;
+
+    if (!s.BindBlob(0, credential_id.data(), credential_id.size()))
+      continue;
+
+    if (!s.Step())
+      continue;
+
+    auto instrument = std::make_unique<SecurePaymentConfirmationInstrument>();
+    instrument->credential_id = std::move(credential_id);
+
+    int index = 0;
+    instrument->relying_party_id = s.ColumnString(index++);
+    instrument->label = s.ColumnString16(index++);
+    if (!s.ColumnBlobAsVector(index++, &instrument->icon))
+      continue;
+
+    if (!instrument->IsValid())
+      continue;
+
+    instruments.push_back(std::move(instrument));
+  }
+
+  return instruments;
+}
+
 }  // namespace payments
diff --git a/components/payments/content/payment_method_manifest_table.h b/components/payments/content/payment_method_manifest_table.h
index c994345..f2eadb7 100644
--- a/components/payments/content/payment_method_manifest_table.h
+++ b/components/payments/content/payment_method_manifest_table.h
@@ -5,36 +5,51 @@
 #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_METHOD_MANIFEST_TABLE_H_
 #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_METHOD_MANIFEST_TABLE_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
+#include "base/strings/string16.h"
 #include "components/webdata/common/web_database_table.h"
 
 class WebDatabase;
 
 namespace payments {
 
-// This class manages payment_method_manifest table in SQLite database. It
-// expects the following schema.
+struct SecurePaymentConfirmationInstrument;
+
+// This class manages Web Payment tables in SQLite database. It expects the
+// following schema.
 //
-// payment_method_manifest The table stores WebAppManifestSection.id of the
+// payment_method_manifest This table stores WebAppManifestSection.id of the
 //                         supported web app in this payment method manifest.
 //                         Note that a payment method manifest might contain
 //                         multiple supported web apps ids.
 //
-//  expire_date            The expire date in seconds from 1601-01-01 00:00:00
+//   expire_date           The expire date in seconds from 1601-01-01 00:00:00
 //                         UTC.
-//  method_name            The method name.
-//  web_app_id             The supported web app id.
+//   method_name           The method name.
+//   web_app_id            The supported web app id.
 //                         (WebAppManifestSection.id).
 //
+// secure_payment_confirmation_instrument
+//                         This table stores instrument information for secure
+//                         payment confirmation method.
+//
+//   credential_id         The WebAuthn credential identifier blob. Primary key.
+//   relying_party_id      The relying party identifier string.
+//   label                 The instrument human-readable label string.
+//   icon                  The serialized SkBitmap blob.
 class PaymentMethodManifestTable : public WebDatabaseTable {
  public:
   PaymentMethodManifestTable();
   ~PaymentMethodManifestTable() override;
 
-  // Retrieves the PaymentMethodManifestTable* owned by |db|.
+  PaymentMethodManifestTable(const PaymentMethodManifestTable& other) = delete;
+  PaymentMethodManifestTable& operator=(
+      const PaymentMethodManifestTable& other) = delete;
+
+  // Retrieves the PaymentMethodManifestTable* owned by `db`.
   static PaymentMethodManifestTable* FromWebDatabase(WebDatabase* db);
 
   // WebDatabaseTable:
@@ -46,17 +61,39 @@
   // Remove expired data.
   void RemoveExpiredData();
 
-  // Adds |payment_method|'s manifest. |web_app_ids| contains supported web apps
+  // Adds `payment_method`'s manifest. `web_app_ids` contains supported web apps
   // ids.
   bool AddManifest(const std::string& payment_method,
                    const std::vector<std::string>& web_app_ids);
 
-  // Gets manifest for |payment_method|. Return empty vector if no manifest
+  // Gets manifest for `payment_method`. Return empty vector if no manifest
   // exists for this method.
   std::vector<std::string> GetManifest(const std::string& payment_method);
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(PaymentMethodManifestTable);
+  // Adds a secure payment confirmation `instrument`. All existing data for the
+  // instrument's (relying_party_id, credential_id) tuple is erased before the
+  // new data is added.
+  //
+  // Each field in the `instrument` should be non-empty and `relying_party_id`
+  // field should be a valid domain string. See:
+  // https://url.spec.whatwg.org/#valid-domain-string
+  //
+  // Returns false for invalid data, e.g., credential reuse between relying
+  // parties, or on failure.
+  bool AddSecurePaymentConfirmationInstrument(
+      const SecurePaymentConfirmationInstrument& instrument);
+
+  // Gets the list of secure payment confirmation instruments for the given list
+  // of `credential_ids`.
+  //
+  // Returns an empty vector when no data is found or when a read error occurs.
+  // Does not return invalid instruments.
+  //
+  // Please use `std::move()` for `credential_ids` parameter to avoid extra
+  // copies.
+  std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>
+  GetSecurePaymentConfirmationInstruments(
+      std::vector<std::vector<uint8_t>> credential_ids);
 };
 
 }  // namespace payments
diff --git a/components/payments/content/payment_method_manifest_table_unittest.cc b/components/payments/content/payment_method_manifest_table_unittest.cc
index a3d2c1a..199c6c07e 100644
--- a/components/payments/content/payment_method_manifest_table_unittest.cc
+++ b/components/payments/content/payment_method_manifest_table_unittest.cc
@@ -4,21 +4,77 @@
 
 #include "components/payments/content/payment_method_manifest_table.h"
 
+#include <stdint.h>
+
 #include <memory>
+#include <utility>
+#include <vector>
 
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/payments/core/secure_payment_confirmation_instrument.h"
 #include "components/webdata/common/web_database.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace payments {
 namespace {
 
+// Creates an icon for testing.
+std::vector<uint8_t> CreateIcon(uint8_t first_byte = 0) {
+  std::vector<uint8_t> icon;
+  icon.push_back(first_byte++);
+  icon.push_back(first_byte++);
+  icon.push_back(first_byte++);
+  icon.push_back(first_byte);
+  return icon;
+}
+
+// Creates one credential identifier for testing.
+std::vector<uint8_t> CreateCredentialId(uint8_t first_byte = 0) {
+  std::vector<uint8_t> credential_id;
+  credential_id.push_back(first_byte++);
+  credential_id.push_back(first_byte++);
+  credential_id.push_back(first_byte++);
+  credential_id.push_back(first_byte);
+  return credential_id;
+}
+
+// Creates a list of one credential identifier for testing.
+std::vector<std::vector<uint8_t>> CreateCredentialIdList(
+    uint8_t first_byte = 0) {
+  std::vector<std::vector<uint8_t>> credential_ids;
+  credential_ids.push_back(CreateCredentialId(first_byte));
+  return credential_ids;
+}
+
+void ExpectOneValidInstrument(
+    const std::vector<uint8_t>& credential_id,
+    const std::string& relying_party_id,
+    const std::string& label,
+    const std::vector<uint8_t>& icon,
+    std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>
+        instruments) {
+  ASSERT_EQ(1U, instruments.size());
+  ASSERT_NE(nullptr, instruments.back());
+  ASSERT_TRUE(instruments.back()->IsValid());
+  EXPECT_EQ(credential_id, instruments.back()->credential_id);
+  EXPECT_EQ(relying_party_id, instruments.back()->relying_party_id);
+  EXPECT_EQ(base::ASCIIToUTF16(label), instruments.back()->label);
+  EXPECT_EQ(icon, instruments.back()->icon);
+}
+
 class PaymentMethodManifestTableTest : public testing::Test {
  public:
-  PaymentMethodManifestTableTest() {}
-  ~PaymentMethodManifestTableTest() override {}
+  PaymentMethodManifestTableTest() = default;
+  ~PaymentMethodManifestTableTest() override = default;
+
+  PaymentMethodManifestTableTest(const PaymentMethodManifestTableTest& other) =
+      delete;
+  PaymentMethodManifestTableTest& operator=(
+      const PaymentMethodManifestTableTest& other) = delete;
 
  protected:
   void SetUp() override {
@@ -31,15 +87,10 @@
     ASSERT_EQ(sql::INIT_OK, db_->Init(file_));
   }
 
-  void TearDown() override {}
-
   base::FilePath file_;
   base::ScopedTempDir temp_dir_;
   std::unique_ptr<PaymentMethodManifestTable> table_;
   std::unique_ptr<WebDatabase> db_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PaymentMethodManifestTableTest);
 };
 
 TEST_F(PaymentMethodManifestTableTest, GetNonExistManifest) {
@@ -116,5 +167,175 @@
   ASSERT_TRUE(base::Contains(alicepay_web_app_ids, web_app_ids[1]));
 }
 
+TEST_F(PaymentMethodManifestTableTest, GetNonExistingInstrument) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+  EXPECT_TRUE(
+      table->GetSecurePaymentConfirmationInstruments(CreateCredentialIdList())
+          .empty());
+
+  EXPECT_TRUE(table->GetSecurePaymentConfirmationInstruments({}).empty());
+
+  EXPECT_TRUE(
+      table->GetSecurePaymentConfirmationInstruments({std::vector<uint8_t>()})
+          .empty());
+}
+
+TEST_F(PaymentMethodManifestTableTest, AddAndGetOneValidInstrument) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label"), CreateIcon())));
+
+  auto instruments =
+      table->GetSecurePaymentConfirmationInstruments(CreateCredentialIdList());
+
+  ExpectOneValidInstrument({0, 1, 2, 3}, "relying-party.example",
+                           "Instrument label", {0, 1, 2, 3},
+                           std::move(instruments));
+
+  EXPECT_TRUE(table->GetSecurePaymentConfirmationInstruments({}).empty());
+  EXPECT_TRUE(
+      table->GetSecurePaymentConfirmationInstruments({std::vector<uint8_t>()})
+          .empty());
+}
+
+TEST_F(PaymentMethodManifestTableTest, AddingInvalidInstrumentReturnsFalse) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+
+  // An empty credential.
+  EXPECT_FALSE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          /*credential_id=*/{}, "relying-party.example",
+          base::ASCIIToUTF16("Instrument label"), CreateIcon())));
+
+  // Empty relying party identifier.
+  EXPECT_FALSE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(), /*relying_party_id=*/"",
+          base::ASCIIToUTF16("Instrument label"), CreateIcon())));
+
+  // Empty label.
+  EXPECT_FALSE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(), "relying-party.example",
+          /*label=*/base::string16(), CreateIcon())));
+
+  // Empty icon.
+  EXPECT_FALSE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label"), {})));
+}
+
+TEST_F(PaymentMethodManifestTableTest, UpdatingInstrumentReturnsTrue) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/0), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label 1"),
+          CreateIcon(/*first_byte=*/0))));
+
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/0), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label 2"),
+          CreateIcon(/*first_byte=*/4))));
+
+  auto instruments = table->GetSecurePaymentConfirmationInstruments(
+      CreateCredentialIdList(/*first_byte=*/0));
+  ExpectOneValidInstrument({0, 1, 2, 3}, "relying-party.example",
+                           "Instrument label 2", {4, 5, 6, 7},
+                           std::move(instruments));
+}
+
+TEST_F(PaymentMethodManifestTableTest,
+       DifferentRelyingPartiesCannotUseSameCredentialIdentifier) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/0), "relying-party-1.example",
+          base::ASCIIToUTF16("Instrument label 1"),
+          CreateIcon(/*first_byte=*/0))));
+
+  EXPECT_FALSE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/0), "relying-party-2.example",
+          base::ASCIIToUTF16("Instrument label 2"),
+          CreateIcon(/*first_byte=*/4))));
+
+  auto instruments = table->GetSecurePaymentConfirmationInstruments(
+      CreateCredentialIdList(/*first_byte=*/0));
+  ExpectOneValidInstrument({0, 1, 2, 3}, "relying-party-1.example",
+                           "Instrument label 1", {0, 1, 2, 3},
+                           std::move(instruments));
+}
+
+TEST_F(PaymentMethodManifestTableTest, RelyingPartyCanHaveMultipleCredentials) {
+  PaymentMethodManifestTable* table =
+      PaymentMethodManifestTable::FromWebDatabase(db_.get());
+
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/0), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label 1"),
+          CreateIcon(/*first_byte=*/0))));
+
+  EXPECT_TRUE(table->AddSecurePaymentConfirmationInstrument(
+      SecurePaymentConfirmationInstrument(
+          CreateCredentialId(/*first_byte=*/4), "relying-party.example",
+          base::ASCIIToUTF16("Instrument label 2"),
+          CreateIcon(/*first_byte=*/4))));
+
+  auto instruments = table->GetSecurePaymentConfirmationInstruments(
+      CreateCredentialIdList(/*first_byte=*/0));
+
+  ExpectOneValidInstrument({0, 1, 2, 3}, "relying-party.example",
+                           "Instrument label 1", {0, 1, 2, 3},
+                           std::move(instruments));
+
+  instruments = table->GetSecurePaymentConfirmationInstruments(
+      CreateCredentialIdList(/*first_byte=*/4));
+
+  ExpectOneValidInstrument({4, 5, 6, 7}, "relying-party.example",
+                           "Instrument label 2", {4, 5, 6, 7},
+                           std::move(instruments));
+
+  std::vector<std::vector<uint8_t>> credential_ids;
+  credential_ids.push_back(CreateCredentialId(/*first_byte=*/0));
+  credential_ids.push_back(CreateCredentialId(/*first_byte=*/4));
+
+  instruments =
+      table->GetSecurePaymentConfirmationInstruments(std::move(credential_ids));
+
+  ASSERT_EQ(2U, instruments.size());
+
+  ASSERT_NE(nullptr, instruments.front());
+  ASSERT_TRUE(instruments.front()->IsValid());
+  std::vector<uint8_t> expected_credential_id = {0, 1, 2, 3};
+  EXPECT_EQ(expected_credential_id, instruments.front()->credential_id);
+  EXPECT_EQ("relying-party.example", instruments.front()->relying_party_id);
+  EXPECT_EQ(base::ASCIIToUTF16("Instrument label 1"),
+            instruments.front()->label);
+  std::vector<uint8_t> expected_icon = {0, 1, 2, 3};
+  EXPECT_EQ(expected_icon, instruments.front()->icon);
+
+  ASSERT_NE(nullptr, instruments.back());
+  ASSERT_TRUE(instruments.back()->IsValid());
+  expected_credential_id = {4, 5, 6, 7};
+  EXPECT_EQ(expected_credential_id, instruments.back()->credential_id);
+  EXPECT_EQ("relying-party.example", instruments.back()->relying_party_id);
+  EXPECT_EQ(base::ASCIIToUTF16("Instrument label 2"),
+            instruments.back()->label);
+  expected_icon = {4, 5, 6, 7};
+  EXPECT_EQ(expected_icon, instruments.back()->icon);
+}
+
 }  // namespace
 }  // namespace payments
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 68fe121..ec2f1d2 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -227,11 +227,12 @@
 
   // Fulfill the pending CanMakePayment call.
   if (can_make_payment_callback_)
-    std::move(can_make_payment_callback_).Run(are_requested_methods_supported_);
+    std::move(can_make_payment_callback_).Run(GetCanMakePaymentValue());
 
   // Fulfill the pending HasEnrolledInstrument call.
   if (has_enrolled_instrument_callback_)
-    std::move(has_enrolled_instrument_callback_).Run(has_enrolled_instrument_);
+    std::move(has_enrolled_instrument_callback_)
+        .Run(GetHasEnrolledInstrumentValue());
 
   // Fulfill the pending AreRequestedMethodsSupported call.
   if (are_requested_methods_supported_callback_)
@@ -239,6 +240,10 @@
         std::move(are_requested_methods_supported_callback_));
 }
 
+void PaymentRequestState::SetCanMakePaymentEvenWithoutApps() {
+  can_make_payment_even_without_apps_ = true;
+}
+
 void PaymentRequestState::OnPaymentResponseReady(
     mojom::PaymentResponsePtr payment_response) {
   if (!delegate_)
@@ -305,7 +310,7 @@
     return;
   }
 
-  PostStatusCallback(std::move(callback), has_enrolled_instrument_);
+  PostStatusCallback(std::move(callback), GetHasEnrolledInstrumentValue());
 }
 
 void PaymentRequestState::AreRequestedMethodsSupported(
@@ -754,4 +759,13 @@
   return !payment_request_delegate_->GetTwaPackageName().empty();
 }
 
+bool PaymentRequestState::GetCanMakePaymentValue() const {
+  return are_requested_methods_supported_ ||
+         can_make_payment_even_without_apps_;
+}
+
+bool PaymentRequestState::GetHasEnrolledInstrumentValue() const {
+  return has_enrolled_instrument_ || can_make_payment_even_without_apps_;
+}
+
 }  // namespace payments
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h
index 00d6458..762b864 100644
--- a/components/payments/content/payment_request_state.h
+++ b/components/payments/content/payment_request_state.h
@@ -151,6 +151,7 @@
   void OnPaymentAppCreationError(const std::string& error_message) override;
   bool SkipCreatingNativePaymentApps() const override;
   void OnDoneCreatingPaymentApps() override;
+  void SetCanMakePaymentEvenWithoutApps() override;
 
   // PaymentResponseHelper::Delegate
   void OnPaymentResponseReady(
@@ -350,6 +351,9 @@
   // Returns whether the browser is currently in a TWA.
   bool IsInTwa() const;
 
+  bool GetCanMakePaymentValue() const;
+  bool GetHasEnrolledInstrumentValue() const;
+
   content::WebContents* web_contents_;
   content::RenderFrameHost* initiator_render_frame_host_;
   const GURL top_origin_;
@@ -426,6 +430,15 @@
   // Whether PaymentRequest.show() was invoked with a user gesture.
   bool is_show_user_gesture_ = false;
 
+  // If set to true, then both GetCanMakePaymentValue() and
+  // GetHasEnrolledInstrumentValue() will return true, regardless of presence of
+  // payment apps. This is used by secure payment confirmation, where
+  // PaymentRequest.canMakePayment() and PaymentRequesthasEnrolledInstrument()
+  // calls in JavaScript both return true without querying the SQLite database
+  // for instrument information and without querying the authenticator for
+  // credentials.
+  bool can_make_payment_even_without_apps_ = false;
+
   base::WeakPtrFactory<PaymentRequestState> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(PaymentRequestState);
diff --git a/components/payments/content/secure_payment_confirmation_app.cc b/components/payments/content/secure_payment_confirmation_app.cc
index fc1c0e73..ef1bca885 100644
--- a/components/payments/content/secure_payment_confirmation_app.cc
+++ b/components/payments/content/secure_payment_confirmation_app.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/base64.h"
 #include "base/check.h"
 #include "base/containers/flat_tree.h"
 #include "base/notreached.h"
@@ -30,7 +31,7 @@
     const std::string& effective_relying_party_identity,
     std::unique_ptr<SkBitmap> icon,
     const base::string16& label,
-    std::vector<std::unique_ptr<std::vector<uint8_t>>> credential_ids,
+    std::vector<uint8_t> credential_id,
     const url::Origin& merchant_origin,
     const mojom::PaymentCurrencyAmountPtr& total,
     mojom::SecurePaymentConfirmationRequestPtr request,
@@ -39,14 +40,13 @@
       effective_relying_party_identity_(effective_relying_party_identity),
       icon_(std::move(icon)),
       label_(label),
-      credential_ids_(std::move(credential_ids)),
+      credential_id_(std::move(credential_id)),
+      encoded_credential_id_(base::Base64Encode(credential_id_)),
       merchant_origin_(merchant_origin),
       total_(total.Clone()),
       request_(std::move(request)),
       authenticator_(std::move(authenticator)) {
-  DCHECK(!credential_ids_.empty());
-  DCHECK(credential_ids_.front());
-  DCHECK(!credential_ids_.front()->empty());
+  DCHECK(!credential_id_.empty());
 
   app_method_names_.insert(methods::kSecurePaymentConfirmation);
 }
@@ -55,11 +55,9 @@
 
 void SecurePaymentConfirmationApp::InvokePaymentApp(Delegate* delegate) {
   std::vector<device::PublicKeyCredentialDescriptor> credentials;
-  for (const auto& credential_id : credential_ids_) {
-    credentials.emplace_back(device::CredentialType::kPublicKey, *credential_id,
-                             base::flat_set<device::FidoTransportProtocol>{
-                                 device::FidoTransportProtocol::kInternal});
-  }
+  credentials.emplace_back(device::CredentialType::kPublicKey, credential_id_,
+                           base::flat_set<device::FidoTransportProtocol>{
+                               device::FidoTransportProtocol::kInternal});
 
   auto options = blink::mojom::PublicKeyCredentialRequestOptions::New();
   options->relying_party_id = effective_relying_party_identity_;
@@ -119,7 +117,7 @@
 }
 
 std::string SecurePaymentConfirmationApp::GetId() const {
-  return request_->instrument_id;
+  return encoded_credential_id_;
 }
 
 base::string16 SecurePaymentConfirmationApp::GetLabel() const {
diff --git a/components/payments/content/secure_payment_confirmation_app.h b/components/payments/content/secure_payment_confirmation_app.h
index 80ee44a3..4144e12 100644
--- a/components/payments/content/secure_payment_confirmation_app.h
+++ b/components/payments/content/secure_payment_confirmation_app.h
@@ -29,11 +29,13 @@
 
 class SecurePaymentConfirmationApp : public PaymentApp {
  public:
+  // Please use `std::move()` for the `credential_id` parameter to avoid extra
+  // copies.
   SecurePaymentConfirmationApp(
       const std::string& effective_relying_party_identity,
       std::unique_ptr<SkBitmap> icon,
       const base::string16& label,
-      std::vector<std::unique_ptr<std::vector<uint8_t>>> credential_ids,
+      std::vector<uint8_t> credential_id,
       const url::Origin& merchant_origin,
       const mojom::PaymentCurrencyAmountPtr& total,
       mojom::SecurePaymentConfirmationRequestPtr request,
@@ -82,7 +84,8 @@
   const std::string effective_relying_party_identity_;
   const std::unique_ptr<SkBitmap> icon_;
   const base::string16 label_;
-  const std::vector<std::unique_ptr<std::vector<uint8_t>>> credential_ids_;
+  const std::vector<uint8_t> credential_id_;
+  const std::string encoded_credential_id_;
   const url::Origin merchant_origin_;
   const mojom::PaymentCurrencyAmountPtr total_;
   const mojom::SecurePaymentConfirmationRequestPtr request_;
diff --git a/components/payments/content/secure_payment_confirmation_app_factory.cc b/components/payments/content/secure_payment_confirmation_app_factory.cc
index 4fe6185..bf182e55bc 100644
--- a/components/payments/content/secure_payment_confirmation_app_factory.cc
+++ b/components/payments/content/secure_payment_confirmation_app_factory.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/check.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -19,6 +20,9 @@
 #include "components/payments/content/secure_payment_confirmation_app.h"
 #include "components/payments/core/method_strings.h"
 #include "components/payments/core/native_error_strings.h"
+#include "components/payments/core/secure_payment_confirmation_instrument.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_base.h"
 #include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
 #include "url/origin.h"
 
@@ -31,15 +35,22 @@
 
 bool IsValid(const mojom::SecurePaymentConfirmationRequestPtr& request,
              std::string* error_message) {
-  // |request| can be null when the feature is disabled in Blink.
+  // `request` can be null when the feature is disabled in Blink.
   if (!request)
     return false;
 
-  if (request->instrument_id.empty()) {
-    *error_message = errors::kInstrumentIdRequired;
+  if (request->credential_ids.empty()) {
+    *error_message = errors::kCredentialIdsRequired;
     return false;
   }
 
+  for (const auto& credential_id : request->credential_ids) {
+    if (credential_id.empty()) {
+      *error_message = errors::kCredentialIdsRequired;
+      return false;
+    }
+  }
+
   if (request->timeout.has_value() &&
       request->timeout.value().InMilliseconds() > kMaxTimeoutInMilliseconds) {
     *error_message = errors::kTimeoutTooLong;
@@ -49,11 +60,14 @@
   return true;
 }
 
-void OnIsUserVerifyingPlatformAuthenticatorAvailable(
-    base::WeakPtr<PaymentAppFactory::Delegate> delegate,
-    mojom::SecurePaymentConfirmationRequestPtr request,
-    std::unique_ptr<autofill::InternalAuthenticator> authenticator,
-    bool is_available) {
+}  // namespace
+
+void SecurePaymentConfirmationAppFactory::
+    OnIsUserVerifyingPlatformAuthenticatorAvailable(
+        base::WeakPtr<PaymentAppFactory::Delegate> delegate,
+        mojom::SecurePaymentConfirmationRequestPtr request,
+        std::unique_ptr<autofill::InternalAuthenticator> authenticator,
+        bool is_available) {
   if (!delegate)
     return;
 
@@ -62,6 +76,11 @@
     return;
   }
 
+  // Regardless of whether `web_data_service` has any apps, canMakePayment() and
+  // hasEnrolledInstrument() should return true when a user-verifying platform
+  // authenticator device is available.
+  delegate->SetCanMakePaymentEvenWithoutApps();
+
   scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
       delegate->GetPaymentManifestWebDataService();
   if (!web_data_service) {
@@ -69,28 +88,13 @@
     return;
   }
 
-  // TODO(https://crbug.com/1110324): Check |web_data_service| for whether
-  // |request->instrument_id| has any credentials on this device. If so,
-  // retrieve the instrument information from |web_data_service| and use these
-  // values to create a SecurePaymentConfirmationApp. For now, use stubs.
-  std::string effective_relying_party_identity = "rp.example";
-  std::unique_ptr<SkBitmap> icon;
-  base::string16 label = base::ASCIIToUTF16("Stub label");
-  std::vector<std::unique_ptr<std::vector<uint8_t>>> credential_ids;
-  credential_ids.emplace_back(std::make_unique<std::vector<uint8_t>>());
-  credential_ids.back()->push_back(0);
-
-  delegate->OnPaymentAppCreated(std::make_unique<SecurePaymentConfirmationApp>(
-      effective_relying_party_identity, std::move(icon), label,
-      std::move(credential_ids),
-      /*merchant_origin=*/url::Origin::Create(delegate->GetTopOrigin()),
-      /*total=*/delegate->GetSpec()->details().total->amount,
-      std::move(request), std::move(authenticator)));
-  delegate->OnDoneCreatingPaymentApps();
+  WebDataServiceBase::Handle handle =
+      web_data_service->GetSecurePaymentConfirmationInstruments(
+          std::move(request->credential_ids), this);
+  requests_[handle] = std::make_unique<Request>(delegate, std::move(request),
+                                                std::move(authenticator));
 }
 
-}  // namespace
-
 SecurePaymentConfirmationAppFactory::SecurePaymentConfirmationAppFactory()
     : PaymentAppFactory(PaymentApp::Type::INTERNAL) {}
 
@@ -120,8 +124,9 @@
           delegate->CreateInternalAuthenticator();
 
       authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(
-          base::BindOnce(&OnIsUserVerifyingPlatformAuthenticatorAvailable,
-                         delegate,
+          base::BindOnce(&SecurePaymentConfirmationAppFactory::
+                             OnIsUserVerifyingPlatformAuthenticatorAvailable,
+                         weak_ptr_factory_.GetWeakPtr(), delegate,
                          method_data->secure_payment_confirmation.Clone(),
                          std::move(authenticator)));
       return;
@@ -131,4 +136,71 @@
   delegate->OnDoneCreatingPaymentApps();
 }
 
+struct SecurePaymentConfirmationAppFactory::Request {
+  Request(base::WeakPtr<PaymentAppFactory::Delegate> delegate,
+          mojom::SecurePaymentConfirmationRequestPtr mojo_request,
+          std::unique_ptr<autofill::InternalAuthenticator> authenticator)
+      : delegate(delegate),
+        mojo_request(std::move(mojo_request)),
+        authenticator(std::move(authenticator)) {}
+
+  ~Request() = default;
+
+  Request(const Request& other) = delete;
+  Request& operator=(const Request& other) = delete;
+
+  base::WeakPtr<PaymentAppFactory::Delegate> delegate;
+  mojom::SecurePaymentConfirmationRequestPtr mojo_request;
+  std::unique_ptr<autofill::InternalAuthenticator> authenticator;
+};
+
+void SecurePaymentConfirmationAppFactory::OnWebDataServiceRequestDone(
+    WebDataServiceBase::Handle handle,
+    std::unique_ptr<WDTypedResult> result) {
+  auto iterator = requests_.find(handle);
+  if (iterator == requests_.end())
+    return;
+
+  std::unique_ptr<Request> request = std::move(iterator->second);
+  requests_.erase(iterator);
+  DCHECK(request.get());
+  if (!request->delegate)
+    return;
+
+  if (!result || result->GetType() != SECURE_PAYMENT_CONFIRMATION) {
+    request->delegate->OnDoneCreatingPaymentApps();
+    return;
+  }
+
+  std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>
+      instruments = static_cast<WDResult<
+          std::vector<std::unique_ptr<SecurePaymentConfirmationInstrument>>>*>(
+                        result.get())
+                        ->GetValue();
+  if (instruments.empty()) {
+    request->delegate->OnDoneCreatingPaymentApps();
+    return;
+  }
+
+  // For the pilot phase, arbitrarily use the first matching instrument.
+  // TODO(https://crbug.com/1110320): Handle multiple instruments.
+  std::unique_ptr<SecurePaymentConfirmationInstrument> instrument =
+      std::move(instruments.front());
+
+  // TODO(https://crbug.com/1110324): Decode `instrument->icon` from
+  // std::unique_ptr<std::vector<uint8_t>> into std::unique_ptr<SkBitmap> and
+  // check the icon validity.
+  auto icon = std::make_unique<SkBitmap>();
+
+  request->delegate->OnPaymentAppCreated(
+      std::make_unique<SecurePaymentConfirmationApp>(
+          instrument->relying_party_id, std::move(icon), instrument->label,
+          std::move(instrument->credential_id),
+          url::Origin::Create(request->delegate->GetTopOrigin()),
+          request->delegate->GetSpec()->details().total->amount,
+          std::move(request->mojo_request), std::move(request->authenticator)));
+
+  request->delegate->OnDoneCreatingPaymentApps();
+}
+
 }  // namespace payments
diff --git a/components/payments/content/secure_payment_confirmation_app_factory.h b/components/payments/content/secure_payment_confirmation_app_factory.h
index f957eede..fd058bc 100644
--- a/components/payments/content/secure_payment_confirmation_app_factory.h
+++ b/components/payments/content/secure_payment_confirmation_app_factory.h
@@ -5,12 +5,17 @@
 #ifndef COMPONENTS_PAYMENTS_CONTENT_SECURE_PAYMENT_CONFIRMATION_APP_FACTORY_H_
 #define COMPONENTS_PAYMENTS_CONTENT_SECURE_PAYMENT_CONFIRMATION_APP_FACTORY_H_
 
+#include <map>
+#include <memory>
+
 #include "base/memory/weak_ptr.h"
 #include "components/payments/content/payment_app_factory.h"
+#include "components/webdata/common/web_data_service_consumer.h"
 
 namespace payments {
 
-class SecurePaymentConfirmationAppFactory : public PaymentAppFactory {
+class SecurePaymentConfirmationAppFactory : public PaymentAppFactory,
+                                            public WebDataServiceConsumer {
  public:
   SecurePaymentConfirmationAppFactory();
   ~SecurePaymentConfirmationAppFactory() override;
@@ -22,6 +27,24 @@
 
   // PaymentAppFactory:
   void Create(base::WeakPtr<Delegate> delegate) override;
+
+ private:
+  struct Request;
+
+  // WebDataServiceConsumer:
+  void OnWebDataServiceRequestDone(
+      WebDataServiceBase::Handle handle,
+      std::unique_ptr<WDTypedResult> result) override;
+
+  void OnIsUserVerifyingPlatformAuthenticatorAvailable(
+      base::WeakPtr<PaymentAppFactory::Delegate> delegate,
+      mojom::SecurePaymentConfirmationRequestPtr request,
+      std::unique_ptr<autofill::InternalAuthenticator> authenticator,
+      bool is_available);
+
+  std::map<WebDataServiceBase::Handle, std::unique_ptr<Request>> requests_;
+  base::WeakPtrFactory<SecurePaymentConfirmationAppFactory> weak_ptr_factory_{
+      this};
 };
 
 }  // namespace payments
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index 2dfd44e3..1f6d6e3 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -55,6 +55,8 @@
     "payments_experimental_features.h",
     "payments_validators.cc",
     "payments_validators.h",
+    "secure_payment_confirmation_instrument.cc",
+    "secure_payment_confirmation_instrument.h",
     "url_util.cc",
     "url_util.h",
   ]
diff --git a/components/payments/core/native_error_strings.cc b/components/payments/core/native_error_strings.cc
index 170e358e..477f11da 100644
--- a/components/payments/core/native_error_strings.cc
+++ b/components/payments/core/native_error_strings.cc
@@ -210,9 +210,9 @@
     "Found more than one IS_READY_TO_PAY service, but at most one service is "
     "supported.";
 
-const char kInstrumentIdRequired[] =
+const char kCredentialIdsRequired[] =
     "The \"secure-payment-confirmation\" method requires a non-empty "
-    "\"instrumentId\" field.";
+    "\"credentialIds\" array of non-empty arrays.";
 
 const char kTimeoutTooLong[] =
     "The \"secure-payment-confirmation\" method requires at most 1 hour "
diff --git a/components/payments/core/native_error_strings.h b/components/payments/core/native_error_strings.h
index 394b51f3..e1f6a046 100644
--- a/components/payments/core/native_error_strings.h
+++ b/components/payments/core/native_error_strings.h
@@ -237,9 +237,9 @@
 // Used when an Android app declares more than one IS_READY_TO_PAY service.
 extern const char kMoreThanOneService[];
 
-// Used when an empty instrument ID is specified for the
+// Used when no credential IDs are specified for the
 // "secure-payment-confirmation" method.
-extern const char kInstrumentIdRequired[];
+extern const char kCredentialIdsRequired[];
 
 // Used when the timeout specified for the "secure-payment-confirmation" method
 // is too long.
diff --git a/components/payments/core/secure_payment_confirmation_instrument.cc b/components/payments/core/secure_payment_confirmation_instrument.cc
new file mode 100644
index 0000000..1674561
--- /dev/null
+++ b/components/payments/core/secure_payment_confirmation_instrument.cc
@@ -0,0 +1,32 @@
+// 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/payments/core/secure_payment_confirmation_instrument.h"
+
+#include <utility>
+
+namespace payments {
+
+SecurePaymentConfirmationInstrument::SecurePaymentConfirmationInstrument() =
+    default;
+
+SecurePaymentConfirmationInstrument::SecurePaymentConfirmationInstrument(
+    std::vector<uint8_t> credential_id,
+    const std::string& relying_party_id,
+    const base::string16& label,
+    std::vector<uint8_t> icon)
+    : credential_id(std::move(credential_id)),
+      relying_party_id(relying_party_id),
+      label(label),
+      icon(std::move(icon)) {}
+
+SecurePaymentConfirmationInstrument::~SecurePaymentConfirmationInstrument() =
+    default;
+
+bool SecurePaymentConfirmationInstrument::IsValid() const {
+  return !credential_id.empty() && !relying_party_id.empty() &&
+         !label.empty() && !icon.empty();
+}
+
+}  // namespace payments
\ No newline at end of file
diff --git a/components/payments/core/secure_payment_confirmation_instrument.h b/components/payments/core/secure_payment_confirmation_instrument.h
new file mode 100644
index 0000000..8540b76
--- /dev/null
+++ b/components/payments/core/secure_payment_confirmation_instrument.h
@@ -0,0 +1,51 @@
+// 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_PAYMENTS_CORE_SECURE_PAYMENT_CONFIRMATION_INSTRUMENT_H_
+#define COMPONENTS_PAYMENTS_CORE_SECURE_PAYMENT_CONFIRMATION_INSTRUMENT_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string16.h"
+
+namespace payments {
+
+// Secure payment information instrument information that can be stored in
+// SQLite database.
+struct SecurePaymentConfirmationInstrument {
+  // Constructs an empty instrument. This instrument is not valid until all
+  // fields are populated.
+  SecurePaymentConfirmationInstrument();
+
+  // Constructs an instrument with the given fields. Please use `std::move()`
+  // when passing the `credential_id` and the `icon` byte arrays to avoid
+  // excessive copying.
+  SecurePaymentConfirmationInstrument(std::vector<uint8_t> credential_id,
+                                      const std::string& relying_party_id,
+                                      const base::string16& label,
+                                      std::vector<uint8_t> icon);
+
+  ~SecurePaymentConfirmationInstrument();
+
+  // An instrument should not be copied or assigned.
+  SecurePaymentConfirmationInstrument(
+      const SecurePaymentConfirmationInstrument& other) = delete;
+  SecurePaymentConfirmationInstrument& operator=(
+      const SecurePaymentConfirmationInstrument& other) = delete;
+
+  // Checks instrument validity.
+  bool IsValid() const;
+
+  std::vector<uint8_t> credential_id;
+  std::string relying_party_id;
+  base::string16 label;
+  std::vector<uint8_t> icon;
+};
+
+}  // namespace payments
+
+#endif  // COMPONENTS_PAYMENTS_CORE_SECURE_PAYMENT_CONFIRMATION_INSTRUMENT_H_
\ No newline at end of file
diff --git a/components/safe_browsing/content/password_protection/password_protection_request.cc b/components/safe_browsing/content/password_protection/password_protection_request.cc
index d694817..cb203a15 100644
--- a/components/safe_browsing/content/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/content/password_protection/password_protection_request.cc
@@ -592,11 +592,11 @@
     if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
       LogPasswordOnFocusRequestOutcome(outcome);
     } else {
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
       LogPasswordEntryRequestOutcome(outcome, password_account_type);
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
       if (password_type_ == PasswordType::PRIMARY_ACCOUNT_PASSWORD) {
         password_protection_service_->MaybeLogPasswordReuseLookupEvent(
             web_contents_, outcome, password_type_, response.get());
diff --git a/components/safe_browsing/content/password_protection/password_protection_service.cc b/components/safe_browsing/content/password_protection/password_protection_service.cc
index 7d991ca..60c866b 100644
--- a/components/safe_browsing/content/password_protection/password_protection_service.cc
+++ b/components/safe_browsing/content/password_protection/password_protection_service.cc
@@ -113,7 +113,7 @@
 }
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
 void PasswordProtectionService::MaybeStartProtectedPasswordEntryRequest(
     WebContents* web_contents,
     const GURL& main_frame_url,
@@ -149,15 +149,15 @@
       RequestOutcome reason = GetPingNotSentReason(
           trigger_type, main_frame_url, reused_password_account_type);
       LogNoPingingReason(trigger_type, reason, reused_password_account_type);
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
       if (reused_password_account_type.is_account_syncing())
         MaybeLogPasswordReuseLookupEvent(web_contents, reason, password_type,
                                          nullptr);
-#endif  // defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#endif  // defined(PASSWORD_REUSE_WARNING_ENABLED)
     }
   }
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   if (CanShowInterstitial(reused_password_account_type, main_frame_url)) {
     LogPasswordAlertModeOutcome(RequestOutcome::SUCCEEDED,
                                 reused_password_account_type);
@@ -166,11 +166,11 @@
         reused_password_account_type;
     ShowInterstitial(web_contents, reused_password_account_type);
   }
-#endif  // defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#endif  // defined(PASSWORD_REUSE_WARNING_ENABLED)
 }
-#endif  // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
 bool PasswordProtectionService::ShouldShowModalWarning(
     LoginReputationClientRequest::TriggerType trigger_type,
     ReusedPasswordAccountType password_type,
@@ -283,7 +283,7 @@
       return;
     }
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
     if (ShouldShowModalWarning(request->trigger_type(), password_type,
                                response->verdict_type())) {
       username_for_last_shown_warning_ = request->username();
diff --git a/components/safe_browsing/content/password_protection/password_protection_service.h b/components/safe_browsing/content/password_protection/password_protection_service.h
index e17e176d..75f3cd2 100644
--- a/components/safe_browsing/content/password_protection/password_protection_service.h
+++ b/components/safe_browsing/content/password_protection/password_protection_service.h
@@ -119,7 +119,7 @@
       const std::string& hosted_domain);
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+#if defined(PASSWORD_REUSE_DETECTION_ENABLED)
   virtual void MaybeStartProtectedPasswordEntryRequest(
       content::WebContents* web_contents,
       const GURL& main_frame_url,
@@ -130,7 +130,7 @@
       bool password_field_exists);
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   // Records a Chrome Sync event that sync password reuse was detected.
   virtual void MaybeLogPasswordReuseDetectedEvent(
       content::WebContents* web_contents) = 0;
@@ -170,7 +170,7 @@
   virtual void ReportPasswordChanged() = 0;
 #endif
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   virtual void UpdateSecurityState(safe_browsing::SBThreatType threat_type,
                                    ReusedPasswordAccountType password_type,
                                    content::WebContents* web_contents) = 0;
@@ -397,7 +397,7 @@
   // If Safe browsing endpoint is not enabled in the country.
   virtual bool IsInExcludedCountry() = 0;
 
-#if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
+#if defined(PASSWORD_REUSE_WARNING_ENABLED)
   // Records a Chrome Sync event for the result of the URL reputation lookup
   // if the user enters their sync password on a website.
   virtual void MaybeLogPasswordReuseLookupEvent(
diff --git a/components/signin/core/browser/account_investigator.cc b/components/signin/core/browser/account_investigator.cc
index 3ba4a1e..2915755 100644
--- a/components/signin/core/browser/account_investigator.cc
+++ b/components/signin/core/browser/account_investigator.cc
@@ -35,6 +35,35 @@
   return info.account_id == account.id;
 }
 
+// Returns the extended info for the primary account (no consent required) if
+// available.
+base::Optional<AccountInfo> GetExtendedAccountInfo(
+    signin::IdentityManager* identity_manager) {
+  CoreAccountId account_id =
+      identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kNotRequired);
+  if (account_id.empty())
+    return base::nullopt;
+  return identity_manager
+      ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+          account_id);
+}
+
+// Returns true if there is primary account (no consent required) but no
+// extended info, yet.
+bool WaitingForExtendedInfo(signin::IdentityManager* identity_manager) {
+  if (!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired))
+    return false;
+  return !GetExtendedAccountInfo(identity_manager).has_value();
+}
+
+// Returns true if the account is managed.
+// TODO(crbug.com/1122496): Move this helper into AccountInfo to reduce code
+// duplication (replaces other instances of such a helper function as well).
+bool IsManaged(const AccountInfo& account_info) {
+  return !account_info.hosted_domain.empty() &&
+         account_info.hosted_domain != kNoHostedDomainFound;
+}
+
 }  // namespace
 
 const TimeDelta AccountInvestigator::kPeriodicReportingInterval =
@@ -58,6 +87,8 @@
   identity_manager_->AddObserver(this);
   previously_authenticated_ = identity_manager_->HasPrimaryAccount();
 
+  // TODO(crbug.com/1121923): Refactor to use signin::PersistentRepeatingTimer
+  // instead.
   Time previous = Time::FromDoubleT(
       pref_service_->GetDouble(prefs::kGaiaCookiePeriodicReportTime));
   if (previous.is_null())
@@ -110,12 +141,18 @@
   // be a change, which means we will report a stable age of 0. This also
   // guarantees that on a fresh install we always have a cookie changed pref.
   if (periodic_pending_) {
-    DoPeriodicReport(signed_in_accounts, signed_out_accounts);
+    TryPeriodicReport();
   }
 
   previously_authenticated_ = currently_authenticated;
 }
 
+void AccountInvestigator::OnExtendedAccountInfoUpdated(
+    const AccountInfo& info) {
+  if (periodic_pending_)
+    TryPeriodicReport();
+}
+
 // static
 TimeDelta AccountInvestigator::CalculatePeriodicDelay(Time previous,
                                                       Time now,
@@ -193,7 +230,8 @@
 void AccountInvestigator::TryPeriodicReport() {
   auto accounts_in_cookie_jar_info =
       identity_manager_->GetAccountsInCookieJar();
-  if (accounts_in_cookie_jar_info.accounts_are_fresh) {
+  if (accounts_in_cookie_jar_info.accounts_are_fresh &&
+      !WaitingForExtendedInfo(identity_manager_)) {
     DoPeriodicReport(accounts_in_cookie_jar_info.signed_in_accounts,
                      accounts_in_cookie_jar_info.signed_out_accounts);
   } else {
@@ -207,6 +245,18 @@
   SharedCookieJarReport(signed_in_accounts, signed_out_accounts, Time::Now(),
                         ReportingType::PERIODIC);
 
+  // Report extra metrics only for signed-in accounts that are split by the
+  // primary account type.
+  if (identity_manager_->HasPrimaryAccount(
+          signin::ConsentLevel::kNotRequired)) {
+    const bool is_syncing =
+        identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
+    base::Optional<AccountInfo> info =
+        GetExtendedAccountInfo(identity_manager_);
+    signin_metrics::LogSignedInCookiesCountsPerPrimaryAccountType(
+        signed_in_accounts.size(), is_syncing, IsManaged(*info));
+  }
+
   periodic_pending_ = false;
   pref_service_->SetDouble(prefs::kGaiaCookiePeriodicReportTime,
                            Time::Now().ToDoubleT());
diff --git a/components/signin/core/browser/account_investigator.h b/components/signin/core/browser/account_investigator.h
index 0a7b9538..f737dde 100644
--- a/components/signin/core/browser/account_investigator.h
+++ b/components/signin/core/browser/account_investigator.h
@@ -58,6 +58,7 @@
   void OnAccountsInCookieUpdated(
       const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
       const GoogleServiceAuthError& error) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
  private:
   friend class AccountInvestigatorTest;
diff --git a/components/signin/core/browser/account_investigator_unittest.cc b/components/signin/core/browser/account_investigator_unittest.cc
index 89ed251e..07a9d497 100644
--- a/components/signin/core/browser/account_investigator_unittest.cc
+++ b/components/signin/core/browser/account_investigator_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "build/build_config.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "components/signin/public/base/signin_pref_names.h"
@@ -358,6 +359,76 @@
   EXPECT_FALSE(*periodic_pending());
   ExpectSharedReportHistograms(ReportingType::PERIODIC, histogram_tester,
                                nullptr, 1, 0, 1, nullptr, false);
+
+  // There's no primary account and thus no break-down into types of primary
+  // accounts.
+  EXPECT_EQ(0u, histogram_tester
+                    .GetTotalCountsForPrefix(
+                        "Signin.CookieJar.SignedInCountWithPrimary.")
+                    .size());
+}
+
+TEST_F(AccountInvestigatorTest, TryPeriodicReportWithPrimary) {
+  investigator()->Initialize();
+
+  std::string email("f@bar.com");
+  identity_test_env()->SetCookieAccounts(
+      {{email, signin::GetTestGaiaIdForEmail(email)}});
+  identity_test_env()->MakePrimaryAccountAvailable(email);
+
+  const HistogramTester histogram_tester;
+  TryPeriodicReport();
+  EXPECT_FALSE(*periodic_pending());
+  histogram_tester.ExpectUniqueSample(
+      "Signin.CookieJar.SignedInCountWithPrimary.SyncConsumer",
+      /*bucket=*/1, /*count=*/1);
+  histogram_tester.ExpectTotalCount(
+      "Signin.CookieJar.SignedInCountWithPrimary.NoSyncConsumer",
+      /*count=*/0);
+}
+
+// Neither iOS nor Android support unconsented primary accounts.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+TEST_F(AccountInvestigatorTest, TryPeriodicReportWithUnconsentedPrimary) {
+  investigator()->Initialize();
+
+  std::string email("f@bar.com");
+  identity_test_env()->SetCookieAccounts(
+      {{email, signin::GetTestGaiaIdForEmail(email)}});
+  identity_test_env()->MakeUnconsentedPrimaryAccountAvailable(email);
+
+  const HistogramTester histogram_tester;
+  TryPeriodicReport();
+  EXPECT_FALSE(*periodic_pending());
+  histogram_tester.ExpectUniqueSample(
+      "Signin.CookieJar.SignedInCountWithPrimary.NoSyncConsumer",
+      /*bucket=*/1, /*count=*/1);
+  histogram_tester.ExpectTotalCount(
+      "Signin.CookieJar.SignedInCountWithPrimary.SyncConsumer",
+      /*count=*/0);
+}
+#endif  // !defined(OS_IOS) && !defined(OS_ANDROID)
+
+TEST_F(AccountInvestigatorTest, TryPeriodicReportWithEnterprisePrimary) {
+  investigator()->Initialize();
+
+  std::string email("f@bar.com");
+  identity_test_env()->SetCookieAccounts(
+      {{email, signin::GetTestGaiaIdForEmail(email)}});
+  AccountInfo account_info =
+      identity_test_env()->MakePrimaryAccountAvailable(email);
+  account_info.hosted_domain = "bar.com";
+  identity_test_env()->UpdateAccountInfoForAccount(account_info);
+
+  const HistogramTester histogram_tester;
+  TryPeriodicReport();
+  EXPECT_FALSE(*periodic_pending());
+  histogram_tester.ExpectUniqueSample(
+      "Signin.CookieJar.SignedInCountWithPrimary.SyncEnterprise",
+      /*bucket=*/1, /*count=*/1);
+  histogram_tester.ExpectTotalCount(
+      "Signin.CookieJar.SignedInCountWithPrimary.NoSyncEnterprise",
+      /*count=*/0);
 }
 
 TEST_F(AccountInvestigatorTest, TryPeriodicReportEmpty) {
diff --git a/components/signin/public/base/signin_metrics.cc b/components/signin/public/base/signin_metrics.cc
index 2310caa..493cc443 100644
--- a/components/signin/public/base/signin_metrics.cc
+++ b/components/signin/public/base/signin_metrics.cc
@@ -7,6 +7,7 @@
 #include <limits.h>
 
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/numerics/safe_conversions.h"
@@ -723,6 +724,33 @@
   INVESTIGATOR_HISTOGRAM_BOOLEAN("Signin.IsShared", type, is_shared);
 }
 
+void LogSignedInCookiesCountsPerPrimaryAccountType(int signed_in_accounts_count,
+                                                   bool primary_syncing,
+                                                   bool primary_managed) {
+  constexpr int kMaxBucket = 10;
+  if (primary_syncing) {
+    if (primary_managed) {
+      base::UmaHistogramExactLinear(
+          "Signin.CookieJar.SignedInCountWithPrimary.SyncEnterprise",
+          signed_in_accounts_count, kMaxBucket);
+    } else {
+      base::UmaHistogramExactLinear(
+          "Signin.CookieJar.SignedInCountWithPrimary.SyncConsumer",
+          signed_in_accounts_count, kMaxBucket);
+    }
+  } else {
+    if (primary_managed) {
+      base::UmaHistogramExactLinear(
+          "Signin.CookieJar.SignedInCountWithPrimary.NoSyncEnterprise",
+          signed_in_accounts_count, kMaxBucket);
+    } else {
+      base::UmaHistogramExactLinear(
+          "Signin.CookieJar.SignedInCountWithPrimary.NoSyncConsumer",
+          signed_in_accounts_count, kMaxBucket);
+    }
+  }
+}
+
 void RecordRefreshTokenUpdatedFromSource(
     bool refresh_token_is_valid,
     SourceForRefreshTokenOperation source) {
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index d3f3cff..4028bd3 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -413,7 +413,7 @@
 void LogCookieJarStableAge(const base::TimeDelta stable_age,
                            const ReportingType type);
 
-// Records three counts for the number of accounts in the cookei jar.
+// Records three counts for the number of accounts in the cookie jar.
 void LogCookieJarCounts(const int signed_in,
                         const int signed_out,
                         const int total,
@@ -428,6 +428,14 @@
 // between multiple users.
 void LogIsShared(const bool is_shared, const ReportingType type);
 
+// Records the number of signed-in accounts in the cookie jar for the given
+// (potentially unconsented) primary account type, characterized by sync being
+// enabled (`primary_syncing`) and the account being managed (i.e. enterprise,
+// `primary_managed`).
+void LogSignedInCookiesCountsPerPrimaryAccountType(int signed_in_accounts_count,
+                                                   bool primary_syncing,
+                                                   bool primary_managed);
+
 // Records the source that updated a refresh token.
 void RecordRefreshTokenUpdatedFromSource(bool refresh_token_is_valid,
                                          SourceForRefreshTokenOperation source);
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index abbe13b..dc15707 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -494,6 +494,7 @@
     "engine_impl/syncer_proto_util_unittest.cc",
     "engine_impl/syncer_unittest.cc",
     "invalidations/fcm_handler_unittest.cc",
+    "invalidations/subscribed_data_types_manager_unittest.cc",
     "js/js_event_details_unittest.cc",
     "js/sync_js_controller_unittest.cc",
     "model/entity_data_unittest.cc",
diff --git a/components/sync/invalidations/BUILD.gn b/components/sync/invalidations/BUILD.gn
index 1e18435..7a636d8d 100644
--- a/components/sync/invalidations/BUILD.gn
+++ b/components/sync/invalidations/BUILD.gn
@@ -10,6 +10,9 @@
     "fcm_handler.h",
     "fcm_registration_token_observer.h",
     "invalidations_listener.h",
+    "subscribed_data_types_manager.cc",
+    "subscribed_data_types_manager.h",
+    "subscribed_data_types_observer.h",
     "switches.cc",
     "switches.h",
     "sync_invalidations_service.h",
@@ -21,6 +24,7 @@
     "//base",
     "//components/gcm_driver",
     "//components/keyed_service/core",
+    "//components/sync/base",
   ]
 }
 
diff --git a/components/sync/invalidations/DEPS b/components/sync/invalidations/DEPS
index 700faa79..87531c28 100644
--- a/components/sync/invalidations/DEPS
+++ b/components/sync/invalidations/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+components/gcm_driver",
   "+components/keyed_service",
+  "+components/sync/base",
 ]
diff --git a/components/sync/invalidations/mock_sync_invalidations_service.h b/components/sync/invalidations/mock_sync_invalidations_service.h
index fa22a915a..40e1ae4 100644
--- a/components/sync/invalidations/mock_sync_invalidations_service.h
+++ b/components/sync/invalidations/mock_sync_invalidations_service.h
@@ -26,6 +26,14 @@
               RemoveTokenObserver,
               (FCMRegistrationTokenObserver * observer));
   MOCK_METHOD(const std::string&, GetFCMRegistrationToken, (), (const));
+  MOCK_METHOD(void,
+              AddSubscribedDataTypesObserver,
+              (SubscribedDataTypesObserver * observer));
+  MOCK_METHOD(void,
+              RemoveSubscribedDataTypesObserver,
+              (SubscribedDataTypesObserver * observer));
+  MOCK_METHOD(const ModelTypeSet&, GetSubscribedDataTypes, (), (const));
+  MOCK_METHOD(void, SetSubscribedDataTypes, (const ModelTypeSet& data_types));
 };
 
 }  // namespace syncer
diff --git a/components/sync/invalidations/subscribed_data_types_manager.cc b/components/sync/invalidations/subscribed_data_types_manager.cc
new file mode 100644
index 0000000..1e8a6a9
--- /dev/null
+++ b/components/sync/invalidations/subscribed_data_types_manager.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 "components/sync/invalidations/subscribed_data_types_manager.h"
+
+#include "components/sync/invalidations/subscribed_data_types_observer.h"
+
+namespace syncer {
+
+SubscribedDataTypesManager::SubscribedDataTypesManager() = default;
+
+SubscribedDataTypesManager::~SubscribedDataTypesManager() = default;
+
+void SubscribedDataTypesManager::AddSubscribedDataTypesObserver(
+    SubscribedDataTypesObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void SubscribedDataTypesManager::RemoveSubscribedDataTypesObserver(
+    SubscribedDataTypesObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+const ModelTypeSet& SubscribedDataTypesManager::GetSubscribedDataTypes() const {
+  return data_types_;
+}
+
+void SubscribedDataTypesManager::SetSubscribedDataTypes(
+    const ModelTypeSet& data_types) {
+  data_types_ = data_types;
+  for (SubscribedDataTypesObserver& observer : observers_) {
+    observer.OnSubscribedDataTypesChanged();
+  }
+}
+
+}  // namespace syncer
diff --git a/components/sync/invalidations/subscribed_data_types_manager.h b/components/sync/invalidations/subscribed_data_types_manager.h
new file mode 100644
index 0000000..018e67b7
--- /dev/null
+++ b/components/sync/invalidations/subscribed_data_types_manager.h
@@ -0,0 +1,43 @@
+// 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_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_MANAGER_H_
+#define COMPONENTS_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_MANAGER_H_
+
+#include "base/observer_list.h"
+#include "components/sync/base/model_type.h"
+
+namespace syncer {
+class SubscribedDataTypesObserver;
+
+// Manages for which data types are invalidations sent to this device.
+class SubscribedDataTypesManager {
+ public:
+  SubscribedDataTypesManager();
+  ~SubscribedDataTypesManager();
+  SubscribedDataTypesManager(const SubscribedDataTypesManager&) = delete;
+  SubscribedDataTypesManager& operator=(const SubscribedDataTypesManager&) =
+      delete;
+
+  // Add or remove a subscribed data types change observer. |observer| must not
+  // be nullptr.
+  void AddSubscribedDataTypesObserver(SubscribedDataTypesObserver* observer);
+  void RemoveSubscribedDataTypesObserver(SubscribedDataTypesObserver* observer);
+
+  // Get or set the subscribed data types.
+  const ModelTypeSet& GetSubscribedDataTypes() const;
+  void SetSubscribedDataTypes(const ModelTypeSet& data_types);
+
+ private:
+  base::ObserverList<SubscribedDataTypesObserver,
+                     /*check_empty=*/true,
+                     /*allow_reentrancy=*/false>
+      observers_;
+
+  ModelTypeSet data_types_;
+};
+
+}  // namespace syncer
+
+#endif  // COMPONENTS_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_MANAGER_H_
diff --git a/components/sync/invalidations/subscribed_data_types_manager_unittest.cc b/components/sync/invalidations/subscribed_data_types_manager_unittest.cc
new file mode 100644
index 0000000..e37f06c
--- /dev/null
+++ b/components/sync/invalidations/subscribed_data_types_manager_unittest.cc
@@ -0,0 +1,42 @@
+// 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/sync/invalidations/subscribed_data_types_manager.h"
+
+#include "components/sync/invalidations/subscribed_data_types_observer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+namespace {
+
+class MockDataTypesObserver : public SubscribedDataTypesObserver {
+ public:
+  MOCK_METHOD0(OnSubscribedDataTypesChanged, void());
+};
+
+class SubscribedDataTypesManagerTest : public testing::Test {
+ protected:
+  SubscribedDataTypesManager manager_;
+};
+
+TEST_F(SubscribedDataTypesManagerTest, ShouldReturnGivenDataTypes) {
+  manager_.SetSubscribedDataTypes(ModelTypeSet(BOOKMARKS, PREFERENCES));
+  EXPECT_EQ(ModelTypeSet(BOOKMARKS, PREFERENCES),
+            manager_.GetSubscribedDataTypes());
+  manager_.SetSubscribedDataTypes(ModelTypeSet(PREFERENCES, PASSWORDS));
+  EXPECT_EQ(ModelTypeSet(PREFERENCES, PASSWORDS),
+            manager_.GetSubscribedDataTypes());
+}
+
+TEST_F(SubscribedDataTypesManagerTest, ShouldNotifyOnChange) {
+  testing::NiceMock<MockDataTypesObserver> observer;
+  manager_.AddSubscribedDataTypesObserver(&observer);
+  EXPECT_CALL(observer, OnSubscribedDataTypesChanged());
+  manager_.SetSubscribedDataTypes(ModelTypeSet(PASSWORDS, AUTOFILL));
+  manager_.RemoveSubscribedDataTypesObserver(&observer);
+}
+
+}  // namespace
+}  // namespace syncer
diff --git a/components/sync/invalidations/subscribed_data_types_observer.h b/components/sync/invalidations/subscribed_data_types_observer.h
new file mode 100644
index 0000000..9a7f62d
--- /dev/null
+++ b/components/sync/invalidations/subscribed_data_types_observer.h
@@ -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.
+
+#ifndef COMPONENTS_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_OBSERVER_H_
+#define COMPONENTS_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_OBSERVER_H_
+
+#include "base/observer_list.h"
+
+namespace syncer {
+
+// An interface to observe changes on data types for which the device wants to
+// receive invalidations.
+class SubscribedDataTypesObserver : public base::CheckedObserver {
+ public:
+  // Called on each change of subscribed data types.
+  virtual void OnSubscribedDataTypesChanged() = 0;
+};
+
+}  // namespace syncer
+
+#endif  // COMPONENTS_SYNC_INVALIDATIONS_SUBSCRIBED_DATA_TYPES_OBSERVER_H_
diff --git a/components/sync/invalidations/sync_invalidations_service.h b/components/sync/invalidations/sync_invalidations_service.h
index faa3c28..328272b6 100644
--- a/components/sync/invalidations/sync_invalidations_service.h
+++ b/components/sync/invalidations/sync_invalidations_service.h
@@ -8,10 +8,12 @@
 #include <string>
 
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/sync/base/model_type.h"
 
 namespace syncer {
 class FCMRegistrationTokenObserver;
 class InvalidationsListener;
+class SubscribedDataTypesObserver;
 
 // Service which is used to register with FCM. It is used to obtain an FCM token
 // which is used to send invalidations from the server. The service also
@@ -33,6 +35,17 @@
   // Used to get an obtained FCM token. Returns empty string if it hasn't been
   // received yet.
   virtual const std::string& GetFCMRegistrationToken() const = 0;
+
+  // Add or remove a subscribed data types change observer. |observer| must not
+  // be nullptr.
+  virtual void AddSubscribedDataTypesObserver(
+      SubscribedDataTypesObserver* observer) = 0;
+  virtual void RemoveSubscribedDataTypesObserver(
+      SubscribedDataTypesObserver* observer) = 0;
+
+  // Get or set for which data types should the device receive invalidations.
+  virtual const ModelTypeSet& GetSubscribedDataTypes() const = 0;
+  virtual void SetSubscribedDataTypes(const ModelTypeSet& data_types) = 0;
 };
 
 }  // namespace syncer
diff --git a/components/sync/invalidations/sync_invalidations_service_impl.cc b/components/sync/invalidations/sync_invalidations_service_impl.cc
index 52650155..159093f 100644
--- a/components/sync/invalidations/sync_invalidations_service_impl.cc
+++ b/components/sync/invalidations/sync_invalidations_service_impl.cc
@@ -45,6 +45,26 @@
   return fcm_handler_->GetFCMRegistrationToken();
 }
 
+void SyncInvalidationsServiceImpl::AddSubscribedDataTypesObserver(
+    SubscribedDataTypesObserver* observer) {
+  data_types_manager_.AddSubscribedDataTypesObserver(observer);
+}
+
+void SyncInvalidationsServiceImpl::RemoveSubscribedDataTypesObserver(
+    SubscribedDataTypesObserver* observer) {
+  data_types_manager_.RemoveSubscribedDataTypesObserver(observer);
+}
+
+const ModelTypeSet& SyncInvalidationsServiceImpl::GetSubscribedDataTypes()
+    const {
+  return data_types_manager_.GetSubscribedDataTypes();
+}
+
+void SyncInvalidationsServiceImpl::SetSubscribedDataTypes(
+    const ModelTypeSet& data_types) {
+  data_types_manager_.SetSubscribedDataTypes(data_types);
+}
+
 void SyncInvalidationsServiceImpl::Shutdown() {
   fcm_handler_.reset();
 }
diff --git a/components/sync/invalidations/sync_invalidations_service_impl.h b/components/sync/invalidations/sync_invalidations_service_impl.h
index e2d1a59..72120e1 100644
--- a/components/sync/invalidations/sync_invalidations_service_impl.h
+++ b/components/sync/invalidations/sync_invalidations_service_impl.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "components/sync/invalidations/subscribed_data_types_manager.h"
 #include "components/sync/invalidations/sync_invalidations_service.h"
 
 namespace gcm {
@@ -38,12 +39,19 @@
   void AddTokenObserver(FCMRegistrationTokenObserver* observer) override;
   void RemoveTokenObserver(FCMRegistrationTokenObserver* observer) override;
   const std::string& GetFCMRegistrationToken() const override;
+  void AddSubscribedDataTypesObserver(
+      SubscribedDataTypesObserver* observer) override;
+  void RemoveSubscribedDataTypesObserver(
+      SubscribedDataTypesObserver* observer) override;
+  const ModelTypeSet& GetSubscribedDataTypes() const override;
+  void SetSubscribedDataTypes(const ModelTypeSet& data_types) override;
 
   // KeyedService overrides.
   void Shutdown() override;
 
  private:
   std::unique_ptr<FCMHandler> fcm_handler_;
+  SubscribedDataTypesManager data_types_manager_;
 };
 
 }  // namespace syncer
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc
index 256dda6..31b0f05 100644
--- a/components/sync/protocol/proto_enum_conversions.cc
+++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -512,9 +512,10 @@
 
 const char* ProtoEnumToString(
     sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode) {
-  ASSERT_ENUM_BOUNDS(sync_pb::WebAppSpecifics, UserDisplayMode, BROWSER,
+  ASSERT_ENUM_BOUNDS(sync_pb::WebAppSpecifics, UserDisplayMode, UNSPECIFIED,
                      STANDALONE);
   switch (user_display_mode) {
+    ENUM_CASE(sync_pb::WebAppSpecifics, UNSPECIFIED);
     ENUM_CASE(sync_pb::WebAppSpecifics, BROWSER);
     ENUM_CASE(sync_pb::WebAppSpecifics, STANDALONE);
   }
diff --git a/components/sync/protocol/web_app_specifics.proto b/components/sync/protocol/web_app_specifics.proto
index ae60605..de39a29 100644
--- a/components/sync/protocol/web_app_specifics.proto
+++ b/components/sync/protocol/web_app_specifics.proto
@@ -37,7 +37,7 @@
   // chrome/browser/web_applications/proto/web_app.proto and
   // third_party/blink/public/mojom/manifest/display_mode.mojom
   enum UserDisplayMode {
-    // UNDEFINED is never serialized.
+    UNSPECIFIED = 0;
     BROWSER = 1;
     // MINIMAL_UI is never serialized.
     STANDALONE = 3;
diff --git a/components/webdata/common/web_data_results.h b/components/webdata/common/web_data_results.h
index b69c697..db1e907 100644
--- a/components/webdata/common/web_data_results.h
+++ b/components/webdata/common/web_data_results.h
@@ -45,6 +45,8 @@
   PAYMENT_WEB_APP_MANIFEST,      // WDResult<std::vector<
                                  //     mojom::WebAppManifestSectionPtr>>
   PAYMENT_METHOD_MANIFEST,       // WDResult<std::vector<std::string>>
+  SECURE_PAYMENT_CONFIRMATION,   // WDResult<std::vector<std::unique_ptr<
+                                 //     SecurePaymentConfirmationInstrument>>>
 #endif
 } WDResultType;
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ca566c1b..434c77a 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -838,6 +838,8 @@
     "devtools/shared_worker_devtools_manager.h",
     "devtools/worker_devtools_agent_host.cc",
     "devtools/worker_devtools_agent_host.h",
+    "direct_sockets/direct_sockets_service_impl.cc",
+    "direct_sockets/direct_sockets_service_impl.h",
     "display_cutout/display_cutout_constants.h",
     "display_cutout/display_cutout_host_impl.cc",
     "display_cutout/display_cutout_host_impl.h",
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 4959a8d..3f2a75b 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -121,6 +121,7 @@
 #include "third_party/blink/public/public_buildflags.h"
 
 #if !defined(OS_ANDROID)
+#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
 #include "content/browser/installedapp/installed_app_provider_impl.h"
 #include "content/public/common/content_switches.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
@@ -739,6 +740,10 @@
   map->Add<blink::mojom::CredentialManager>(base::BindRepeating(
       &EmptyBinderForFrame<blink::mojom::CredentialManager>));
 #if !defined(OS_ANDROID)
+  if (base::FeatureList::IsEnabled(features::kDirectSockets)) {
+    map->Add<blink::mojom::DirectSocketsService>(
+        base::BindRepeating(&DirectSocketsServiceImpl::CreateForFrame));
+  }
   map->Add<media::mojom::SpeechRecognitionContext>(base::BindRepeating(
       &EmptyBinderForFrame<media::mojom::SpeechRecognitionContext>));
 #endif
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index bdfeda65..1635479f 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -643,6 +643,12 @@
 
 #if defined(OS_FUCHSIA)
   InitDefaultJob();
+
+  // Have child processes & jobs terminate automatically if the browser process
+  // exits, by marking the browser process as "critical" to its job.
+  zx_status_t result =
+      zx::job::default_job()->set_critical(0, *zx::process::self());
+  ZX_CHECK(ZX_OK == result, result) << "zx_job_set_critical";
 #endif
 
 #if defined(OS_WIN)
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index ae141c4..70e229e 100644
--- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -145,8 +145,8 @@
   return CrossOriginResourcePolicy::IsBlockedByHeaderValue(
              response->url_list.back(), response->url_list.front(),
              document_origin, corp_header_value, RequestMode::kNoCors,
-             document_origin, document_coep,
-             coep_reporter ? coep_reporter.get() : nullptr)
+             document_origin, network::mojom::RequestDestination::kEmpty,
+             document_coep, coep_reporter ? coep_reporter.get() : nullptr)
       .has_value();
 }
 
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc
index 320cb9c..1807940 100644
--- a/content/browser/cross_origin_opener_policy_browsertest.cc
+++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -2370,6 +2370,11 @@
   void SetUpCommandLine(base::CommandLine* command_line) final {
     ContentBrowserTest::SetUpCommandLine(command_line);
     command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+
+    // TODO(https://crbug.com/1119555): Remove this once fixed.
+    // This test relies on the origin-trial's public key to keep its default
+    // value. Overriding it would break the test.
+    CHECK(!command_line->HasSwitch("origin-trial-public-key"));
   }
 
  private:
diff --git a/content/browser/direct_sockets/OWNERS b/content/browser/direct_sockets/OWNERS
new file mode 100644
index 0000000..3b6e1ba
--- /dev/null
+++ b/content/browser/direct_sockets/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/modules/direct_sockets/OWNERS
diff --git a/content/browser/direct_sockets/README.md b/content/browser/direct_sockets/README.md
new file mode 100644
index 0000000..19c2737
--- /dev/null
+++ b/content/browser/direct_sockets/README.md
@@ -0,0 +1,13 @@
+This directory implements permission and user consent checks for the
+browser side of socket opening for the [Direct Sockets API](
+https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md).
+
+Examples of the checks include
+- user dialog, allowing user to enter destination address
+- permissions policy
+- rate limiting
+- checking hostnames resolve to public addresses
+- content security policy
+
+When requests to establish TCP or UDP communication have passed the
+various checks, they are forwarded to the network service.
diff --git a/content/browser/direct_sockets/direct_sockets_browsertest.cc b/content/browser/direct_sockets/direct_sockets_browsertest.cc
new file mode 100644
index 0000000..ee0da5d
--- /dev/null
+++ b/content/browser/direct_sockets/direct_sockets_browsertest.cc
@@ -0,0 +1,94 @@
+// 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 "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "net/base/net_errors.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class DirectSocketsBrowserTest : public ContentBrowserTest {
+ public:
+  DirectSocketsBrowserTest() {
+    feature_list_.InitAndEnableFeature(features::kDirectSockets);
+  }
+  ~DirectSocketsBrowserTest() override = default;
+
+  GURL GetTestPageURL() {
+    return embedded_test_server()->GetURL("/direct_sockets/index.html");
+  }
+
+ protected:
+  void SetUp() override {
+    embedded_test_server()->AddDefaultHandlers(GetTestDataFilePath());
+    ASSERT_TRUE(embedded_test_server()->Start());
+
+    ContentBrowserTest::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenTcp_Success) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+
+  DirectSocketsServiceImpl::SetPermissionCallbackForTesting(
+      base::BindLambdaForTesting(
+          [&](const blink::mojom::DirectSocketOptions&) { return net::OK; }));
+
+  // TODO(crbug.com/905818): Use port from a listening net::TCPServerSocket.
+  const std::string script = base::StringPrintf(
+      "openTcp({remoteAddress: '127.0.0.1', remotePort: %d})", 0);
+
+  EXPECT_EQ("openTcp succeeded", EvalJs(shell(), script));
+}
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenTcp_NotAllowedError) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+
+  // TODO(crbug.com/905818): Use port from a listening net::TCPServerSocket.
+  const std::string script = base::StringPrintf(
+      "openTcp({remoteAddress: '127.0.0.1', remotePort: %d})", 0);
+
+  EXPECT_EQ("openTcp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+}
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenUdp_Success) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+
+  DirectSocketsServiceImpl::SetPermissionCallbackForTesting(
+      base::BindLambdaForTesting(
+          [&](const blink::mojom::DirectSocketOptions&) { return net::OK; }));
+
+  // TODO(crbug.com/1119620): Use port from a listening net::UDPServerSocket.
+  const std::string script = base::StringPrintf(
+      "openUdp({remoteAddress: '127.0.0.1', remotePort: %d})", 0);
+
+  EXPECT_EQ("openUdp succeeded", EvalJs(shell(), script));
+}
+
+IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenUdp_NotAllowedError) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL()));
+
+  // TODO(crbug.com/1119620): Use port from a listening net::UDPServerSocket.
+  const std::string script = base::StringPrintf(
+      "openUdp({remoteAddress: '127.0.0.1', remotePort: %d})", 0);
+
+  EXPECT_EQ("openUdp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+}
+
+}  // namespace content
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc
new file mode 100644
index 0000000..89b27a4
--- /dev/null
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -0,0 +1,117 @@
+// 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 "content/browser/direct_sockets/direct_sockets_service_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/optional.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+namespace content {
+
+namespace {
+
+DirectSocketsServiceImpl::PermissionCallback&
+GetPermissionCallbackForTesting() {
+  static base::NoDestructor<DirectSocketsServiceImpl::PermissionCallback>
+      callback;
+  return *callback;
+}
+
+}  // namespace
+
+DirectSocketsServiceImpl::DirectSocketsServiceImpl(RenderFrameHost& frame_host)
+    : frame_host_(&frame_host) {}
+
+// static
+void DirectSocketsServiceImpl::CreateForFrame(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::DirectSocketsService> receiver) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<DirectSocketsServiceImpl>(*render_frame_host),
+      std::move(receiver));
+}
+
+void DirectSocketsServiceImpl::OpenTcpSocket(
+    blink::mojom::DirectSocketOptionsPtr options,
+    OpenTcpSocketCallback callback) {
+  if (!options) {
+    mojo::ReportBadMessage("Invalid request to open socket");
+    return;
+  }
+  net::Error result = EnsurePermission(*options);
+
+  // TODO(crbug.com/1119681): Collect metrics for usage and permission checks
+
+  if (result == net::OK) {
+    // TODO(crbug.com/905818): GetNetworkContext()->CreateTCPConnectedSocket
+    GetNetworkContext();
+    NOTIMPLEMENTED();
+  }
+
+  std::move(callback).Run(result);
+}
+
+void DirectSocketsServiceImpl::OpenUdpSocket(
+    blink::mojom::DirectSocketOptionsPtr options,
+    OpenUdpSocketCallback callback) {
+  if (!options) {
+    mojo::ReportBadMessage("Invalid request to open socket");
+    return;
+  }
+  net::Error result = EnsurePermission(*options);
+
+  // TODO(crbug.com/1119681): Collect metrics for usage and permission checks
+
+  if (result == net::OK) {
+    // TODO(crbug.com/1119620): GetNetworkContext()->CreateUDPSocket
+    GetNetworkContext();
+    NOTIMPLEMENTED();
+  }
+
+  std::move(callback).Run(result);
+}
+
+// static
+void DirectSocketsServiceImpl::SetPermissionCallbackForTesting(
+    PermissionCallback callback) {
+  GetPermissionCallbackForTesting() = std::move(callback);
+}
+
+net::Error DirectSocketsServiceImpl::EnsurePermission(
+    const blink::mojom::DirectSocketOptions& options) {
+  DCHECK(base::FeatureList::IsEnabled(features::kDirectSockets));
+
+  if (GetPermissionCallbackForTesting())
+    return GetPermissionCallbackForTesting().Run(options);
+
+  if (options.send_buffer_size < 0 || options.receive_buffer_size < 0)
+    return net::ERR_INVALID_ARGUMENT;
+
+  // TODO(crbug.com/1119662): Check for enterprise software policies.
+  // TODO(crbug.com/1119659): Check permissions policy.
+  // TODO(crbug.com/1119600): Check for transient activation.
+  // TODO(crbug.com/1119600): Implement rate limiting.
+  // TODO(crbug.com/1119601): Check CORS iff requested port is HTTPS.
+
+  // EnsurePermission() will need to become asynchronous:
+  // TODO(crbug.com/1119597): Show consent dialog
+  // TODO(crbug.com/1119661): Reject hostnames that resolve to non-public
+  // addresses.
+
+  return net::ERR_NOT_IMPLEMENTED;
+}
+
+network::mojom::NetworkContext* DirectSocketsServiceImpl::GetNetworkContext() {
+  return frame_host_->GetStoragePartition()->GetNetworkContext();
+}
+
+}  // namespace content
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.h b/content/browser/direct_sockets/direct_sockets_service_impl.h
new file mode 100644
index 0000000..2092d70
--- /dev/null
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.h
@@ -0,0 +1,60 @@
+// 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_BROWSER_DIRECT_SOCKETS_DIRECT_SOCKETS_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_DIRECT_SOCKETS_DIRECT_SOCKETS_SERVICE_IMPL_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/render_frame_host.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "net/base/net_errors.h"
+#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
+
+namespace network {
+namespace mojom {
+class NetworkContext;
+}
+}  // namespace network
+
+namespace content {
+
+// Implementation of the DirectSocketsService Mojo service.
+class CONTENT_EXPORT DirectSocketsServiceImpl
+    : public blink::mojom::DirectSocketsService {
+ public:
+  using PermissionCallback = base::RepeatingCallback<net::Error(
+      const blink::mojom::DirectSocketOptions&)>;
+
+  explicit DirectSocketsServiceImpl(RenderFrameHost& frame_host);
+  ~DirectSocketsServiceImpl() override = default;
+
+  DirectSocketsServiceImpl(const DirectSocketsServiceImpl&) = delete;
+  DirectSocketsServiceImpl& operator=(const DirectSocketsServiceImpl&) = delete;
+
+  static void CreateForFrame(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::DirectSocketsService> receiver);
+
+  // blink::mojom::DirectSocketsService override:
+  void OpenTcpSocket(blink::mojom::DirectSocketOptionsPtr options,
+                     OpenTcpSocketCallback callback) override;
+  void OpenUdpSocket(blink::mojom::DirectSocketOptionsPtr options,
+                     OpenUdpSocketCallback callback) override;
+
+  static void SetPermissionCallbackForTesting(PermissionCallback callback);
+
+ private:
+  net::Error EnsurePermission(const blink::mojom::DirectSocketOptions& options);
+
+  network::mojom::NetworkContext* GetNetworkContext();
+
+  RenderFrameHost* const frame_host_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DIRECT_SOCKETS_DIRECT_SOCKETS_SERVICE_IMPL_H_
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 8c88c4b..4039355c5 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -4856,7 +4856,7 @@
   return network::CrossOriginResourcePolicy::IsNavigationBlocked(
       url, redirect_chain_[0], parent_frame->GetLastCommittedOrigin(),
       *response_head_, parent_frame->GetLastCommittedOrigin(),
-      parent_frame->cross_origin_embedder_policy(),
+      request_destination(), parent_frame->cross_origin_embedder_policy(),
       parent_frame->coep_reporter());
 }
 
diff --git a/content/browser/net/cross_origin_embedder_policy_reporter.cc b/content/browser/net/cross_origin_embedder_policy_reporter.cc
index 7d3e980f..8109a98 100644
--- a/content/browser/net/cross_origin_embedder_policy_reporter.cc
+++ b/content/browser/net/cross_origin_embedder_policy_reporter.cc
@@ -6,6 +6,7 @@
 
 #include "base/values.h"
 #include "content/public/browser/storage_partition.h"
+#include "services/network/public/cpp/request_destination.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
 namespace content {
@@ -40,11 +41,18 @@
 
 void CrossOriginEmbedderPolicyReporter::QueueCorpViolationReport(
     const GURL& blocked_url,
+    network::mojom::RequestDestination destination,
     bool report_only) {
   GURL url_to_pass = StripUsernameAndPassword(blocked_url);
-  QueueAndNotify({std::make_pair("type", "corp"),
-                  std::make_pair("blocked-url", url_to_pass.spec())},
-                 report_only);
+  // We're migrating from "blocked-url" to "blockedURL".
+  // TODO(crbug.com/1119676): Remove "blocked-url" in M90.
+  QueueAndNotify(
+      {std::make_pair("type", "corp"),
+       std::make_pair("blocked-url", url_to_pass.spec()),
+       std::make_pair("blockedURL", url_to_pass.spec()),
+       std::make_pair("destination",
+                      network::RequestDestinationToString(destination))},
+      report_only);
 }
 
 void CrossOriginEmbedderPolicyReporter::BindObserver(
@@ -56,8 +64,11 @@
     const GURL& blocked_url,
     bool report_only) {
   GURL url_to_pass = StripUsernameAndPassword(blocked_url);
+  // We're migrating from "blocked-url" to "blockedURL".
+  // TODO(crbug.com/1119676): Remove "blocked-url" in M90.
   QueueAndNotify({std::make_pair("type", "navigation"),
-                  std::make_pair("blocked-url", url_to_pass.spec())},
+                  std::make_pair("blocked-url", url_to_pass.spec()),
+                  std::make_pair("blockedURL", url_to_pass.spec())},
                  report_only);
 }
 
@@ -72,6 +83,7 @@
     bool report_only) {
   const base::Optional<std::string>& endpoint =
       report_only ? report_only_endpoint_ : endpoint_;
+  const char* const disposition = report_only ? "reporting" : "enforce";
   if (observer_) {
     std::vector<blink::mojom::ReportBodyElementPtr> list;
 
@@ -79,6 +91,8 @@
       list.push_back(blink::mojom::ReportBodyElement::New(
           pair.first.as_string(), pair.second.as_string()));
     }
+    list.push_back(
+        blink::mojom::ReportBodyElement::New("disposition", disposition));
 
     observer_->Notify(blink::mojom::Report::New(
         kType, context_url_, blink::mojom::ReportBody::New(std::move(list))));
@@ -88,6 +102,7 @@
     for (const auto& pair : body) {
       body_to_pass.SetString(pair.first, pair.second);
     }
+    body_to_pass.SetString("disposition", disposition);
     storage_partition_->GetNetworkContext()->QueueReport(
         kType, *endpoint, context_url_, /*user_agent=*/base::nullopt,
         std::move(body_to_pass));
diff --git a/content/browser/net/cross_origin_embedder_policy_reporter.h b/content/browser/net/cross_origin_embedder_policy_reporter.h
index d06fa2a..26c3746 100644
--- a/content/browser/net/cross_origin_embedder_policy_reporter.h
+++ b/content/browser/net/cross_origin_embedder_policy_reporter.h
@@ -14,6 +14,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "third_party/blink/public/mojom/frame/reporting_observer.mojom.h"
 #include "url/gurl.h"
 
@@ -47,6 +48,7 @@
 
   // network::mojom::CrossOriginEmbedderPolicyReporter implementation.
   void QueueCorpViolationReport(const GURL& blocked_url,
+                                network::mojom::RequestDestination destination,
                                 bool report_only) override;
   void Clone(
       mojo::PendingReceiver<network::mojom::CrossOriginEmbedderPolicyReporter>
diff --git a/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc b/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
index cc3bfe6..ee4c226 100644
--- a/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
+++ b/content/browser/net/cross_origin_embedder_policy_reporter_unittest.cc
@@ -11,6 +11,7 @@
 #include "content/public/test/test_storage_partition.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/cpp/cross_origin_embedder_policy.h"
+#include "services/network/public/cpp/request_destination.h"
 #include "services/network/test/test_network_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/frame/reporting_observer.mojom.h"
@@ -19,6 +20,7 @@
 namespace {
 
 using network::CrossOriginEmbedderPolicy;
+using network::mojom::RequestDestination;
 
 class TestNetworkContext : public network::TestNetworkContext {
  public:
@@ -80,25 +82,34 @@
 
   StoragePartition* storage_partition() { return &storage_partition_; }
   const TestNetworkContext& network_context() const { return network_context_; }
-  base::Value CreateBodyForCorp(base::StringPiece s) const {
+  base::Value CreateBodyForCorp(base::StringPiece blocked_url,
+                                RequestDestination destination,
+                                base::StringPiece disposition) const {
     base::Value dict(base::Value::Type::DICTIONARY);
-    for (const auto& pair : CreateBodyForCorpInternal(s)) {
+    for (const auto& pair :
+         CreateBodyForCorpInternal(blocked_url, destination, disposition)) {
       dict.SetKey(std::move(pair.first), base::Value(std::move(pair.second)));
     }
     return dict;
   }
 
-  base::Value CreateBodyForNavigation(base::StringPiece s) {
+  base::Value CreateBodyForNavigation(base::StringPiece blocked_url,
+                                      base::StringPiece disposition) {
     base::Value dict(base::Value::Type::DICTIONARY);
-    for (const auto& pair : CreateBodyForNavigationInternal(s)) {
+    for (const auto& pair :
+         CreateBodyForNavigationInternal(blocked_url, disposition)) {
       dict.SetKey(std::move(pair.first), base::Value(std::move(pair.second)));
     }
     return dict;
   }
 
-  blink::mojom::ReportBodyPtr CreateMojomBodyForCorp(base::StringPiece s) {
+  blink::mojom::ReportBodyPtr CreateMojomBodyForCorp(
+      base::StringPiece blocked_url,
+      RequestDestination destination,
+      base::StringPiece disposition) {
     auto body = blink::mojom::ReportBody::New();
-    for (const auto& pair : CreateBodyForCorpInternal(s)) {
+    for (const auto& pair :
+         CreateBodyForCorpInternal(blocked_url, destination, disposition)) {
       body->body.push_back(blink::mojom::ReportBodyElement::New(
           std::move(pair.first), std::move(pair.second)));
     }
@@ -106,9 +117,11 @@
   }
 
   blink::mojom::ReportBodyPtr CreateMojomBodyForNavigation(
-      base::StringPiece s) {
+      base::StringPiece blocked_url,
+      base::StringPiece disposition) {
     auto body = blink::mojom::ReportBody::New();
-    for (const auto& pair : CreateBodyForNavigationInternal(s)) {
+    for (const auto& pair :
+         CreateBodyForNavigationInternal(blocked_url, disposition)) {
       body->body.push_back(blink::mojom::ReportBodyElement::New(
           std::move(pair.first), std::move(pair.second)));
     }
@@ -117,15 +130,24 @@
 
  private:
   std::vector<std::pair<std::string, std::string>> CreateBodyForCorpInternal(
-      base::StringPiece s) const {
+      base::StringPiece blocked_url,
+      RequestDestination destination,
+      base::StringPiece disposition) const {
     return {std::make_pair("type", "corp"),
-            std::make_pair("blocked-url", s.as_string())};
+            std::make_pair("blocked-url", blocked_url.as_string()),
+            std::make_pair("blockedURL", blocked_url.as_string()),
+            std::make_pair("destination",
+                           network::RequestDestinationToString(destination)),
+            std::make_pair("disposition", disposition.as_string())};
   }
 
   std::vector<std::pair<std::string, std::string>>
-  CreateBodyForNavigationInternal(base::StringPiece s) const {
+  CreateBodyForNavigationInternal(base::StringPiece blocked_url,
+                                  base::StringPiece disposition) const {
     return {std::make_pair("type", "navigation"),
-            std::make_pair("blocked-url", s.as_string())};
+            std::make_pair("blocked-url", blocked_url.as_string()),
+            std::make_pair("blockedURL", blocked_url.as_string()),
+            std::make_pair("disposition", disposition.as_string())};
   }
 
   base::test::TaskEnvironment task_environment_;
@@ -139,8 +161,10 @@
                                              base::nullopt, base::nullopt);
 
   reporter.QueueCorpViolationReport(GURL("https://www1.example.com/y"),
+                                    RequestDestination::kEmpty,
                                     /*report_only=*/false);
   reporter.QueueCorpViolationReport(GURL("https://www2.example.com/x"),
+                                    RequestDestination::kEmpty,
                                     /*report_only=*/true);
 
   EXPECT_TRUE(network_context().reports().empty());
@@ -153,8 +177,10 @@
 
   reporter.QueueCorpViolationReport(
       GURL("https://www1.example.com/x#foo?bar=baz"),
+      RequestDestination::kScript,
       /*report_only=*/false);
   reporter.QueueCorpViolationReport(GURL("http://www2.example.com:41/y"),
+                                    RequestDestination::kEmpty,
                                     /*report_only=*/true);
 
   ASSERT_EQ(2u, network_context().reports().size());
@@ -164,12 +190,14 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.group, "e1");
   EXPECT_EQ(r1.url, kContextUrl);
-  EXPECT_EQ(r1.body,
-            CreateBodyForCorp("https://www1.example.com/x#foo?bar=baz"));
+  EXPECT_EQ(r1.body, CreateBodyForCorp("https://www1.example.com/x#foo?bar=baz",
+                                       RequestDestination::kScript, "enforce"));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.group, "e2");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_EQ(r2.body, CreateBodyForCorp("http://www2.example.com:41/y"));
+  EXPECT_EQ(r2.body,
+            CreateBodyForCorp("http://www2.example.com:41/y",
+                              RequestDestination::kEmpty, "reporting"));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, UserAndPassForCorp) {
@@ -178,8 +206,10 @@
                                              "e1", "e2");
 
   reporter.QueueCorpViolationReport(GURL("https://u:p@www1.example.com/x"),
+                                    RequestDestination::kImage,
                                     /*report_only=*/false);
   reporter.QueueCorpViolationReport(GURL("https://u:p@www2.example.com/y"),
+                                    RequestDestination::kScript,
                                     /*report_only=*/true);
 
   ASSERT_EQ(2u, network_context().reports().size());
@@ -189,11 +219,14 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.group, "e1");
   EXPECT_EQ(r1.url, kContextUrl);
-  EXPECT_EQ(r1.body, CreateBodyForCorp("https://www1.example.com/x"));
+  EXPECT_EQ(r1.body, CreateBodyForCorp("https://www1.example.com/x",
+                                       RequestDestination::kImage, "enforce"));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.group, "e2");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_EQ(r2.body, CreateBodyForCorp("https://www2.example.com/y"));
+  EXPECT_EQ(r2.body,
+            CreateBodyForCorp("https://www2.example.com/y",
+                              RequestDestination::kScript, "reporting"));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, ObserverForCorp) {
@@ -205,8 +238,10 @@
                                              base::nullopt, base::nullopt);
   reporter.BindObserver(std::move(observer_remote));
   reporter.QueueCorpViolationReport(GURL("https://u:p@www1.example.com/x"),
+                                    RequestDestination::kImage,
                                     /*report_only=*/false);
   reporter.QueueCorpViolationReport(GURL("https://u:p@www2.example.com/y"),
+                                    RequestDestination::kEmpty,
                                     /*report_only=*/true);
 
   observer.FlushForTesting();
@@ -217,11 +252,14 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.url, kContextUrl);
   EXPECT_TRUE(mojo::Equals(
-      r1.body, CreateMojomBodyForCorp("https://www1.example.com/x")));
+      r1.body, CreateMojomBodyForCorp("https://www1.example.com/x",
+                                      RequestDestination::kImage, "enforce")));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.url, kContextUrl);
   EXPECT_TRUE(mojo::Equals(
-      r2.body, CreateMojomBodyForCorp("https://www2.example.com/y")));
+      r2.body,
+      CreateMojomBodyForCorp("https://www2.example.com/y",
+                             RequestDestination::kEmpty, "reporting")));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, Clone) {
@@ -233,8 +271,10 @@
   reporter.Clone(remote.BindNewPipeAndPassReceiver());
 
   remote->QueueCorpViolationReport(GURL("https://www1.example.com/x"),
+                                   RequestDestination::kIframe,
                                    /*report_only=*/false);
   remote->QueueCorpViolationReport(GURL("https://www2.example.com/y"),
+                                   RequestDestination::kScript,
                                    /*report_only=*/true);
 
   remote.FlushForTesting();
@@ -246,11 +286,14 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.group, "e1");
   EXPECT_EQ(r1.url, kContextUrl);
-  EXPECT_EQ(r1.body, CreateBodyForCorp("https://www1.example.com/x"));
+  EXPECT_EQ(r1.body, CreateBodyForCorp("https://www1.example.com/x",
+                                       RequestDestination::kIframe, "enforce"));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.group, "e2");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_EQ(r2.body, CreateBodyForCorp("https://www2.example.com/y"));
+  EXPECT_EQ(r2.body,
+            CreateBodyForCorp("https://www2.example.com/y",
+                              RequestDestination::kScript, "reporting"));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, NullEndpointsForNavigation) {
@@ -286,12 +329,13 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.group, "e1");
   EXPECT_EQ(r1.url, kContextUrl);
-  EXPECT_EQ(r1.body,
-            CreateBodyForNavigation("https://www1.example.com/x#foo?bar=baz"));
+  EXPECT_EQ(r1.body, CreateBodyForNavigation(
+                         "https://www1.example.com/x#foo?bar=baz", "enforce"));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.group, "e2");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_EQ(r2.body, CreateBodyForNavigation("http://www2.example.com:41/y"));
+  EXPECT_EQ(r2.body, CreateBodyForNavigation("http://www2.example.com:41/y",
+                                             "reporting"));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, ObserverForNavigation) {
@@ -315,12 +359,13 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.url, kContextUrl);
   EXPECT_TRUE(mojo::Equals(
-      r1.body,
-      CreateMojomBodyForNavigation("https://www1.example.com/x#foo?bar=baz")));
+      r1.body, CreateMojomBodyForNavigation(
+                   "https://www1.example.com/x#foo?bar=baz", "enforce")));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_TRUE(mojo::Equals(
-      r2.body, CreateMojomBodyForNavigation("http://www2.example.com:41/y")));
+  EXPECT_TRUE(
+      mojo::Equals(r2.body, CreateMojomBodyForNavigation(
+                                "http://www2.example.com:41/y", "reporting")));
 }
 
 TEST_F(CrossOriginEmbedderPolicyReporterTest, UserAndPassForNavigation) {
@@ -339,11 +384,13 @@
   EXPECT_EQ(r1.type, "coep");
   EXPECT_EQ(r1.group, "e1");
   EXPECT_EQ(r1.url, kContextUrl);
-  EXPECT_EQ(r1.body, CreateBodyForNavigation("https://www1.example.com/x"));
+  EXPECT_EQ(r1.body,
+            CreateBodyForNavigation("https://www1.example.com/x", "enforce"));
   EXPECT_EQ(r2.type, "coep");
   EXPECT_EQ(r2.group, "e2");
   EXPECT_EQ(r2.url, kContextUrl);
-  EXPECT_EQ(r2.body, CreateBodyForNavigation("https://www2.example.com/y"));
+  EXPECT_EQ(r2.body,
+            CreateBodyForNavigation("https://www2.example.com/y", "reporting"));
 }
 
 }  // namespace
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index eaad71e..d65d2e3f 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -697,6 +697,10 @@
     device_launcher_->AbortLaunch();
     return;
   }
+  // |buffer_contexts_| contain references to |launched_device_| as observers.
+  // Clear those observer references prior to resetting |launced_device_|.
+  for (auto& entry : buffer_contexts_)
+    entry.set_consumer_feedback_observer(nullptr);
   launched_device_.reset();
 }
 
diff --git a/content/browser/sms/sms_browsertest.cc b/content/browser/sms/sms_browsertest.cc
index dabeac33..2404a99 100644
--- a/content/browser/sms/sms_browsertest.cc
+++ b/content/browser/sms/sms_browsertest.cc
@@ -334,12 +334,6 @@
   MockSmsProvider* mock_provider_ptr = provider.get();
   BrowserMainLoop::GetInstance()->SetSmsProviderForTesting(std::move(provider));
 
-  std::string script = R"(
-    // kicks off the sms receiver, adding the service
-    // to the observer's list.
-    navigator.credentials.get({otp: {transport: ["sms"]}});
-  )";
-
   base::RunLoop loop;
 
   EXPECT_CALL(*mock_provider_ptr, Retrieve(_)).WillOnce(Invoke([&loop]() {
@@ -348,26 +342,22 @@
     loop.Quit();
   }));
 
-  EXPECT_TRUE(ExecJs(shell(), script));
+  EXPECT_TRUE(ExecJs(shell(), R"(
+    navigator.credentials.get({otp: {transport: ["sms"]}});
+  )"));
 
   loop.Run();
 
   ASSERT_TRUE(GetSmsFetcher()->HasSubscribers());
+  ASSERT_TRUE(mock_provider_ptr->HasObservers());
 
-  // Wait for UKM to be recorded to avoid race condition between outcome
-  // capture and evaluation.
-  base::RunLoop ukm_loop;
-  ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
-                                        ukm_loop.QuitClosure());
-
-  // Reload the page.
+  // Reload the page. This destroys the ExecutionContext and resets any HeapMojo
+  // connections.
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
-  ukm_loop.Run();
-
   ASSERT_FALSE(GetSmsFetcher()->HasSubscribers());
 
-  ExpectOutcomeUKM(url, blink::SMSReceiverOutcome::kTimeout);
+  ExpectNoOutcomeUKM();
 }
 
 IN_PROC_BROWSER_TEST_F(SmsBrowserTest, Close) {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 1ae1a6b..f5e7b729 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -623,6 +623,9 @@
   WebRuntimeFeatures::EnableBackForwardCache(
       content::IsBackForwardCacheEnabled());
 
+  if (base::FeatureList::IsEnabled(features::kDirectSockets))
+    WebRuntimeFeatures::EnableDirectSockets(true);
+
   if (base::FeatureList::IsEnabled(
           blink::features::kAppCacheRequireOriginTrial)) {
     // The kAppCacheRequireOriginTrial is a flag that controls whether or not
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 48d6fc3..7dfb123 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -507,6 +507,10 @@
 const base::Feature kPushSubscriptionChangeEvent{
     "PushSubscriptionChangeEvent", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables the Direct Sockets API.
+const base::Feature kDirectSockets{"DirectSockets",
+                                   base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls whether FileURLLoaderFactory can fetch additional files based on the
 // isolated world's origin. This feature is disabled by default because we want
 // content scripts to have the same permissions as the page they are injected
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 9c470ae..0df682c 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -111,6 +111,7 @@
 CONTENT_EXPORT extern const base::Feature
     kProcessSharingWithStrictSiteInstances;
 CONTENT_EXPORT extern const base::Feature kPushSubscriptionChangeEvent;
+CONTENT_EXPORT extern const base::Feature kDirectSockets;
 CONTENT_EXPORT extern const base::Feature
     kRelaxIsolatedWorldCorsInFileUrlLoaderFactory;
 CONTENT_EXPORT extern const base::Feature kReloadHiddenTabsWithCrashedSubframes;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index b2e4272f..4e9cfea 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1450,6 +1450,7 @@
   } else {
     # Non-Android.
     sources += [
+      "../browser/direct_sockets/direct_sockets_browsertest.cc",
       "../browser/host_zoom_map_impl_browsertest.cc",
       "../browser/serial/serial_browsertest.cc",
       "../browser/speech/speech_recognition_browsertest.cc",
diff --git a/content/test/data/direct_sockets/index.html b/content/test/data/direct_sockets/index.html
new file mode 100644
index 0000000..6a47189a
--- /dev/null
+++ b/content/test/data/direct_sockets/index.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Direct Sockets Test</title>
+  <script>
+    'use strict';
+
+    async function openTcp(options) {
+      try {
+        let tcpSocket = await navigator.openTCPSocket(options);
+        return 'openTcp succeeded';
+      } catch(error) {
+        return ('openTcp failed: ' + error);
+      }
+    }
+
+    async function openUdp(options) {
+      try {
+        let udpSocket = await navigator.openUDPSocket(options);
+        return 'openUdp succeeded';
+      } catch(error) {
+        return ('openUdp failed: ' + error);
+      }
+    }
+
+  </script>
+</head>
+<body>
+  <h1>Direct Sockets Test</h1>
+</body>
+</html>
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index ca6d19cf..312bace 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -552,13 +552,6 @@
     context_process = base::LaunchProcess(launch_command, launch_options);
   }
 
-  if (context_process.IsValid()) {
-    // Set |context_process| termination to teardown its job and sub-processes.
-    zx_status_t result = zx_job_set_critical(launch_options.job_handle, 0,
-                                             context_process.Handle());
-    ZX_CHECK(ZX_OK == result, result) << "zx_job_set_critical";
-  }
-
   // |context_request|, any DevTools channels and data directory channels were
   // transferred (not copied) to the Context process.
   ignore_result(context_request.TakeChannel().release());
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index d89e233..02d074a 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -56,7 +56,7 @@
 
 ci.console_view(
     name = "chromium.chromiumos",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     ordering = {
         None: ["default"],
         "default": ci.ordering(short_names = ["ful", "rel"]),
@@ -1137,7 +1137,7 @@
 
 ci.chromiumos_builder(
     name = "chromeos-amd64-generic-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     console_view_entry = ci.console_view_entry(
         category = "simple|release|x64",
         short_name = "rel",
@@ -1157,7 +1157,7 @@
 
 ci.chromiumos_builder(
     name = "chromeos-arm-generic-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     console_view_entry = ci.console_view_entry(
         category = "simple|release",
         short_name = "arm",
@@ -1168,6 +1168,7 @@
 
 ci.chromiumos_builder(
     name = "chromeos-kevin-rel",
+    branch_selector = branches.ALL_RELEASES,
     console_view_entry = ci.console_view_entry(
         category = "simple|release",
         short_name = "kvn",
@@ -1188,7 +1189,7 @@
 
 ci.chromiumos_builder(
     name = "linux-chromeos-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     console_view_entry = ci.console_view_entry(
         category = "default",
         short_name = "rel",
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index b3e51bc5..d86d0257 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -37,7 +37,7 @@
 
 try_.list_view(
     name = "tryserver.chromium.chromiumos",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
 )
 
 try_.list_view(
@@ -538,7 +538,7 @@
 
 try_.chromium_chromiumos_builder(
     name = "chromeos-amd64-generic-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     main_list_view = settings.main_list_view_name,
     tryjob = try_.job(),
 )
@@ -549,7 +549,7 @@
 
 try_.chromium_chromiumos_builder(
     name = "chromeos-arm-generic-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     main_list_view = settings.main_list_view_name,
     tryjob = try_.job(),
 )
@@ -567,6 +567,7 @@
 
 try_.chromium_chromiumos_builder(
     name = "chromeos-kevin-rel",
+    branch_selector = branches.ALL_RELEASES,
     main_list_view = settings.main_list_view_name,
     tryjob = try_.job(
         location_regexp = [
@@ -579,7 +580,7 @@
 
 try_.chromium_chromiumos_builder(
     name = "linux-chromeos-rel",
-    branch_selector = branches.STANDARD_RELEASES,
+    branch_selector = branches.ALL_RELEASES,
     goma_jobs = goma.jobs.J150,
     main_list_view = settings.main_list_view_name,
     tryjob = try_.job(cancel_stale = False),
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 44f3d49..2141943 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -175,6 +175,7 @@
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/table_view/cells:cells_constants",
     "//ios/chrome/browser/ui/table_view/cells/resources:table_view_cell_check_mark",
+    "//ios/chrome/browser/upgrade:public",
     "//ios/chrome/browser/voice",
     "//ios/chrome/browser/web:web",
     "//ios/chrome/common",
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm
index 34a6224..4ba347c 100644
--- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm
+++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm
@@ -240,6 +240,12 @@
     _passwordCheckItem.infoButtonHidden = YES;
     _passwordCheckItem.trailingImage = nil;
 
+    // Show unsafe state if user already ran password check and there are
+    // compromised credentials.
+    if (!_passwordCheckManager->GetCompromisedCredentials().empty()) {
+      _passwordCheckRowState = PasswordCheckRowStateUnSafe;
+    }
+
     _safeBrowsingCheckRowState = SafeBrowsingCheckRowStateDefault;
     _safeBrowsingCheckItem =
         [[SettingsCheckItem alloc] initWithType:SafeBrowsingItemType];
@@ -275,6 +281,10 @@
   [_consumer setCheckItems:checkItems];
   [_consumer setSafetyCheckHeaderItem:self.headerItem];
   [_consumer setCheckStartItem:self.checkStartItem];
+
+  // Need to reconfigure the |passwordCheckItem| to an unsafe state if there are
+  // remaining password issues.
+  [self reconfigurePasswordCheckItem];
 }
 
 #pragma mark - PasswordCheckObserver
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
index 916d3b88..1c6de40 100644
--- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -29,7 +29,10 @@
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/main/browser.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
+#include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/search_engines/search_engine_observer_bridge.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
@@ -51,6 +54,7 @@
 #import "ios/chrome/browser/ui/settings/autofill/autofill_profile_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/bandwidth_management_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/cells/account_sign_in_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_check_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h"
 #import "ios/chrome/browser/ui/settings/content_settings_table_view_controller.h"
@@ -77,6 +81,7 @@
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#include "ios/chrome/browser/upgrade/upgrade_utils.h"
 #include "ios/chrome/browser/voice/speech_input_locale_config.h"
 #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
@@ -169,6 +174,7 @@
     ChromeIdentityServiceObserver,
     GoogleServicesSettingsCoordinatorDelegate,
     IdentityManagerObserverBridgeDelegate,
+    PasswordCheckObserver,
     PopoverLabelViewControllerDelegate,
     PrefObserverDelegate,
     PrivacyCoordinatorDelegate,
@@ -187,6 +193,11 @@
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityObserverBridge;
   std::unique_ptr<SyncObserverBridge> _syncObserverBridge;
+  // A helper object for observing changes in the password check status
+  // and changes to the compromised credentials list.
+  std::unique_ptr<PasswordCheckObserverBridge> _passwordCheckObserver;
+  // The service responsible for password check feature.
+  scoped_refptr<IOSChromePasswordCheckManager> _passwordCheckManager;
   // Whether the impression of the Signin button has already been recorded.
   BOOL _hasRecordedSigninImpression;
   // PrefBackedBoolean for ShowMemoryDebugTools switch.
@@ -197,6 +208,8 @@
   SettingsSwitchItem* _showMemoryDebugToolsItem;
   // The item related to the switch for the show suggestions setting.
   SettingsSwitchItem* _articlesForYouItem;
+  // The item related to the safety check.
+  SettingsCheckItem* _safetyCheckItem;
 
   // Mediator to configure the sign-in promo cell. Also used to received
   // identity update notifications.
@@ -297,6 +310,14 @@
 
     PrefService* prefService = _browserState->GetPrefs();
 
+    if (base::FeatureList::IsEnabled(kSafetyCheckIOS)) {
+      _passwordCheckManager =
+          IOSChromePasswordCheckManagerFactory::GetForBrowserState(
+              _browserState);
+      _passwordCheckObserver = std::make_unique<PasswordCheckObserverBridge>(
+          self, _passwordCheckManager.get());
+    }
+
     _articlesEnabled = [[PrefBackedBoolean alloc]
         initWithPrefService:prefService
                    prefName:prefs::kArticlesForYouEnabled];
@@ -630,14 +651,29 @@
   return _voiceSearchDetailItem;
 }
 
-- (TableViewItem*)safetyCheckDetailItem {
+- (SettingsCheckItem*)safetyCheckDetailItem {
   NSString* safetyCheckTitle =
       l10n_util::GetNSString(IDS_OPTIONS_ADVANCED_SECTION_TITLE_SAFETY_CHECK);
-  return [self detailItemWithType:ItemTypeSafetyCheck
-                             text:safetyCheckTitle
-                       detailText:nil
-                    iconImageName:kSettingsSafetyCheckImageName
-          accessibilityIdentifier:nil];
+  _safetyCheckItem =
+      [[SettingsCheckItem alloc] initWithType:ItemTypeSafetyCheck];
+  _safetyCheckItem.text = safetyCheckTitle;
+  _safetyCheckItem.enabled = YES;
+  _safetyCheckItem.indicatorHidden = YES;
+  _safetyCheckItem.infoButtonHidden = YES;
+  _safetyCheckItem.trailingImage = nil;
+  _safetyCheckItem.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+  UIImage* safetyCheckIcon = [UIImage imageNamed:kSettingsSafetyCheckImageName];
+  _safetyCheckItem.leadingImage = safetyCheckIcon;
+
+  // Check if an issue state should be shown for updates.
+  if (!IsAppUpToDate()) {
+    UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
+        imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+    _safetyCheckItem.trailingImage = unSafeIconImage;
+    _safetyCheckItem.trailingImageTintColor = [UIColor colorNamed:kRedColor];
+  }
+
+  return _safetyCheckItem;
 }
 
 - (TableViewItem*)privacyDetailItem {
@@ -1032,7 +1068,7 @@
 }
 #endif  // BUILDFLAG(CHROMIUM_BRANDING) && !defined(NDEBUG)
 
-#pragma mark Private methods
+#pragma mark - Private methods
 
 - (void)showSyncGoogleService {
   DCHECK(!_googleServicesSettingsCoordinator);
@@ -1056,6 +1092,29 @@
   [_safetyCheckCoordinator start];
 }
 
+// Checks if there are any remaining password issues from the last time password
+// check was run.
+- (BOOL)hasPasswordIssuesRemaining {
+  return !_passwordCheckManager->GetCompromisedCredentials().empty();
+}
+
+// Displays a red issue state on |_safetyCheckItem| if there is a reamining
+// issue for any of the checks.
+- (void)setSafetyCheckIssueStateUnsafe:(BOOL)isUnsafe {
+  // TODO(crbug.com/1078782): Add aditional check to make sure check has been
+  // run at least once.
+  if (isUnsafe) {
+    UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
+        imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+    _safetyCheckItem.trailingImage = unSafeIconImage;
+    _safetyCheckItem.trailingImageTintColor = [UIColor colorNamed:kRedColor];
+  } else {
+    _safetyCheckItem.trailingImage = nil;
+    _safetyCheckItem.trailingImageTintColor = nil;
+  }
+  [self reconfigureCellsForItems:@[ _safetyCheckItem ]];
+}
+
 // Shows Privacy screen.
 - (void)showPrivacy {
   DCHECK(!_privacyCoordinator);
@@ -1335,6 +1394,18 @@
   }
 }
 
+#pragma mark - PasswordCheckObserver
+
+- (void)passwordCheckStateDidChange:(PasswordCheckState)state {
+  [self setSafetyCheckIssueStateUnsafe:[self hasPasswordIssuesRemaining]];
+}
+
+- (void)compromisedCredentialsDidChange:
+    (password_manager::CompromisedCredentialsManager::CredentialsView)
+        credentials {
+  [self setSafetyCheckIssueStateUnsafe:[self hasPasswordIssuesRemaining]];
+}
+
 #pragma mark - PrefObserverDelegate
 
 - (void)onPreferenceChanged:(const std::string&)preferenceName {
diff --git a/ios/chrome/browser/upgrade/BUILD.gn b/ios/chrome/browser/upgrade/BUILD.gn
index fcf595e1..504846e 100644
--- a/ios/chrome/browser/upgrade/BUILD.gn
+++ b/ios/chrome/browser/upgrade/BUILD.gn
@@ -10,6 +10,7 @@
     "upgrade_recommended_details.h",
   ]
   deps = [
+    ":public",
     "resources:infobar_update",
     "//base",
     "//components/infobars/core",
@@ -25,6 +26,22 @@
   frameworks = [ "UIKit.framework" ]
 }
 
+source_set("public") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "upgrade_constants.h",
+    "upgrade_constants.mm",
+    "upgrade_utils.h",
+    "upgrade_utils.mm",
+  ]
+  deps = [
+    "//base",
+    "//components/version_info:version_info",
+    "//ios/chrome/browser",
+  ]
+  frameworks = [ "UIKit.framework" ]
+}
+
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
diff --git a/ios/chrome/browser/upgrade/upgrade_center.mm b/ios/chrome/browser/upgrade/upgrade_center.mm
index 1e216c1..003d2b87 100644
--- a/ios/chrome/browser/upgrade/upgrade_center.mm
+++ b/ios/chrome/browser/upgrade/upgrade_center.mm
@@ -18,6 +18,7 @@
 #include "components/version_info/version_info.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
+#import "ios/chrome/browser/upgrade/upgrade_constants.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/web/common/url_scheme_util.h"
@@ -54,10 +55,6 @@
 
 namespace {
 
-// The user defaults key for the upgrade version.
-NSString* const kNextVersionKey = @"UpdateInfobarNextVersion";
-// The user defaults key for the upgrade URL.
-NSString* const kUpgradeURLKey = @"UpdateInfobarUpgradeURL";
 // The user defaults key for the last time the update infobar was shown.
 NSString* const kLastInfobarDisplayTimeKey = @"UpdateInfobarLastDisplayTime";
 // The amount of time that must elapse before showing the infobar again.
@@ -253,7 +250,7 @@
 
 - (BOOL)isCurrentVersionObsolete {
   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  NSString* nextVersion = [defaults stringForKey:kNextVersionKey];
+  NSString* nextVersion = [defaults stringForKey:kIOSChromeNextVersionKey];
   if (nextVersion) {
     const base::Version& current_version = version_info::GetVersion();
     const std::string upgrade = base::SysNSStringToUTF8(nextVersion);
@@ -345,8 +342,8 @@
   [self hideUpgradeInfoBars];
 
   if (shouldUpgrade) {
-    NSString* urlString =
-        [[NSUserDefaults standardUserDefaults] valueForKey:kUpgradeURLKey];
+    NSString* urlString = [[NSUserDefaults standardUserDefaults]
+        valueForKey:kIOSChromeUpgradeURLKey];
     if (!urlString)
       return;  // Missing URL, no upgrade possible.
 
@@ -428,15 +425,16 @@
 
   // Reset the display clock when the version changes.
   NSString* newVersionString = base::SysUTF8ToNSString(details.next_version);
-  NSString* previousVersionString = [defaults stringForKey:kNextVersionKey];
+  NSString* previousVersionString =
+      [defaults stringForKey:kIOSChromeNextVersionKey];
   if (!previousVersionString ||
       ![previousVersionString isEqualToString:newVersionString]) {
     [defaults removeObjectForKey:kLastInfobarDisplayTimeKey];
   }
 
   [defaults setValue:base::SysUTF8ToNSString(upgradeUrl.spec())
-              forKey:kUpgradeURLKey];
-  [defaults setValue:newVersionString forKey:kNextVersionKey];
+              forKey:kIOSChromeUpgradeURLKey];
+  [defaults setValue:newVersionString forKey:kIOSChromeNextVersionKey];
 
   if ([self shouldShowInfoBar])
     [self showUpgradeInfoBars];
@@ -445,8 +443,8 @@
 - (void)resetForTests {
   [[UpgradeCenter sharedInstance] hideUpgradeInfoBars];
   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults removeObjectForKey:kNextVersionKey];
-  [defaults removeObjectForKey:kUpgradeURLKey];
+  [defaults removeObjectForKey:kIOSChromeNextVersionKey];
+  [defaults removeObjectForKey:kIOSChromeUpgradeURLKey];
   [defaults removeObjectForKey:kLastInfobarDisplayTimeKey];
   [_clients removeAllObjects];
 }
diff --git a/ios/chrome/browser/upgrade/upgrade_constants.h b/ios/chrome/browser/upgrade/upgrade_constants.h
new file mode 100644
index 0000000..ff24b60
--- /dev/null
+++ b/ios/chrome/browser/upgrade/upgrade_constants.h
@@ -0,0 +1,15 @@
+// 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 IOS_CHROME_BROWSER_UPGRADE_UPGRADE_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_UPGRADE_UPGRADE_CONSTANTS_H_
+
+#import <Foundation/Foundation.h>
+
+// The user defaults key for the upgrade version.
+extern NSString* const kIOSChromeNextVersionKey;
+// The user defaults key for the upgrade URL.
+extern NSString* const kIOSChromeUpgradeURLKey;
+
+#endif  // IOS_CHROME_BROWSER_UPGRADE_UPGRADE_CONSTANTS_H_
diff --git a/ios/chrome/browser/upgrade/upgrade_constants.mm b/ios/chrome/browser/upgrade/upgrade_constants.mm
new file mode 100644
index 0000000..fee7b48
--- /dev/null
+++ b/ios/chrome/browser/upgrade/upgrade_constants.mm
@@ -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.
+
+#import "ios/chrome/browser/upgrade/upgrade_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+NSString* const kIOSChromeNextVersionKey = @"UpdateInfobarUpgradeURL";
+NSString* const kIOSChromeUpgradeURLKey = @"UpdateInfobarNextVersion";
diff --git a/ios/chrome/browser/upgrade/upgrade_utils.h b/ios/chrome/browser/upgrade/upgrade_utils.h
new file mode 100644
index 0000000..2e08d79
--- /dev/null
+++ b/ios/chrome/browser/upgrade/upgrade_utils.h
@@ -0,0 +1,13 @@
+// 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 IOS_CHROME_BROWSER_UPGRADE_UPGRADE_UTILS_H_
+#define IOS_CHROME_BROWSER_UPGRADE_UPGRADE_UTILS_H_
+
+#import <UIKit/UIKit.h>
+
+// Returns YES if app is up to date.
+bool IsAppUpToDate();
+
+#endif  // IOS_CHROME_BROWSER_UPGRADE_UPGRADE_UTILS_H_
diff --git a/ios/chrome/browser/upgrade/upgrade_utils.mm b/ios/chrome/browser/upgrade/upgrade_utils.mm
new file mode 100644
index 0000000..1f8b3777
--- /dev/null
+++ b/ios/chrome/browser/upgrade/upgrade_utils.mm
@@ -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.
+
+#import "ios/chrome/browser/upgrade/upgrade_utils.h"
+
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/version.h"
+#include "components/version_info/version_info.h"
+#include "ios/chrome/browser/upgrade/upgrade_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+bool IsAppUpToDate() {
+  // See if the user is out of date based on current information.
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+  NSString* nextVersionString =
+      [defaults stringForKey:kIOSChromeNextVersionKey];
+  base::Version nextVersion =
+      base::Version(base::SysNSStringToUTF8(nextVersionString));
+
+  const base::Version& currentVersion = version_info::GetVersion();
+
+  // TODO(crbug.com/1078782): Add max supported version support.
+  if (nextVersion.IsValid() && nextVersion > currentVersion &&
+      (nextVersion.components()[0] - currentVersion.components()[0]) < 9) {
+    return NO;
+  }
+  return YES;
+}
diff --git a/media/gpu/vaapi/va.sigs b/media/gpu/vaapi/va.sigs
index c24aad2..a735f31 100644
--- a/media/gpu/vaapi/va.sigs
+++ b/media/gpu/vaapi/va.sigs
@@ -6,6 +6,7 @@
 // Functions from libva used in chromium code.
 //------------------------------------------------
 VAStatus vaBeginPicture(VADisplay dpy, VAContextID context, VASurfaceID render_target);
+const char *vaConfigAttribTypeStr(VAConfigAttribType configAttribType);
 VAStatus vaCreateBuffer(VADisplay dpy, VAContextID context, VABufferType type, unsigned int size, unsigned int num_elements, void *data, VABufferID *buf_id);
 VAStatus vaCreateConfig(VADisplay dpy, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id);
 VAStatus vaCreateContext(VADisplay dpy, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context);
@@ -38,6 +39,7 @@
 VAStatus vaQueryImageFormats(VADisplay dpy, VAImageFormat *format_list, int *num_formats);
 VAStatus vaQuerySurfaceAttributes(VADisplay dpy, VAConfigID config, VASurfaceAttrib *attrib_list, unsigned int *num_attribs);
 const char* vaQueryVendorString(VADisplay dpy);
+VAStatus vaQueryVideoProcPipelineCaps(VADisplay dpy, VAContextID context, VABufferID *filters, unsigned int num_filters, VAProcPipelineCaps *pipeline_caps);
 VAStatus vaRenderPicture(VADisplay dpy, VAContextID context, VABufferID *buffers, int num_buffers);
 VAStatus vaSyncSurface(VADisplay dpy, VASurfaceID render_target);
 VAStatus vaTerminate(VADisplay dpy);
diff --git a/services/network/public/cpp/cross_origin_read_blocking.cc b/services/network/public/cpp/cross_origin_read_blocking.cc
index 5892de9..af40fb6 100644
--- a/services/network/public/cpp/cross_origin_read_blocking.cc
+++ b/services/network/public/cpp/cross_origin_read_blocking.cc
@@ -852,6 +852,7 @@
   if (CrossOriginResourcePolicy::IsBlocked(
           request_url, request_url, request_initiator, response,
           kOverreachingRequestMode, request_initiator_origin_lock,
+          network::mojom::RequestDestination::kEmpty,
           CrossOriginEmbedderPolicy())) {
     // Ignore mime types and/or sniffing and have CORB block all responses with
     // COR*P* header.
diff --git a/services/network/public/cpp/cross_origin_resource_policy.cc b/services/network/public/cpp/cross_origin_resource_policy.cc
index cd2b23c..39791e4 100644
--- a/services/network/public/cpp/cross_origin_resource_policy.cc
+++ b/services/network/public/cpp/cross_origin_resource_policy.cc
@@ -208,6 +208,7 @@
     const base::Optional<url::Origin>& request_initiator,
     mojom::RequestMode request_mode,
     base::Optional<url::Origin> request_initiator_origin_lock,
+    mojom::RequestDestination request_destination,
     const CrossOriginEmbedderPolicy& embedder_policy,
     mojom::CrossOriginEmbedderPolicyReporter* reporter) {
   constexpr auto kBlockedDueToCoep = mojom::BlockedByResponseReason::
@@ -223,7 +224,8 @@
         ToCorpResult(result));
     if (result == kBlockedDueToCoep ||
         (result.has_value() && request_mode == mojom::RequestMode::kNavigate)) {
-      reporter->QueueCorpViolationReport(original_url, /*report_only=*/true);
+      reporter->QueueCorpViolationReport(original_url, request_destination,
+                                         /*report_only=*/true);
     }
   }
 
@@ -240,7 +242,8 @@
   if (reporter &&
       (result == kBlockedDueToCoep ||
        (result.has_value() && request_mode == mojom::RequestMode::kNavigate))) {
-    reporter->QueueCorpViolationReport(original_url, /*report_only=*/false);
+    reporter->QueueCorpViolationReport(original_url, request_destination,
+                                       /*report_only=*/false);
   }
   return result;
 }
@@ -260,6 +263,7 @@
     const network::mojom::URLResponseHead& response,
     mojom::RequestMode request_mode,
     base::Optional<url::Origin> request_initiator_origin_lock,
+    mojom::RequestDestination request_destination,
     const CrossOriginEmbedderPolicy& embedder_policy,
     mojom::CrossOriginEmbedderPolicyReporter* reporter) {
   // From https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header:
@@ -279,7 +283,8 @@
 
   return IsBlockedInternalWithReporting(
       policy, request_url, original_url, request_initiator, request_mode,
-      request_initiator_origin_lock, embedder_policy, reporter);
+      request_initiator_origin_lock, request_destination, embedder_policy,
+      reporter);
 }
 
 // static
@@ -291,6 +296,7 @@
     base::Optional<std::string> corp_header_value,
     mojom::RequestMode request_mode,
     base::Optional<url::Origin> request_initiator_origin_lock,
+    mojom::RequestDestination request_destination,
     const CrossOriginEmbedderPolicy& embedder_policy,
     mojom::CrossOriginEmbedderPolicyReporter* reporter) {
   // From https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header:
@@ -302,7 +308,8 @@
 
   return IsBlockedInternalWithReporting(
       policy, request_url, original_url, request_initiator, request_mode,
-      request_initiator_origin_lock, embedder_policy, reporter);
+      request_initiator_origin_lock, request_destination, embedder_policy,
+      reporter);
 }
 
 // static
@@ -313,6 +320,7 @@
     const base::Optional<url::Origin>& request_initiator,
     const network::mojom::URLResponseHead& response,
     base::Optional<url::Origin> request_initiator_origin_lock,
+    mojom::RequestDestination request_destination,
     const CrossOriginEmbedderPolicy& embedder_policy,
     mojom::CrossOriginEmbedderPolicyReporter* reporter) {
   ParsedHeader policy =
@@ -321,7 +329,7 @@
   return IsBlockedInternalWithReporting(
       policy, request_url, original_url, request_initiator,
       mojom::RequestMode::kNavigate, request_initiator_origin_lock,
-      embedder_policy, reporter);
+      request_destination, embedder_policy, reporter);
 }
 
 // static
diff --git a/services/network/public/cpp/cross_origin_resource_policy.h b/services/network/public/cpp/cross_origin_resource_policy.h
index 0d7829fa..22c08b3 100644
--- a/services/network/public/cpp/cross_origin_resource_policy.h
+++ b/services/network/public/cpp/cross_origin_resource_policy.h
@@ -46,6 +46,7 @@
       const network::mojom::URLResponseHead& response,
       mojom::RequestMode request_mode,
       base::Optional<url::Origin> request_initiator_origin_lock,
+      mojom::RequestDestination request_destination,
       const CrossOriginEmbedderPolicy& embedder_policy,
       mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
       WARN_UNUSED_RESULT;
@@ -59,6 +60,7 @@
       base::Optional<std::string> corp_header_value,
       mojom::RequestMode request_mode,
       base::Optional<url::Origin> request_initiator_origin_lock,
+      mojom::RequestDestination request_destination,
       const CrossOriginEmbedderPolicy& embedder_policy,
       mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
       WARN_UNUSED_RESULT;
@@ -71,6 +73,7 @@
       const base::Optional<url::Origin>& request_initiator,
       const network::mojom::URLResponseHead& response,
       base::Optional<url::Origin> request_initiator_origin_lock,
+      mojom::RequestDestination request_destination,
       const CrossOriginEmbedderPolicy& embedder_policy,
       mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr);
 
diff --git a/services/network/public/cpp/cross_origin_resource_policy_unittest.cc b/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
index b18f4ab0b..5d6a9981 100644
--- a/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
+++ b/services/network/public/cpp/cross_origin_resource_policy_unittest.cc
@@ -19,10 +19,15 @@
 class TestCoepReporter final : public mojom::CrossOriginEmbedderPolicyReporter {
  public:
   struct Report {
-    Report(const GURL& blocked_url, bool report_only)
-        : blocked_url(blocked_url), report_only(report_only) {}
+    Report(const GURL& blocked_url,
+           mojom::RequestDestination destination,
+           bool report_only)
+        : blocked_url(blocked_url),
+          destination(destination),
+          report_only(report_only) {}
 
     const GURL blocked_url;
+    const mojom::RequestDestination destination;
     const bool report_only;
   };
 
@@ -33,8 +38,9 @@
 
   // mojom::CrossOriginEmbedderPolicyReporter implementation.
   void QueueCorpViolationReport(const GURL& blocked_url,
+                                mojom::RequestDestination destination,
                                 bool report_only) override {
-    reports_.push_back(Report(blocked_url, report_only));
+    reports_.emplace_back(blocked_url, destination, report_only);
   }
   void Clone(
       mojo::PendingReceiver<network::mojom::CrossOriginEmbedderPolicyReporter>
@@ -177,8 +183,8 @@
           "HTTP/1.1 200 OK\n"
           "cross-origin-resource-policy: cross-origin\n"));
 
-  GURL original_destination("https://original.example.com/x/y");
-  GURL destination("https://www.example.com/z/u");
+  const GURL original_url("https://original.example.com/x/y");
+  const GURL final_url("https://www.example.com/z/u");
 
   url::Origin destination_origin =
       url::Origin::Create(GURL("https://www.example.com"));
@@ -186,6 +192,7 @@
       url::Origin::Create(GURL("https://www2.example.com"));
 
   constexpr auto kAllow = base::nullopt;
+  using mojom::RequestDestination;
   using mojom::RequestMode;
 
   struct TestCase {
@@ -229,26 +236,29 @@
          test_case.expectation_with_coep_require_corp);
 
     // COEP: none, COEP-report-only: none
-    EXPECT_EQ(test_case.expectation_with_coep_none,
-              CrossOriginResourcePolicy::IsBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.request_mode,
-                  test_case.origin, embedder_policy, &reporter));
+    EXPECT_EQ(
+        test_case.expectation_with_coep_none,
+        CrossOriginResourcePolicy::IsBlocked(
+            final_url, original_url, test_case.origin, *test_case.response_info,
+            test_case.request_mode, test_case.origin,
+            RequestDestination::kImage, embedder_policy, &reporter));
 
     EXPECT_TRUE(reporter.reports().empty());
 
     reporter.ClearReports();
     // COEP: require-corp, COEP-report-only: none
     embedder_policy.value = mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
-    EXPECT_EQ(test_case.expectation_with_coep_require_corp,
-              CrossOriginResourcePolicy::IsBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.request_mode,
-                  test_case.origin, embedder_policy, &reporter));
+    EXPECT_EQ(
+        test_case.expectation_with_coep_require_corp,
+        CrossOriginResourcePolicy::IsBlocked(
+            final_url, original_url, test_case.origin, *test_case.response_info,
+            test_case.request_mode, test_case.origin,
+            RequestDestination::kImage, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(1u, reporter.reports().size());
       EXPECT_FALSE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kImage);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
@@ -258,15 +268,17 @@
     embedder_policy.value = mojom::CrossOriginEmbedderPolicyValue::kNone;
     embedder_policy.report_only_value =
         mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
-    EXPECT_EQ(test_case.expectation_with_coep_none,
-              CrossOriginResourcePolicy::IsBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.request_mode,
-                  test_case.origin, embedder_policy, &reporter));
+    EXPECT_EQ(
+        test_case.expectation_with_coep_none,
+        CrossOriginResourcePolicy::IsBlocked(
+            final_url, original_url, test_case.origin, *test_case.response_info,
+            test_case.request_mode, test_case.origin,
+            RequestDestination::kScript, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(1u, reporter.reports().size());
       EXPECT_TRUE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kScript);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
@@ -276,17 +288,20 @@
     embedder_policy.value = mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
     embedder_policy.report_only_value =
         mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
-    EXPECT_EQ(test_case.expectation_with_coep_require_corp,
-              CrossOriginResourcePolicy::IsBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.request_mode,
-                  test_case.origin, embedder_policy, &reporter));
+    EXPECT_EQ(
+        test_case.expectation_with_coep_require_corp,
+        CrossOriginResourcePolicy::IsBlocked(
+            final_url, original_url, test_case.origin, *test_case.response_info,
+            test_case.request_mode, test_case.origin,
+            RequestDestination::kEmpty, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(2u, reporter.reports().size());
       EXPECT_TRUE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kEmpty);
       EXPECT_FALSE(reporter.reports()[1].report_only);
-      EXPECT_EQ(reporter.reports()[1].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[1].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[1].destination, RequestDestination::kEmpty);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
@@ -311,8 +326,8 @@
           "HTTP/1.1 200 OK\n"
           "cross-origin-resource-policy: cross-origin\n"));
 
-  GURL original_destination("https://original.example.com/x/y");
-  GURL destination("https://www.example.com/z/u");
+  GURL original_url("https://original.example.com/x/y");
+  GURL final_url("https://www.example.com/z/u");
 
   url::Origin destination_origin =
       url::Origin::Create(GURL("https://www.example.com"));
@@ -320,6 +335,7 @@
       url::Origin::Create(GURL("https://www2.example.com"));
 
   constexpr auto kAllow = base::nullopt;
+  using mojom::RequestDestination;
   using mojom::RequestMode;
 
   struct TestCase {
@@ -357,9 +373,9 @@
     // COEP: none, COEP-report-only: none
     EXPECT_EQ(test_case.expectation_with_coep_none,
               CrossOriginResourcePolicy::IsNavigationBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.origin, embedder_policy,
-                  &reporter));
+                  final_url, original_url, test_case.origin,
+                  *test_case.response_info, test_case.origin,
+                  RequestDestination::kImage, embedder_policy, &reporter));
 
     EXPECT_TRUE(reporter.reports().empty());
 
@@ -368,13 +384,14 @@
     embedder_policy.value = mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
     EXPECT_EQ(test_case.expectation_with_coep_require_corp,
               CrossOriginResourcePolicy::IsNavigationBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.origin, embedder_policy,
-                  &reporter));
+                  final_url, original_url, test_case.origin,
+                  *test_case.response_info, test_case.origin,
+                  RequestDestination::kImage, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(1u, reporter.reports().size());
       EXPECT_FALSE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kImage);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
@@ -386,13 +403,14 @@
         mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
     EXPECT_EQ(test_case.expectation_with_coep_none,
               CrossOriginResourcePolicy::IsNavigationBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.origin, embedder_policy,
-                  &reporter));
+                  final_url, original_url, test_case.origin,
+                  *test_case.response_info, test_case.origin,
+                  RequestDestination::kScript, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(1u, reporter.reports().size());
       EXPECT_TRUE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kScript);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
@@ -404,15 +422,17 @@
         mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
     EXPECT_EQ(test_case.expectation_with_coep_require_corp,
               CrossOriginResourcePolicy::IsNavigationBlocked(
-                  destination, original_destination, test_case.origin,
-                  *test_case.response_info, test_case.origin, embedder_policy,
-                  &reporter));
+                  final_url, original_url, test_case.origin,
+                  *test_case.response_info, test_case.origin,
+                  RequestDestination::kEmpty, embedder_policy, &reporter));
     if (should_be_blocked_due_to_coep) {
       ASSERT_EQ(2u, reporter.reports().size());
       EXPECT_TRUE(reporter.reports()[0].report_only);
-      EXPECT_EQ(reporter.reports()[0].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[0].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[0].destination, RequestDestination::kEmpty);
       EXPECT_FALSE(reporter.reports()[1].report_only);
-      EXPECT_EQ(reporter.reports()[1].blocked_url, original_destination);
+      EXPECT_EQ(reporter.reports()[1].blocked_url, original_url);
+      EXPECT_EQ(reporter.reports()[1].destination, RequestDestination::kEmpty);
     } else {
       EXPECT_TRUE(reporter.reports().empty());
     }
diff --git a/services/network/public/mojom/cross_origin_embedder_policy.mojom b/services/network/public/mojom/cross_origin_embedder_policy.mojom
index d5edd09c..222cb835 100644
--- a/services/network/public/mojom/cross_origin_embedder_policy.mojom
+++ b/services/network/public/mojom/cross_origin_embedder_policy.mojom
@@ -5,6 +5,7 @@
 module network.mojom;
 
 import "url/mojom/url.mojom";
+import "services/network/public/mojom/fetch_api.mojom";
 
 // https://mikewest.github.io/corpp/#integration-html
 enum CrossOriginEmbedderPolicyValue {
@@ -16,7 +17,9 @@
 // in the network service. Implemented in the browser process.
 interface CrossOriginEmbedderPolicyReporter {
   // Queues a report of a CORP violation caused by COEP.
-  QueueCorpViolationReport(url.mojom.Url blocked_url, bool report_only);
+  QueueCorpViolationReport(url.mojom.Url blocked_url,
+                           network.mojom.RequestDestination destination,
+                           bool report_only);
 
   // Connects a new pipe to this instance.
   Clone(pending_receiver<CrossOriginEmbedderPolicyReporter> receiver);
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index d1de1a9..2527d28 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1083,7 +1083,8 @@
               url_request_->url(), url_request_->original_url(),
               url_request_->initiator(), *response, request_mode_,
               factory_params_->request_initiator_origin_lock,
-              cross_origin_embedder_policy, coep_reporter_)) {
+              request_destination_, cross_origin_embedder_policy,
+              coep_reporter_)) {
     CompleteBlockedResponse(net::ERR_BLOCKED_BY_RESPONSE, false,
                             blocked_reason);
     DeleteSelf();
@@ -1296,7 +1297,8 @@
               url_request_->url(), url_request_->original_url(),
               url_request_->initiator(), *response_, request_mode_,
               factory_params_->request_initiator_origin_lock,
-              cross_origin_embedder_policy, coep_reporter_)) {
+              request_destination_, cross_origin_embedder_policy,
+              coep_reporter_)) {
     CompleteBlockedResponse(net::ERR_BLOCKED_BY_RESPONSE, false,
                             blocked_reason);
     DeleteSelf();
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 441fd9f..e14b37f 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -294,29 +294,6 @@
             ]
         }
     ],
-    "AutofillCompany": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "RejectBirthyearAndSocialTitleAsCompany_20200210",
-                    "enable_features": [
-                        "AutofillEnableCompanyName",
-                        "AutofillRejectCompanyBirthyear",
-                        "AutofillRejectCompanySocialTitle"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillCreditCardAuthentication": [
         {
             "platforms": [
@@ -493,6 +470,27 @@
             ]
         }
     ],
+    "AutofillSkipFillingFieldsWithChangedValues": [
+        {
+            "platforms": [
+                "android",
+                "android_weblayer",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "enabled",
+                    "enable_features": [
+                        "AutofillSkipFillingFieldsWithChangedValues"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillSmallFormSupport": [
         {
             "platforms": [
@@ -2241,6 +2239,21 @@
             ]
         }
     ],
+    "EnableAutofillPasswordReauthIOS": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "EnableAutofillPasswordReauthIOS"
+                    ]
+                }
+            ]
+        }
+    ],
     "EnableContextMenuPerformanceHints": [
         {
             "platforms": [
@@ -4810,27 +4823,6 @@
             ]
         }
     ],
-    "OptOutWebRTCFromAllThrottling": [
-        {
-            "platforms": [
-                "android",
-                "android_weblayer",
-                "android_webview",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "OptOutWebRTCFromAllThrottling"
-                    ]
-                }
-            ]
-        }
-    ],
     "OutOfBlinkCors": [
         {
             "platforms": [
@@ -6089,6 +6081,21 @@
             ]
         }
     ],
+    "SafeBrowsingRealTimeUrlLookupEnabledIOS": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "SafeBrowsingRealTimeUrlLookupEnabled"
+                    ]
+                }
+            ]
+        }
+    ],
     "SafeBrowsingRealTimeUrlLookupEnabledWithToken": [
         {
             "platforms": [
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index 236fb28..0c99afee 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: dc969f34a79d019497abb61c2a3f79b5b4be2ea9
+Revision: c03c18e7fef8d06eb6c445f5607af533e69cadfe
 Security Critical: yes
 
 Description:
diff --git a/third_party/abseil-cpp/WORKSPACE b/third_party/abseil-cpp/WORKSPACE
index 9633819..0b53356 100644
--- a/third_party/abseil-cpp/WORKSPACE
+++ b/third_party/abseil-cpp/WORKSPACE
@@ -39,7 +39,6 @@
     sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d",
     strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
         "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
     ],
 )
diff --git a/third_party/abseil-cpp/absl/algorithm/BUILD.bazel b/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
index 229cd71..a3002b7 100644
--- a/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "algorithm",
diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel
index 2c4887b..9d96abe 100644
--- a/third_party/abseil-cpp/absl/base/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "atomic_hook",
diff --git a/third_party/abseil-cpp/absl/base/dynamic_annotations.h b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
index 1911272..94488ac1 100644
--- a/third_party/abseil-cpp/absl/base/dynamic_annotations.h
+++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
@@ -80,12 +80,9 @@
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
 #if !defined(SWIG)
 #define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
-#else
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 #else
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 
 // Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
@@ -268,19 +265,19 @@
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END attributes.
 
-#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
   __attribute((exclusive_lock_function("*")))
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
   __attribute((unlock_function("*")))
 
-#else  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
+#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty
 
-#endif  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END annotations.
diff --git a/third_party/abseil-cpp/absl/container/BUILD.bazel b/third_party/abseil-cpp/absl/container/BUILD.bazel
index cca5d441..8e72ad03 100644
--- a/third_party/abseil-cpp/absl/container/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/container/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "compressed_tuple",
diff --git a/third_party/abseil-cpp/absl/container/internal/container_memory.h b/third_party/abseil-cpp/absl/container/internal/container_memory.h
index d02c576d..e67529e 100644
--- a/third_party/abseil-cpp/absl/container/internal/container_memory.h
+++ b/third_party/abseil-cpp/absl/container/internal/container_memory.h
@@ -57,8 +57,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
   assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
          "allocator does not respect alignment");
   return p;
@@ -73,8 +76,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  AT::deallocate(mem_alloc, static_cast<M*>(p),
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  AT::deallocate(my_mem_alloc, static_cast<M*>(p),
                  (n + sizeof(M) - 1) / sizeof(M));
 }
 
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
index 308119c..e140ee00 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
@@ -186,7 +186,7 @@
 
 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
-#endif  // ABSL_PER_THREAD_TLS
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
index 48a1a8c..130da13 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -122,6 +122,16 @@
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <typename AllocType>
+void SwapAlloc(AllocType& lhs, AllocType& rhs,
+               std::true_type /* propagate_on_container_swap */) {
+  using std::swap;
+  swap(lhs, rhs);
+}
+template <typename AllocType>
+void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
+               std::false_type /* propagate_on_container_swap */) {}
+
 template <size_t Width>
 class probe_seq {
  public:
@@ -169,10 +179,14 @@
 
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
-constexpr bool IsNoThrowSwappable() {
+constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
   using std::swap;
   return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
 }
+template <class T>
+constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
+  return false;
+}
 
 template <typename T>
 int TrailingZeros(T x) {
@@ -1231,8 +1245,8 @@
 
   void swap(raw_hash_set& that) noexcept(
       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
-      (!AllocTraits::propagate_on_container_swap::value ||
-       IsNoThrowSwappable<allocator_type>())) {
+      IsNoThrowSwappable<allocator_type>(
+          typename AllocTraits::propagate_on_container_swap{})) {
     using std::swap;
     swap(ctrl_, that.ctrl_);
     swap(slots_, that.slots_);
@@ -1242,12 +1256,8 @@
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
     swap(infoz_, that.infoz_);
-    if (AllocTraits::propagate_on_container_swap::value) {
-      swap(alloc_ref(), that.alloc_ref());
-    } else {
-      // If the allocators do not compare equal it is officially undefined
-      // behavior. We choose to do nothing.
-    }
+    SwapAlloc(alloc_ref(), that.alloc_ref(),
+              typename AllocTraits::propagate_on_container_swap{});
   }
 
   void rehash(size_t n) {
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
index 7ac4b9f..1a03608 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -424,6 +424,77 @@
   EXPECT_EQ(0, it->num_copies());
 }
 
+// This allocator is similar to std::pmr::polymorphic_allocator.
+// Note the disabled assignment.
+template <class T>
+class PAlloc {
+  template <class>
+  friend class PAlloc;
+
+ public:
+  // types
+  using value_type = T;
+
+  // traits
+  using propagate_on_container_swap = std::false_type;
+
+  PAlloc() noexcept = default;
+  explicit PAlloc(size_t id) noexcept : id_(id) {}
+  PAlloc(const PAlloc&) noexcept = default;
+  PAlloc& operator=(const PAlloc&) noexcept = delete;
+
+  template <class U>
+  PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {}  // NOLINT
+
+  template <class U>
+  struct rebind {
+    using other = PAlloc<U>;
+  };
+
+  constexpr PAlloc select_on_container_copy_construction() const { return {}; }
+
+  // public member functions
+  T* allocate(size_t) { return new T; }
+  void deallocate(T* p, size_t) { delete p; }
+
+  friend bool operator==(const PAlloc& a, const PAlloc& b) {
+    return a.id_ == b.id_;
+  }
+  friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }
+
+ private:
+  size_t id_ = std::numeric_limits<size_t>::max();
+};
+
+TEST(NoPropagateOn, Swap) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  swap(t1, t2);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
+TEST(NoPropagateOn, CopyConstruct) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(t1);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA());
+}
+
+TEST(NoPropagateOn, Assignment) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  t1 = t2;
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/debugging/BUILD.bazel b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
index 9098ca4..86faac9 100644
--- a/third_party/abseil-cpp/absl/debugging/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
@@ -26,7 +26,7 @@
     default_visibility = ["//visibility:public"],
 )
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "stacktrace",
diff --git a/third_party/abseil-cpp/absl/debugging/symbolize.cc b/third_party/abseil-cpp/absl/debugging/symbolize.cc
index eec7a6e..5e4a25d 100644
--- a/third_party/abseil-cpp/absl/debugging/symbolize.cc
+++ b/third_party/abseil-cpp/absl/debugging/symbolize.cc
@@ -14,9 +14,18 @@
 
 #include "absl/debugging/symbolize.h"
 
+#ifdef _WIN32
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
+    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// UWP doesn't have access to win32 APIs.
+#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
+#endif
+#endif
+
 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
 #include "absl/debugging/symbolize_elf.inc"
-#elif defined(_WIN32)
+#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
 // The Windows Symbolizer only works if PDB files containing the debug info
 // are available to the program at runtime.
 #include "absl/debugging/symbolize_win32.inc"
diff --git a/third_party/abseil-cpp/absl/flags/BUILD.bazel b/third_party/abseil-cpp/absl/flags/BUILD.bazel
index 92bd4f15..62fb9a8bd 100644
--- a/third_party/abseil-cpp/absl/flags/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/flags/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "path_util",
@@ -179,6 +179,7 @@
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/container:flat_hash_map",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -464,6 +465,7 @@
         ":flag",
         ":marshalling",
         ":reflection",
+        ":usage_internal",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
diff --git a/third_party/abseil-cpp/absl/flags/BUILD.gn b/third_party/abseil-cpp/absl/flags/BUILD.gn
index 99c61ca..169935b 100644
--- a/third_party/abseil-cpp/absl/flags/BUILD.gn
+++ b/third_party/abseil-cpp/absl/flags/BUILD.gn
@@ -101,6 +101,7 @@
     ":private_handle_accessor",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/container:flat_hash_map",
     "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/synchronization",
   ]
diff --git a/third_party/abseil-cpp/absl/flags/CMakeLists.txt b/third_party/abseil-cpp/absl/flags/CMakeLists.txt
index 343774d..28bd5a8 100644
--- a/third_party/abseil-cpp/absl/flags/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/flags/CMakeLists.txt
@@ -165,6 +165,7 @@
     absl::flags_config
     absl::strings
     absl::synchronization
+    absl::flat_hash_map
 )
 
 # Internal-only target, do not depend on directly.
@@ -407,9 +408,10 @@
     absl::flags_commandlineflag_internal
     absl::flags
     absl::flags_reflection
+    absl::flags_usage
     absl::memory
     absl::strings
-    gtest_main
+    gmock_main
 )
 
 absl_cc_test(
diff --git a/third_party/abseil-cpp/absl/flags/reflection.cc b/third_party/abseil-cpp/absl/flags/reflection.cc
index e4145b3..d7060221 100644
--- a/third_party/abseil-cpp/absl/flags/reflection.cc
+++ b/third_party/abseil-cpp/absl/flags/reflection.cc
@@ -303,5 +303,15 @@
   return registry.FindFlagLocked(name);
 }
 
+// --------------------------------------------------------------------
+
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    res.insert({flag.Name(), &flag});
+  });
+  return res;
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/third_party/abseil-cpp/absl/flags/reflection.h b/third_party/abseil-cpp/absl/flags/reflection.h
index 045f978..4ce0ab6 100644
--- a/third_party/abseil-cpp/absl/flags/reflection.h
+++ b/third_party/abseil-cpp/absl/flags/reflection.h
@@ -26,6 +26,7 @@
 #include <string>
 
 #include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 
@@ -40,7 +41,11 @@
 // Returns the reflection handle of an Abseil flag of the specified name, or
 // `nullptr` if not found. This function will emit a warning if the name of a
 // 'retired' flag is specified.
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
 
 //------------------------------------------------------------------------------
 // FlagSaver
diff --git a/third_party/abseil-cpp/absl/flags/reflection_test.cc b/third_party/abseil-cpp/absl/flags/reflection_test.cc
index 2da0a0e..1a1dcb4a 100644
--- a/third_party/abseil-cpp/absl/flags/reflection_test.cc
+++ b/third_party/abseil-cpp/absl/flags/reflection_test.cc
@@ -18,7 +18,9 @@
 #include <memory>
 #include <string>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/marshalling.h"
@@ -30,6 +32,8 @@
 ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
 ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
 
+ABSL_DECLARE_FLAG(bool, help);
+
 namespace {
 
 namespace flags = absl::flags_internal;
@@ -61,6 +65,33 @@
 
 // --------------------------------------------------------------------
 
+TEST_F(ReflectionTest, TestGetAllFlags) {
+  (void)absl::GetFlag(FLAGS_help);  // Force linking of usage flags.
+
+  auto all_flags = absl::GetAllFlags();
+  EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("bool_retired_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("help"), all_flags.end());
+  EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+  std::vector<absl::string_view> flag_names_first_attempt;
+  auto all_flags_1 = absl::GetAllFlags();
+  for (auto f : all_flags_1) {
+    flag_names_first_attempt.push_back(f.first);
+  }
+
+  std::vector<absl::string_view> flag_names_second_attempt;
+  auto all_flags_2 = absl::GetAllFlags();
+  for (auto f : all_flags_2) {
+    flag_names_second_attempt.push_back(f.first);
+  }
+
+  EXPECT_THAT(flag_names_first_attempt,
+              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
 struct CustomUDT {
   CustomUDT() : a(1), b(1) {}
   CustomUDT(int a_, int b_) : a(a_), b(b_) {}
diff --git a/third_party/abseil-cpp/absl/functional/BUILD.bazel b/third_party/abseil-cpp/absl/functional/BUILD.bazel
index 432546c..ebd9b99b 100644
--- a/third_party/abseil-cpp/absl/functional/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/functional/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "bind_front",
diff --git a/third_party/abseil-cpp/absl/hash/BUILD.bazel b/third_party/abseil-cpp/absl/hash/BUILD.bazel
index 6c77f1a..5b1e2d0 100644
--- a/third_party/abseil-cpp/absl/hash/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/hash/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "hash",
diff --git a/third_party/abseil-cpp/absl/hash/hash.h b/third_party/abseil-cpp/absl/hash/hash.h
index d7386f6c..5de132c 100644
--- a/third_party/abseil-cpp/absl/hash/hash.h
+++ b/third_party/abseil-cpp/absl/hash/hash.h
@@ -88,7 +88,6 @@
 //  * T is an arithmetic or pointer type
 //  * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
 //    hash state `H`.
-//  - T defines a specialization of `HASH_NAMESPACE::hash<T>`
 //  - T defines a specialization of `std::hash<T>`
 //
 // `absl::Hash` intrinsically supports the following types:
@@ -128,8 +127,6 @@
 //   * Natively supported types out of the box (see above)
 //   * Types for which an `AbslHashValue()` overload is provided (such as
 //     user-defined types). See "Adding Type Support to `absl::Hash`" below.
-//   * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka
-//     `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC)
 //   * Types which define a `std::hash<T>` specialization
 //
 // The fallback to legacy hash functions exists mainly for backwards
diff --git a/third_party/abseil-cpp/absl/memory/BUILD.bazel b/third_party/abseil-cpp/absl/memory/BUILD.bazel
index 2ba9d7cb..d2824a05 100644
--- a/third_party/abseil-cpp/absl/memory/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/memory/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "memory",
diff --git a/third_party/abseil-cpp/absl/memory/memory.h b/third_party/abseil-cpp/absl/memory/memory.h
index 513f710..2b5ff623 100644
--- a/third_party/abseil-cpp/absl/memory/memory.h
+++ b/third_party/abseil-cpp/absl/memory/memory.h
@@ -420,6 +420,9 @@
 //
 // A C++11 compatible implementation of C++17's std::allocator_traits.
 //
+#if __cplusplus >= 201703L
+using std::allocator_traits;
+#else  // __cplusplus >= 201703L
 template <typename Alloc>
 struct allocator_traits {
   using allocator_type = Alloc;
@@ -609,6 +612,7 @@
     return a;
   }
 };
+#endif  // __cplusplus >= 201703L
 
 namespace memory_internal {
 
diff --git a/third_party/abseil-cpp/absl/memory/memory_test.cc b/third_party/abseil-cpp/absl/memory/memory_test.cc
index 0d2e13bd..1990c7b 100644
--- a/third_party/abseil-cpp/absl/memory/memory_test.cc
+++ b/third_party/abseil-cpp/absl/memory/memory_test.cc
@@ -555,7 +555,7 @@
   EXPECT_CALL(mock, deallocate(&x, 7));
 
   EXPECT_EQ(&x, Traits::allocate(mock, 7));
-  Traits::allocate(mock, 7, static_cast<const void*>(&hint));
+  static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   Traits::deallocate(mock, &x, 7);
 
diff --git a/third_party/abseil-cpp/absl/meta/BUILD.bazel b/third_party/abseil-cpp/absl/meta/BUILD.bazel
index c06d2d9..5585fcca 100644
--- a/third_party/abseil-cpp/absl/meta/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/meta/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "type_traits",
diff --git a/third_party/abseil-cpp/absl/numeric/BUILD.bazel b/third_party/abseil-cpp/absl/numeric/BUILD.bazel
index da3af4d..f808f5d 100644
--- a/third_party/abseil-cpp/absl/numeric/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/numeric/BUILD.bazel
@@ -22,7 +22,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "int128",
diff --git a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
index 000cc45..8485e28 100644
--- a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
@@ -30,7 +30,7 @@
     "//absl/random:__pkg__",
 ])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "traits",
diff --git a/third_party/abseil-cpp/absl/status/BUILD.bazel b/third_party/abseil-cpp/absl/status/BUILD.bazel
index c4c5e49..81fa46c 100644
--- a/third_party/abseil-cpp/absl/status/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/status/BUILD.bazel
@@ -26,7 +26,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "status",
diff --git a/third_party/abseil-cpp/absl/strings/string_view.h b/third_party/abseil-cpp/absl/strings/string_view.h
index 8a9db8c3..5260b5b7 100644
--- a/third_party/abseil-cpp/absl/strings/string_view.h
+++ b/third_party/abseil-cpp/absl/strings/string_view.h
@@ -111,6 +111,11 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
+// For another example, a Cord is a non-contiguous, potentially very
+// long string-like object.  The Cord class has an interface that iteratively
+// provides string_view objects that point to the successive pieces of a Cord
+// object.
+//
 // When constructed from a source which is NUL-terminated, the `string_view`
 // itself will not include the NUL-terminator unless a specific size (including
 // the NUL) is passed to the constructor. As a result, common idioms that work
@@ -382,6 +387,7 @@
   // Returns a "substring" of the `string_view` (at offset `pos` and length
   // `n`) as another string_view. This function throws `std::out_of_bounds` if
   // `pos > size`.
+  // Use absl::ClippedSubstr if you need a truncating substr operation.
   constexpr string_view substr(size_type pos, size_type n = npos) const {
     return ABSL_PREDICT_FALSE(pos > length_)
                ? (base_internal::ThrowStdOutOfRange(
diff --git a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
index 1a5c02a..4d4d680 100644
--- a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 # Internal data structure for efficiently detecting mutex dependency cycles
 cc_library(
diff --git a/third_party/abseil-cpp/absl/time/BUILD.bazel b/third_party/abseil-cpp/absl/time/BUILD.bazel
index 1d69f59..991241a 100644
--- a/third_party/abseil-cpp/absl/time/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/time/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "time",
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel b/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
index 7a53c81..7379dec9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
@@ -16,7 +16,7 @@
 
 package(features = ["-parse_headers"])
 
-licenses(["notice"])  # Apache License
+licenses(["notice"])
 
 filegroup(
     name = "zoneinfo",
diff --git a/third_party/abseil-cpp/absl/types/BUILD.bazel b/third_party/abseil-cpp/absl/types/BUILD.bazel
index 102affa..83be9360 100644
--- a/third_party/abseil-cpp/absl/types/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/types/BUILD.bazel
@@ -23,7 +23,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "any",
diff --git a/third_party/abseil-cpp/absl/utility/BUILD.bazel b/third_party/abseil-cpp/absl/utility/BUILD.bazel
index 6881f93..02b2c40 100644
--- a/third_party/abseil-cpp/absl/utility/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/utility/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "utility",
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 80fb5c6..63a16660 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -744,5 +744,15 @@
 const base::Feature kTransferableStreams{"TransferableStreams",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
+// The "BackForwardCacheABExperimentControl" feature indicates the state of the
+// same-site BackForwardCache experiment. This information is used when sending
+// the "Sec-bfcache-experiment" HTTP Header on resource requests. The header
+// value is determined by the value of the "experiment_group_for_http_header"
+// feature parameter.
+const base::Feature kBackForwardCacheABExperimentControl{
+    "BackForwardCacheABExperimentControl", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kBackForwardCacheABExperimentGroup[] =
+    "experiment_group_for_http_header";
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
index d0bf605..ffa6066 100644
--- a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
+++ b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -109,6 +109,8 @@
       return "KeyboardLock";
     case WebSchedulerTrackedFeature::kSmsService:
       return "SMSService";
+    case WebSchedulerTrackedFeature::kOutstandingNetworkRequestDirectSocket:
+      return "outstanding network request (direct socket)";
   }
 }
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 8438c81..c5aea51 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -305,6 +305,11 @@
 
 BLINK_COMMON_EXPORT extern const base::Feature kTransferableStreams;
 
+BLINK_COMMON_EXPORT extern const base::Feature
+    kBackForwardCacheABExperimentControl;
+BLINK_COMMON_EXPORT
+extern const char kBackForwardCacheABExperimentGroup[];
+
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
index 090c0f06..d3ab992 100644
--- a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
+++ b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -96,9 +96,10 @@
   kSpeechSynthesis = 50,
   kKeyboardLock = 51,
   kSmsService = 52,
+  kOutstandingNetworkRequestDirectSocket = 53,
 
   // NB: This enum is used in a bitmask, so kMaxValue must be less than 64.
-  kMaxValue = kSmsService
+  kMaxValue = kOutstandingNetworkRequestDirectSocket
 };
 
 static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64,
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 09815a6..112f9d31 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -45,6 +45,7 @@
     "devtools/devtools_agent.mojom",
     "devtools/devtools_frontend.mojom",
     "devtools/inspector_issue.mojom",
+    "direct_sockets/direct_sockets.mojom",
     "disk_allocator.mojom",
     "favicon/favicon_url.mojom",
     "feature_observer/feature_observer.mojom",
diff --git a/third_party/blink/public/mojom/direct_sockets/OWNERS b/third_party/blink/public/mojom/direct_sockets/OWNERS
new file mode 100644
index 0000000..af9a801
--- /dev/null
+++ b/third_party/blink/public/mojom/direct_sockets/OWNERS
@@ -0,0 +1,8 @@
+ericwilligers@chromium.org
+glenrob@chromium.org
+mgiuca@chromium.org
+
+# Changes to Mojo interfaces require a security review to avoid
+# introducing new sandbox escapes.
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom b/third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom
new file mode 100644
index 0000000..17e2e45
--- /dev/null
+++ b/third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom
@@ -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.
+
+module blink.mojom;
+
+// Explainer for the Direct Sockets API:
+// https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md
+
+struct DirectSocketOptions {
+  string? local_hostname;
+  uint16 local_port = 0;
+
+  string? remote_hostname;
+  uint16 remote_port = 0;
+
+  int32 send_buffer_size = 0;
+  int32 receive_buffer_size = 0;
+
+  // These are only relevant for TCP:
+  bool keep_alive = false;
+  bool no_delay = false;
+};
+
+// This wraps network.mojom.NetworkContext and handles extra work such as
+// permission checking, chooser showing, etc.
+// The browser process implements the interface, and the renderer process
+// sends messages to it.
+// The return values are net::Error codes. 0 indicates success.
+interface DirectSocketsService {
+  // TODO(crbug.com/905818): Return TCP socket details
+  OpenTcpSocket(
+      DirectSocketOptions options)
+      => (int32 result);
+
+  // TODO(crbug.com/1119620): Return UDP socket details
+  OpenUdpSocket(
+      DirectSocketOptions options)
+      => (int32 result);
+};
diff --git a/third_party/blink/public/mojom/payments/payment_request.mojom b/third_party/blink/public/mojom/payments/payment_request.mojom
index 7d0e3a8..7695f1da 100644
--- a/third_party/blink/public/mojom/payments/payment_request.mojom
+++ b/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -125,9 +125,10 @@
 // Parameters for the "secure-payment-confirmation" payment method identifier.
 // https://github.com/rsolomakhin/secure-payment-confirmation
 struct SecurePaymentConfirmationRequest {
-  // An identifier of a set of credentials that map to a single instrument
-  // name and icon.
-  string instrument_id;
+  // A list of WebAuthn credential identifiers. These values will be looked up
+  // in "secure_payment_confirmation_instrument" table. Upon user gesture, one
+  // of these credentials will be queried from WebAuthn.
+  array<array<uint8>> credential_ids;
 
   // An indefinite-length blob passed from the relying party server, to be sent
   // to an authenticator for signing together with the price and merchant
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index c4137a2..f7487b8 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2786,6 +2786,7 @@
   kWebCodecsVideoEncoder = 3458,
   kWebCodecsVideoTrackReader= 3459,
   kWebCodecsImageDecoder = 3460,
+  kBackForwardCacheExperimentHTTPHeader = 3461,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 0edffa3..aad09090 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -154,6 +154,7 @@
   BLINK_PLATFORM_EXPORT static void EnablePresentationAPI(bool);
   BLINK_PLATFORM_EXPORT static void EnablePushMessaging(bool);
   BLINK_PLATFORM_EXPORT static void EnablePushSubscriptionChangeEvent(bool);
+  BLINK_PLATFORM_EXPORT static void EnableDirectSockets(bool);
   BLINK_PLATFORM_EXPORT static void EnableRemotePlaybackAPI(bool);
   BLINK_PLATFORM_EXPORT static void
   EnableRestrictAutomaticLazyFrameLoadingToDataSaver(bool);
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 6e84308..0672667 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -582,6 +582,8 @@
           "//third_party/blink/renderer/modules/quota/storage_usage_details.idl",
           "//third_party/blink/renderer/modules/quota/window_quota.idl",
           "//third_party/blink/renderer/modules/quota/worker_navigator_storage_quota.idl",
+          "//third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl",
+          "//third_party/blink/renderer/modules/direct_sockets/socket_options.idl",
           "//third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl",
           "//third_party/blink/renderer/modules/remoteplayback/remote_playback.idl",
           "//third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl",
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl
index e85ab80..2d39cfdb 100644
--- a/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.cc.tmpl
@@ -6,6 +6,7 @@
 #include "third_party/blink/renderer/core/css/{{file_basename}}.h"
 
 #include <string.h>
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
 #include "third_party/blink/renderer/core/css/hash_tools.h"
 #include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl
index 1da8f0f..557ee17b 100644
--- a/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/templates/css_property_names.h.tmpl
@@ -5,7 +5,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAMES_H_
 
 #include <stddef.h>
-#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc
index 764d8a30..f2b8c41 100644
--- a/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -972,8 +972,11 @@
       if (CSSPropertyEquality::PropertiesEqual(property, state.style,
                                                *running_transition->to)) {
         if (!state.transition_data) {
-          UseCounter::Count(state.animating_element->GetDocument(),
-                            WebFeature::kCSSTransitionCancelledByRemovingStyle);
+          if (!running_transition->animation->FinishedInternal()) {
+            UseCounter::Count(
+                state.animating_element->GetDocument(),
+                WebFeature::kCSSTransitionCancelledByRemovingStyle);
+          }
           // TODO(crbug.com/934700): Add a return to this branch to correctly
           // continue transitions under default settings (all 0s) in the absence
           // of a change in base computed style.
diff --git a/third_party/blink/renderer/core/dom/child_list_mutation_scope.h b/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
index 0f6bd80..213a1d6 100644
--- a/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
+++ b/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
@@ -31,7 +31,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_LIST_MUTATION_SCOPE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_LIST_MUTATION_SCOPE_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/mutation_observer.h"
 #include "third_party/blink/renderer/core/dom/node.h"
@@ -99,6 +98,8 @@
       accumulator_->EnterMutationScope();
     }
   }
+  ChildListMutationScope(const ChildListMutationScope&) = delete;
+  ChildListMutationScope& operator=(const ChildListMutationScope&) = delete;
 
   ~ChildListMutationScope() {
     if (accumulator_) {
@@ -120,7 +121,6 @@
 
  private:
   ChildListMutationAccumulator* accumulator_ = nullptr;
-  DISALLOW_COPY_AND_ASSIGN(ChildListMutationScope);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document_lifecycle.h b/third_party/blink/renderer/core/dom/document_lifecycle.h
index d878d9eb..0d58f5c 100644
--- a/third_party/blink/renderer/core/dom/document_lifecycle.h
+++ b/third_party/blink/renderer/core/dom/document_lifecycle.h
@@ -32,7 +32,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_LIFECYCLE_H_
 
 #include "base/auto_reset.h"
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -99,12 +98,13 @@
 
    public:
     Scope(DocumentLifecycle&, LifecycleState final_state);
+    Scope(const Scope&) = delete;
+    Scope& operator=(const Scope&) = delete;
     ~Scope();
 
    private:
     DocumentLifecycle& lifecycle_;
     LifecycleState final_state_;
-    DISALLOW_COPY_AND_ASSIGN(Scope);
   };
 
   class DeprecatedTransition {
@@ -112,6 +112,8 @@
 
    public:
     DeprecatedTransition(LifecycleState from, LifecycleState to);
+    DeprecatedTransition(const DeprecatedTransition&) = delete;
+    DeprecatedTransition& operator=(const DeprecatedTransition&) = delete;
     ~DeprecatedTransition();
 
     LifecycleState From() const { return from_; }
@@ -121,7 +123,6 @@
     DeprecatedTransition* previous_;
     LifecycleState from_;
     LifecycleState to_;
-    DISALLOW_COPY_AND_ASSIGN(DeprecatedTransition);
   };
 
   // Within this scope, state transitions are not allowed.
@@ -134,6 +135,8 @@
         : document_lifecycle_(document_lifecycle) {
       document_lifecycle_.IncrementNoTransitionCount();
     }
+    DisallowTransitionScope(const DisallowTransitionScope&) = delete;
+    DisallowTransitionScope& operator=(const DisallowTransitionScope&) = delete;
 
     ~DisallowTransitionScope() {
       document_lifecycle_.DecrementNoTransitionCount();
@@ -141,7 +144,6 @@
 
    private:
     DocumentLifecycle& document_lifecycle_;
-    DISALLOW_COPY_AND_ASSIGN(DisallowTransitionScope);
   };
 
   class DetachScope {
@@ -152,12 +154,13 @@
         : document_lifecycle_(document_lifecycle) {
       document_lifecycle_.IncrementDetachCount();
     }
+    DetachScope(const DetachScope&) = delete;
+    DetachScope& operator=(const DetachScope&) = delete;
 
     ~DetachScope() { document_lifecycle_.DecrementDetachCount(); }
 
    private:
     DocumentLifecycle& document_lifecycle_;
-    DISALLOW_COPY_AND_ASSIGN(DetachScope);
   };
 
   // Throttling is disabled by default. Instantiating this class allows
@@ -169,8 +172,9 @@
 
    public:
     AllowThrottlingScope(DocumentLifecycle&);
+    AllowThrottlingScope(const AllowThrottlingScope&) = delete;
+    AllowThrottlingScope& operator=(const AllowThrottlingScope&) = delete;
     ~AllowThrottlingScope();
-    DISALLOW_COPY_AND_ASSIGN(AllowThrottlingScope);
   };
 
   class CORE_EXPORT DisallowThrottlingScope {
@@ -178,11 +182,12 @@
 
    public:
     DisallowThrottlingScope(DocumentLifecycle&);
+    DisallowThrottlingScope(const DisallowThrottlingScope&) = delete;
+    DisallowThrottlingScope& operator=(const DisallowThrottlingScope&) = delete;
     ~DisallowThrottlingScope();
 
    private:
     int saved_count_;
-    DISALLOW_COPY_AND_ASSIGN(DisallowThrottlingScope);
   };
 
   // If we hit a devtool break point in the middle of document lifecycle, for
@@ -217,6 +222,8 @@
   };
 
   DocumentLifecycle();
+  DocumentLifecycle(const DocumentLifecycle&) = delete;
+  DocumentLifecycle& operator=(const DocumentLifecycle&) = delete;
 
   bool IsActive() const { return state_ > kInactive && state_ < kStopping; }
   LifecycleState GetState() const { return state_; }
@@ -265,7 +272,6 @@
   int disallow_transition_count_;
   bool life_cycle_postponed_;
   bool check_no_transition_;
-  DISALLOW_COPY_AND_ASSIGN(DocumentLifecycle);
 };
 
 inline bool DocumentLifecycle::StateAllowsTreeMutations() const {
diff --git a/third_party/blink/renderer/core/dom/document_parser_timing.h b/third_party/blink/renderer/core/dom/document_parser_timing.h
index 9791c0c9..91a5251 100644
--- a/third_party/blink/renderer/core/dom/document_parser_timing.h
+++ b/third_party/blink/renderer/core/dom/document_parser_timing.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_PARSER_TIMING_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_PARSER_TIMING_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
@@ -21,6 +20,8 @@
   static const char kSupplementName[];
 
   explicit DocumentParserTiming(Document&);
+  DocumentParserTiming(const DocumentParserTiming&) = delete;
+  DocumentParserTiming& operator=(const DocumentParserTiming&) = delete;
   virtual ~DocumentParserTiming() = default;
 
   static DocumentParserTiming& From(Document&);
@@ -108,7 +109,6 @@
   base::TimeDelta
       parser_blocked_on_script_execution_from_document_write_duration_;
   bool parser_detached_ = false;
-  DISALLOW_COPY_AND_ASSIGN(DocumentParserTiming);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index 8366d62..5a8b9ce0 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -151,6 +151,10 @@
   };
 
   explicit TestSynchronousMutationObserver(Document&);
+  TestSynchronousMutationObserver(const TestSynchronousMutationObserver&) =
+      delete;
+  TestSynchronousMutationObserver& operator=(
+      const TestSynchronousMutationObserver&) = delete;
   virtual ~TestSynchronousMutationObserver() = default;
 
   int CountContextDestroyedCalled() const {
@@ -211,8 +215,6 @@
   HeapVector<Member<Node>> removed_nodes_;
   HeapVector<Member<const Text>> split_text_nodes_;
   HeapVector<Member<UpdateCharacterDataRecord>> updated_character_data_records_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSynchronousMutationObserver);
 };
 
 TestSynchronousMutationObserver::TestSynchronousMutationObserver(
diff --git a/third_party/blink/renderer/core/dom/dom_string_map.h b/third_party/blink/renderer/core/dom/dom_string_map.h
index 5ae98a1..1a95d1e 100644
--- a/third_party/blink/renderer/core/dom/dom_string_map.h
+++ b/third_party/blink/renderer/core/dom/dom_string_map.h
@@ -26,7 +26,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_STRING_MAP_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_STRING_MAP_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -54,6 +53,8 @@
     SetItem(name, value, exception_state);
     return NamedPropertySetterResult::kIntercepted;
   }
+  DOMStringMap(const DOMStringMap&) = delete;
+  DOMStringMap& operator=(const DOMStringMap&) = delete;
   NamedPropertyDeleterResult AnonymousNamedDeleter(const AtomicString& name) {
     return DeleteItem(name) ? NamedPropertyDeleterResult::kDeleted
                             : NamedPropertyDeleterResult::kDidNotIntercept;
@@ -65,7 +66,6 @@
 
  protected:
   DOMStringMap() = default;
-  DISALLOW_COPY_AND_ASSIGN(DOMStringMap);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/dom_token_list.h b/third_party/blink/renderer/core/dom/dom_token_list.h
index eb73388..9b8e18a 100644
--- a/third_party/blink/renderer/core/dom/dom_token_list.h
+++ b/third_party/blink/renderer/core/dom/dom_token_list.h
@@ -25,7 +25,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_TOKEN_LIST_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_TOKEN_LIST_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/qualified_name.h"
 #include "third_party/blink/renderer/core/dom/space_split_string.h"
@@ -45,6 +44,8 @@
  public:
   DOMTokenList(Element& element, const QualifiedName& attr)
       : element_(element), attribute_name_(attr) {}
+  DOMTokenList(const DOMTokenList&) = delete;
+  DOMTokenList& operator=(const DOMTokenList&) = delete;
   ~DOMTokenList() override = default;
   void Trace(Visitor*) const override;
 
@@ -91,7 +92,6 @@
   // |attribute_name_| is |g_null_name| in that case.
   const QualifiedName attribute_name_;
   bool is_in_update_step_ = false;
-  DISALLOW_COPY_AND_ASSIGN(DOMTokenList);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index dcbca6fb..1a56fd7 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1351,11 +1351,11 @@
   return 0;
 }
 
-PaintLayerScrollableArea* Element::GetScrollableArea() const {
+LayoutBox* Element::GetLayoutBoxForScrolling() const {
   LayoutBox* box = GetLayoutBox();
   if (!box || !box->HasNonVisibleOverflow())
     return nullptr;
-  return box->GetScrollableArea();
+  return box;
 }
 
 double Element::scrollLeft() {
@@ -1371,7 +1371,10 @@
     return 0;
   }
 
-  if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return 0;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     DCHECK(GetLayoutBox());
 
     if (HasLeftwardDirection(*this)) {
@@ -1409,7 +1412,10 @@
     return 0;
   }
 
-  if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return 0;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     DCHECK(GetLayoutBox());
 
     if (HasUpwardDirection(*this)) {
@@ -1449,10 +1455,13 @@
       options->setLeft(new_left);
       window->scrollTo(options);
     }
-  } else if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
-    LayoutBox* box = GetLayoutBox();
-    DCHECK(box);
+    return;
+  }
 
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     if (HasLeftwardDirection(*this)) {
       UseCounter::Count(
           GetDocument(),
@@ -1516,10 +1525,13 @@
       options->setTop(new_top);
       window->scrollTo(options);
     }
-  } else if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
-    LayoutBox* box = GetLayoutBox();
-    DCHECK(box);
+    return;
+  }
 
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     if (HasUpwardDirection(*this)) {
       UseCounter::Count(
           GetDocument(),
@@ -1675,8 +1687,10 @@
       mojom::blink::ScrollBehavior::kAuto;
   ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(),
                                            scroll_behavior);
-  if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
-    LayoutBox* box = GetLayoutBox();
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     DCHECK(box);
     gfx::ScrollOffset current_position(scrollable_area->ScrollPosition().X(),
                                        scrollable_area->ScrollPosition().Y());
@@ -1701,9 +1715,10 @@
   ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(),
                                            scroll_behavior);
 
-  if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
-    LayoutBox* box = GetLayoutBox();
-    DCHECK(box);
+  LayoutBox* box = GetLayoutBoxForScrolling();
+  if (!box)
+    return;
+  if (PaintLayerScrollableArea* scrollable_area = box->GetScrollableArea()) {
     if (scroll_to_options->hasLeft() && HasLeftwardDirection(*this)) {
       UseCounter::Count(
           GetDocument(),
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 7d6143be..e793b2a 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -73,7 +73,6 @@
 class Locale;
 class MutableCSSPropertyValueSet;
 class NamedNodeMap;
-class PaintLayerScrollableArea;
 class PointerLockOptions;
 class PseudoElement;
 class PseudoElementStyleRequest;
@@ -325,9 +324,10 @@
   void scrollBy(const ScrollToOptions*);
   void scrollTo(double x, double y);
   void scrollTo(const ScrollToOptions*);
-  // This will return the |GetScrollableArea| of correspond LayoutBox. For
-  // LayoutTextControlSingleLine, it will return its |InnerEditorElement|'s.
-  virtual PaintLayerScrollableArea* GetScrollableArea() const;
+  // This is similar to GetLayoutBox(), but returns nullptr if it's not
+  // scrollable. Some elements override this to delegate scroll operations to
+  // a descendant LayoutBox.
+  virtual LayoutBox* GetLayoutBoxForScrolling() const;
 
   IntRect BoundsInViewport() const;
   // Returns an intersection rectangle of the bounds rectangle and the visual
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h b/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h
index b67041a3..f87c501 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h
+++ b/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
 
 #include "base/auto_reset.h"
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -18,13 +17,15 @@
 
 class EventDispatchForbiddenScope {
   STACK_ALLOCATED();
-  DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
 
  public:
   EventDispatchForbiddenScope() {
     DCHECK(IsMainThread());
     ++count_;
   }
+  EventDispatchForbiddenScope(const EventDispatchForbiddenScope&) = delete;
+  EventDispatchForbiddenScope& operator=(const EventDispatchForbiddenScope&) =
+      delete;
 
   ~EventDispatchForbiddenScope() {
     DCHECK(IsMainThread());
@@ -57,10 +58,12 @@
 
 class EventDispatchForbiddenScope {
   STACK_ALLOCATED();
-  DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
 
  public:
   EventDispatchForbiddenScope() {}
+  EventDispatchForbiddenScope(const EventDispatchForbiddenScope&) = delete;
+  EventDispatchForbiddenScope& operator=(const EventDispatchForbiddenScope&) =
+      delete;
 
   class AllowUserAgentEvents {
    public:
diff --git a/third_party/blink/renderer/core/dom/events/event_listener.h b/third_party/blink/renderer/core/dom/events/event_listener.h
index 6235bc2..be951450 100644
--- a/third_party/blink/renderer/core/dom/events/event_listener.h
+++ b/third_party/blink/renderer/core/dom/events/event_listener.h
@@ -21,7 +21,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
@@ -47,6 +46,8 @@
 class CORE_EXPORT EventListener : public GarbageCollected<EventListener>,
                                   public NameClient {
  public:
+  EventListener(const EventListener&) = delete;
+  EventListener& operator=(const EventListener&) = delete;
   virtual ~EventListener() = default;
 
   // Invokes this event listener.
@@ -94,8 +95,6 @@
   // subclasses must inherit from either of them.
   friend class JSBasedEventListener;
   friend class NativeEventListener;
-
-  DISALLOW_COPY_AND_ASSIGN(EventListener);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_listener_map.h b/third_party/blink/renderer/core/dom/events/event_listener_map.h
index bdccfd2..44002b91 100644
--- a/third_party/blink/renderer/core/dom/events/event_listener_map.h
+++ b/third_party/blink/renderer/core/dom/events/event_listener_map.h
@@ -33,7 +33,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_MAP_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_MAP_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/registered_event_listener.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
@@ -50,6 +49,8 @@
 
  public:
   EventListenerMap();
+  EventListenerMap(const EventListenerMap&) = delete;
+  EventListenerMap& operator=(const EventListenerMap&) = delete;
 
   bool IsEmpty() const { return entries_.IsEmpty(); }
   bool Contains(const AtomicString& event_type) const;
@@ -87,7 +88,6 @@
 #if DCHECK_IS_ON()
   int active_iterator_count_ = 0;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(EventListenerMap);
 };
 
 #if !DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/dom/events/event_path.h b/third_party/blink/renderer/core/dom/events/event_path.h
index 691512e..a02ed7c8 100644
--- a/third_party/blink/renderer/core/dom/events/event_path.h
+++ b/third_party/blink/renderer/core/dom/events/event_path.h
@@ -27,7 +27,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_PATH_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_PATH_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/node_event_context.h"
 #include "third_party/blink/renderer/core/dom/events/tree_scope_event_context.h"
@@ -46,6 +45,8 @@
 class CORE_EXPORT EventPath final : public GarbageCollected<EventPath> {
  public:
   explicit EventPath(Node&, Event* = nullptr);
+  EventPath(const EventPath&) = delete;
+  EventPath& operator=(const EventPath&) = delete;
 
   void InitializeWith(Node&, Event*);
 
@@ -128,7 +129,6 @@
   Member<Event> event_;
   HeapVector<Member<TreeScopeEventContext>, 8> tree_scope_event_contexts_;
   Member<WindowEventContext> window_event_context_;
-  DISALLOW_COPY_AND_ASSIGN(EventPath);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_target.h b/third_party/blink/renderer/core/dom/events/event_target.h
index 5bf904c..2bec93e 100644
--- a/third_party/blink/renderer/core/dom/events/event_target.h
+++ b/third_party/blink/renderer/core/dom/events/event_target.h
@@ -34,7 +34,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
@@ -80,13 +79,14 @@
     : public GarbageCollected<EventTargetData> {
  public:
   EventTargetData();
+  EventTargetData(const EventTargetData&) = delete;
+  EventTargetData& operator=(const EventTargetData&) = delete;
   ~EventTargetData();
 
   void Trace(Visitor*) const;
 
   EventListenerMap event_listener_map;
   std::unique_ptr<FiringEventIteratorVector> firing_event_iterators;
-  DISALLOW_COPY_AND_ASSIGN(EventTargetData);
 };
 
 // All DOM event targets extend EventTarget. The spec is defined here:
diff --git a/third_party/blink/renderer/core/dom/events/scoped_event_queue.h b/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
index e2e9cb8..504b51b 100644
--- a/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
+++ b/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
@@ -31,7 +31,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_SCOPED_EVENT_QUEUE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_SCOPED_EVENT_QUEUE_H_
 
-#include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
@@ -45,6 +44,8 @@
   USING_FAST_MALLOC(ScopedEventQueue);
 
  public:
+  ScopedEventQueue(const ScopedEventQueue&) = delete;
+  ScopedEventQueue& operator=(const ScopedEventQueue&) = delete;
   ~ScopedEventQueue();
 
   void EnqueueEvent(Event&);
@@ -64,7 +65,6 @@
   unsigned scoping_level_;
 
   static ScopedEventQueue* instance_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedEventQueue);
 };
 
 class EventQueueScope {
@@ -72,8 +72,9 @@
 
  public:
   EventQueueScope() { ScopedEventQueue::Instance()->IncrementScopingLevel(); }
+  EventQueueScope(const EventQueueScope&) = delete;
+  EventQueueScope& operator=(const EventQueueScope&) = delete;
   ~EventQueueScope() { ScopedEventQueue::Instance()->DecrementScopingLevel(); }
-  DISALLOW_COPY_AND_ASSIGN(EventQueueScope);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/window_event_context.h b/third_party/blink/renderer/core/dom/events/window_event_context.h
index c5ce666..8b67d01 100644
--- a/third_party/blink/renderer/core/dom/events/window_event_context.h
+++ b/third_party/blink/renderer/core/dom/events/window_event_context.h
@@ -27,7 +27,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_WINDOW_EVENT_CONTEXT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_WINDOW_EVENT_CONTEXT_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
@@ -40,6 +39,8 @@
 class WindowEventContext : public GarbageCollected<WindowEventContext> {
  public:
   WindowEventContext(Event&, const NodeEventContext& top_node_event_context);
+  WindowEventContext(const WindowEventContext&) = delete;
+  WindowEventContext& operator=(const WindowEventContext&) = delete;
 
   LocalDOMWindow* Window() const;
   EventTarget* Target() const;
@@ -52,7 +53,6 @@
   Member<LocalDOMWindow> window_;
   Member<EventTarget> target_;
   Member<EventTarget> related_target_;
-  DISALLOW_COPY_AND_ASSIGN(WindowEventContext);
 };
 
 inline LocalDOMWindow* WindowEventContext::Window() const {
diff --git a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
index 4b6e05a9..64b94100 100644
--- a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
@@ -25,7 +25,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FIRST_LETTER_PSEUDO_ELEMENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FIRST_LETTER_PSEUDO_ELEMENT_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/pseudo_element.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -40,6 +39,8 @@
 class CORE_EXPORT FirstLetterPseudoElement final : public PseudoElement {
  public:
   explicit FirstLetterPseudoElement(Element*);
+  FirstLetterPseudoElement(const FirstLetterPseudoElement&) = delete;
+  FirstLetterPseudoElement& operator=(const FirstLetterPseudoElement&) = delete;
   ~FirstLetterPseudoElement() override;
 
   static LayoutText* FirstLetterTextLayoutObject(const Element&);
@@ -62,7 +63,6 @@
   void AttachFirstLetterTextLayoutObjects(LayoutText* first_letter_text);
 
   LayoutTextFragment* remaining_text_layout_object_;
-  DISALLOW_COPY_AND_ASSIGN(FirstLetterPseudoElement);
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/dom/flat_tree_node_data.h b/third_party/blink/renderer/core/dom/flat_tree_node_data.h
index 4a8b63a..46bc1e73 100644
--- a/third_party/blink/renderer/core/dom/flat_tree_node_data.h
+++ b/third_party/blink/renderer/core/dom/flat_tree_node_data.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_NODE_DATA_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_NODE_DATA_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -16,6 +15,8 @@
 class FlatTreeNodeData final : public GarbageCollected<FlatTreeNodeData> {
  public:
   FlatTreeNodeData() {}
+  FlatTreeNodeData(const FlatTreeNodeData&) = delete;
+  FlatTreeNodeData& operator=(const FlatTreeNodeData&) = delete;
   void Clear() {
     assigned_slot_ = nullptr;
     previous_in_assigned_nodes_ = nullptr;
@@ -54,7 +55,6 @@
   WeakMember<HTMLSlotElement> assigned_slot_;
   WeakMember<Node> previous_in_assigned_nodes_;
   WeakMember<Node> next_in_assigned_nodes_;
-  DISALLOW_COPY_AND_ASSIGN(FlatTreeNodeData);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/flat_tree_traversal_forbidden_scope.h b/third_party/blink/renderer/core/dom/flat_tree_traversal_forbidden_scope.h
index 668f2b18..3815d62 100644
--- a/third_party/blink/renderer/core/dom/flat_tree_traversal_forbidden_scope.h
+++ b/third_party/blink/renderer/core/dom/flat_tree_traversal_forbidden_scope.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_FORBIDDEN_SCOPE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_FORBIDDEN_SCOPE_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 
 namespace blink {
@@ -18,6 +17,10 @@
       : count_(document.FlatTreeTraversalForbiddenRecursionDepth()) {
     ++count_;
   }
+  FlatTreeTraversalForbiddenScope(const FlatTreeTraversalForbiddenScope&) =
+      delete;
+  FlatTreeTraversalForbiddenScope& operator=(
+      const FlatTreeTraversalForbiddenScope&) = delete;
 
   ~FlatTreeTraversalForbiddenScope() {
     DCHECK_GT(count_, 0u);
@@ -26,7 +29,6 @@
 
  private:
   unsigned& count_;
-  DISALLOW_COPY_AND_ASSIGN(FlatTreeTraversalForbiddenScope);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/id_target_observer_registry.h b/third_party/blink/renderer/core/dom/id_target_observer_registry.h
index ea74a3a2..02b3b38b 100644
--- a/third_party/blink/renderer/core/dom/id_target_observer_registry.h
+++ b/third_party/blink/renderer/core/dom/id_target_observer_registry.h
@@ -26,7 +26,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ID_TARGET_OBSERVER_REGISTRY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ID_TARGET_OBSERVER_REGISTRY_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -43,6 +42,8 @@
 
  public:
   IdTargetObserverRegistry() : notifying_observers_in_set_(nullptr) {}
+  IdTargetObserverRegistry(const IdTargetObserverRegistry&) = delete;
+  IdTargetObserverRegistry& operator=(const IdTargetObserverRegistry&) = delete;
 
   void Trace(Visitor*) const;
   void NotifyObservers(const AtomicString& id);
@@ -57,7 +58,6 @@
   typedef HeapHashMap<StringImpl*, Member<ObserverSet>> IdToObserverSetMap;
   IdToObserverSetMap registry_;
   Member<ObserverSet> notifying_observers_in_set_;
-  DISALLOW_COPY_AND_ASSIGN(IdTargetObserverRegistry);
 };
 
 inline void IdTargetObserverRegistry::NotifyObservers(const AtomicString& id) {
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
index bef2e1bd..ce63ba6 100644
--- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc
+++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -17,6 +17,9 @@
 class MockIdleDeadlineScheduler final : public ThreadScheduler {
  public:
   MockIdleDeadlineScheduler() = default;
+  MockIdleDeadlineScheduler(const MockIdleDeadlineScheduler&) = delete;
+  MockIdleDeadlineScheduler& operator=(const MockIdleDeadlineScheduler&) =
+      delete;
   ~MockIdleDeadlineScheduler() override = default;
 
   // ThreadScheduler implementation:
@@ -67,9 +70,6 @@
   }
 
   void SetV8Isolate(v8::Isolate* isolate) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockIdleDeadlineScheduler);
 };
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h b/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
index 6f2a222..3f01352 100644
--- a/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
+++ b/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
@@ -22,6 +21,10 @@
       return;
     ++(*count_);
   }
+  IgnoreOpensDuringUnloadCountIncrementer(
+      const IgnoreOpensDuringUnloadCountIncrementer&) = delete;
+  IgnoreOpensDuringUnloadCountIncrementer& operator=(
+      const IgnoreOpensDuringUnloadCountIncrementer&) = delete;
 
   ~IgnoreOpensDuringUnloadCountIncrementer() {
     if (!count_)
@@ -31,7 +34,6 @@
 
  private:
   unsigned* count_;
-  DISALLOW_COPY_AND_ASSIGN(IgnoreOpensDuringUnloadCountIncrementer);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
index a4f0a3f..106fe32 100644
--- a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
+++ b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -23,6 +22,9 @@
 
  public:
   explicit IncrementLoadEventDelayCount(Document&);
+  IncrementLoadEventDelayCount(const IncrementLoadEventDelayCount&) = delete;
+  IncrementLoadEventDelayCount& operator=(const IncrementLoadEventDelayCount&) =
+      delete;
   ~IncrementLoadEventDelayCount();
 
   // Decrements the loadEventDelayCount and checks load event synchronously,
@@ -37,7 +39,6 @@
 
  private:
   WeakPersistent<Document> document_;
-  DISALLOW_COPY_AND_ASSIGN(IncrementLoadEventDelayCount);
 };
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/dom/live_node_list_registry.h b/third_party/blink/renderer/core/dom/live_node_list_registry.h
index b6ee317..ab9fc00 100644
--- a/third_party/blink/renderer/core/dom/live_node_list_registry.h
+++ b/third_party/blink/renderer/core/dom/live_node_list_registry.h
@@ -7,7 +7,6 @@
 
 #include <algorithm>
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
@@ -34,6 +33,8 @@
 
  public:
   LiveNodeListRegistry() = default;
+  LiveNodeListRegistry(const LiveNodeListRegistry&) = delete;
+  LiveNodeListRegistry& operator=(const LiveNodeListRegistry&) = delete;
   void Add(const LiveNodeListBase*, NodeListInvalidationType);
   void Remove(const LiveNodeListBase*, NodeListInvalidationType);
 
@@ -63,7 +64,6 @@
   Vector<Entry> data_;
 
   unsigned mask_ = 0;
-  DISALLOW_COPY_AND_ASSIGN(LiveNodeListRegistry);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/names_map.h b/third_party/blink/renderer/core/dom/names_map.h
index 659a2e3..3a0a318 100644
--- a/third_party/blink/renderer/core/dom/names_map.h
+++ b/third_party/blink/renderer/core/dom/names_map.h
@@ -27,6 +27,8 @@
 
  public:
   NamesMap() = default;
+  NamesMap(const NamesMap&) = delete;
+  NamesMap& operator=(const NamesMap&) = delete;
   explicit NamesMap(const AtomicString& string);
 
   // Clears any existing mapping, parses the string and sets the mapping from
@@ -44,8 +46,6 @@
   void Set(const AtomicString&, const CharacterType*);
 
   HashMap<AtomicString, base::Optional<SpaceSplitString>> data_;
-
-  DISALLOW_COPY_AND_ASSIGN(NamesMap);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/node_lists_node_data.h b/third_party/blink/renderer/core/dom/node_lists_node_data.h
index 3818015..f2457b5 100644
--- a/third_party/blink/renderer/core/dom/node_lists_node_data.h
+++ b/third_party/blink/renderer/core/dom/node_lists_node_data.h
@@ -22,7 +22,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_LISTS_NODE_DATA_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_LISTS_NODE_DATA_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/child_node_list.h"
 #include "third_party/blink/renderer/core/dom/empty_node_list.h"
 #include "third_party/blink/renderer/core/dom/qualified_name.h"
@@ -133,6 +132,8 @@
   }
 
   NodeListsNodeData() : child_node_list_(nullptr) {}
+  NodeListsNodeData(const NodeListsNodeData&) = delete;
+  NodeListsNodeData& operator=(const NodeListsNodeData&) = delete;
 
   void InvalidateCaches(const QualifiedName* attr_name = nullptr);
 
@@ -173,7 +174,6 @@
   Member<NodeList> child_node_list_;
   NodeListAtomicNameCacheMap atomic_name_caches_;
   TagCollectionNSCache tag_collection_ns_caches_;
-  DISALLOW_COPY_AND_ASSIGN(NodeListsNodeData);
 };
 
 template <typename Collection>
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.h b/third_party/blink/renderer/core/dom/node_rare_data.h
index 9858939..95eb4e76 100644
--- a/third_party/blink/renderer/core/dom/node_rare_data.h
+++ b/third_party/blink/renderer/core/dom/node_rare_data.h
@@ -22,7 +22,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_RARE_DATA_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_RARE_DATA_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/wtf/bit_field.h"
@@ -43,6 +42,8 @@
     : public GarbageCollected<NodeMutationObserverData> {
  public:
   NodeMutationObserverData() = default;
+  NodeMutationObserverData(const NodeMutationObserverData&) = delete;
+  NodeMutationObserverData& operator=(const NodeMutationObserverData&) = delete;
 
   const HeapVector<Member<MutationObserverRegistration>>& Registry() {
     return registry_;
@@ -62,7 +63,6 @@
  private:
   HeapVector<Member<MutationObserverRegistration>> registry_;
   HeapHashSet<Member<MutationObserverRegistration>> transient_registry_;
-  DISALLOW_COPY_AND_ASSIGN(NodeMutationObserverData);
 };
 
 class GC_PLUGIN_IGNORE(
@@ -107,6 +107,8 @@
  public:
   NodeRenderingData(LayoutObject*,
                     scoped_refptr<const ComputedStyle> computed_style);
+  NodeRenderingData(const NodeRenderingData&) = delete;
+  NodeRenderingData& operator=(const NodeRenderingData&) = delete;
 
   LayoutObject* GetLayoutObject() const { return layout_object_; }
   void SetLayoutObject(LayoutObject* layout_object) {
@@ -129,7 +131,6 @@
  private:
   LayoutObject* layout_object_;
   scoped_refptr<const ComputedStyle> computed_style_;
-  DISALLOW_COPY_AND_ASSIGN(NodeRenderingData);
 };
 
 class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.") NodeRareData
@@ -137,6 +138,8 @@
  public:
   explicit NodeRareData(NodeRenderingData* node_layout_data)
       : NodeRareData(node_layout_data, false) {}
+  NodeRareData(const NodeRareData&) = delete;
+  NodeRareData& operator=(const NodeRareData&) = delete;
 
   NodeRenderingData* GetNodeRenderingData() const { return node_layout_data_; }
   void SetNodeRenderingData(NodeRenderingData* node_layout_data) {
@@ -223,8 +226,6 @@
   // Keeps strong scroll timeline pointers linked to this node to ensure
   // the timelines are alive as long as the node is alive.
   Member<HeapHashSet<Member<ScrollTimeline>>> scroll_timelines_;
-
-  DISALLOW_COPY_AND_ASSIGN(NodeRareData);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/nth_index_cache.h b/third_party/blink/renderer/core/dom/nth_index_cache.h
index b3c38ed3..1c3f636 100644
--- a/third_party/blink/renderer/core/dom/nth_index_cache.h
+++ b/third_party/blink/renderer/core/dom/nth_index_cache.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NTH_INDEX_CACHE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NTH_INDEX_CACHE_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -19,6 +18,8 @@
  public:
   NthIndexData(ContainerNode&);
   NthIndexData(ContainerNode&, const QualifiedName& type);
+  NthIndexData(const NthIndexData&) = delete;
+  NthIndexData& operator=(const NthIndexData&) = delete;
 
   unsigned NthIndex(Element&) const;
   unsigned NthLastIndex(Element&) const;
@@ -30,7 +31,6 @@
  private:
   HeapHashMap<Member<Element>, unsigned> element_index_map_;
   unsigned count_ = 0;
-  DISALLOW_COPY_AND_ASSIGN(NthIndexData);
 };
 
 class CORE_EXPORT NthIndexCache final {
@@ -38,6 +38,8 @@
 
  public:
   explicit NthIndexCache(Document&);
+  NthIndexCache(const NthIndexCache&) = delete;
+  NthIndexCache& operator=(const NthIndexCache&) = delete;
   ~NthIndexCache();
 
   static unsigned NthChildIndex(Element&);
@@ -62,7 +64,6 @@
 #if DCHECK_IS_ON()
   uint64_t dom_tree_version_;
 #endif
-  DISALLOW_COPY_AND_ASSIGN(NthIndexCache);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/pseudo_element_data.h b/third_party/blink/renderer/core/dom/pseudo_element_data.h
index 01f1355..73a78bc 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element_data.h
+++ b/third_party/blink/renderer/core/dom/pseudo_element_data.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_PSEUDO_ELEMENT_DATA_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_PSEUDO_ELEMENT_DATA_H_
 
-#include "base/macros.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -14,6 +13,8 @@
 class PseudoElementData final : public GarbageCollected<PseudoElementData> {
  public:
   PseudoElementData() = default;
+  PseudoElementData(const PseudoElementData&) = delete;
+  PseudoElementData& operator=(const PseudoElementData&) = delete;
 
   void SetPseudoElement(PseudoId, PseudoElement*);
   PseudoElement* GetPseudoElement(PseudoId) const;
@@ -37,7 +38,6 @@
   Member<PseudoElement> generated_marker_;
   Member<PseudoElement> generated_first_letter_;
   Member<PseudoElement> backdrop_;
-  DISALLOW_COPY_AND_ASSIGN(PseudoElementData);
 };
 
 inline bool PseudoElementData::HasPseudoElements() const {
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc
index 5b0e901..d1f22b7 100644
--- a/third_party/blink/renderer/core/dom/range.cc
+++ b/third_party/blink/renderer/core/dom/range.cc
@@ -79,6 +79,8 @@
 #endif
     }
   }
+  RangeUpdateScope(const RangeUpdateScope&) = delete;
+  RangeUpdateScope& operator=(const RangeUpdateScope&) = delete;
 
   ~RangeUpdateScope() {
     DCHECK_GE(scope_count_, 1);
@@ -109,7 +111,6 @@
   Range* range_ = nullptr;
   Document* old_document_ = nullptr;
 
-  DISALLOW_COPY_AND_ASSIGN(RangeUpdateScope);
 };
 
 int RangeUpdateScope::scope_count_ = 0;
diff --git a/third_party/blink/renderer/core/dom/scoped_window_focus_allowed_indicator.h b/third_party/blink/renderer/core/dom/scoped_window_focus_allowed_indicator.h
index 9dd6afb..a5316cc 100644
--- a/third_party/blink/renderer/core/dom/scoped_window_focus_allowed_indicator.h
+++ b/third_party/blink/renderer/core/dom/scoped_window_focus_allowed_indicator.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCOPED_WINDOW_FOCUS_ALLOWED_INDICATOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCOPED_WINDOW_FOCUS_ALLOWED_INDICATOR_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 
 namespace blink {
@@ -19,6 +18,10 @@
       : execution_context_(execution_context) {
     execution_context->AllowWindowInteraction();
   }
+  ScopedWindowFocusAllowedIndicator(const ScopedWindowFocusAllowedIndicator&) =
+      delete;
+  ScopedWindowFocusAllowedIndicator& operator=(
+      const ScopedWindowFocusAllowedIndicator&) = delete;
   ~ScopedWindowFocusAllowedIndicator() {
     execution_context_->ConsumeWindowInteraction();
   }
@@ -27,7 +30,6 @@
   // This doesn't create a cycle because ScopedWindowFocusAllowedIndicator
   // is used only on a machine stack.
   Persistent<ExecutionContext> execution_context_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedWindowFocusAllowedIndicator);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
index dcb0742..e2bb5eb 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -23,6 +23,10 @@
  public:
   explicit MockScriptedIdleTaskControllerScheduler(ShouldYield should_yield)
       : should_yield_(should_yield == ShouldYield::YIELD) {}
+  MockScriptedIdleTaskControllerScheduler(
+      const MockScriptedIdleTaskControllerScheduler&) = delete;
+  MockScriptedIdleTaskControllerScheduler& operator=(
+      const MockScriptedIdleTaskControllerScheduler&) = delete;
   ~MockScriptedIdleTaskControllerScheduler() override = default;
 
   // ThreadScheduler implementation:
@@ -91,8 +95,6 @@
   Thread::IdleTask idle_task_;
   scoped_refptr<scheduler::FakeTaskRunner> task_runner_ =
       base::MakeRefCounted<scheduler::FakeTaskRunner>();
-
-  DISALLOW_COPY_AND_ASSIGN(MockScriptedIdleTaskControllerScheduler);
 };
 
 class MockIdleTask : public ScriptedIdleTaskController::IdleTask {
diff --git a/third_party/blink/renderer/core/dom/shadow_root.h b/third_party/blink/renderer/core/dom/shadow_root.h
index e6bde410..909c1420 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/third_party/blink/renderer/core/dom/shadow_root.h
@@ -51,6 +51,8 @@
 
  public:
   ShadowRoot(Document&, ShadowRootType);
+  ShadowRoot(const ShadowRoot&) = delete;
+  ShadowRoot& operator=(const ShadowRoot&) = delete;
 
   // Disambiguate between Node and TreeScope hierarchies; TreeScope's
   // implementation is simpler.
@@ -195,8 +197,6 @@
   unsigned is_declarative_shadow_root_ : 1;
   unsigned needs_distribution_recalc_ : 1;
   unsigned unused_ : 9;
-
-  DISALLOW_COPY_AND_ASSIGN(ShadowRoot);
 };
 
 inline Element* ShadowRoot::ActiveElement() const {
diff --git a/third_party/blink/renderer/core/dom/shadow_root_v0.h b/third_party/blink/renderer/core/dom/shadow_root_v0.h
index 4aae91a..eb1fed9 100644
--- a/third_party/blink/renderer/core/dom/shadow_root_v0.h
+++ b/third_party/blink/renderer/core/dom/shadow_root_v0.h
@@ -43,6 +43,8 @@
       HeapHashMap<Member<const Node>, Member<DestinationInsertionPoints>>;
 
   explicit ShadowRootV0(ShadowRoot& shadow_root) : shadow_root_(&shadow_root) {}
+  ShadowRootV0(const ShadowRootV0&) = delete;
+  ShadowRootV0& operator=(const ShadowRootV0&) = delete;
 
   bool ContainsShadowElements() const {
     return descendant_shadow_element_count_;
@@ -97,8 +99,6 @@
   SelectRuleFeatureSet select_features_;
   bool needs_select_feature_set_ = false;
   bool descendant_insertion_points_is_valid_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(ShadowRootV0);
 };
 
 inline void ShadowRootV0::DidAddInsertionPoint(V0InsertionPoint* point) {
diff --git a/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h b/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h
index 8e25b44c..6ed832a1 100644
--- a/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h
+++ b/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SLOT_ASSIGNMENT_RECALC_FORBIDDEN_SCOPE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SLOT_ASSIGNMENT_RECALC_FORBIDDEN_SCOPE_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 
 namespace blink {
@@ -20,11 +19,14 @@
     ++count_;
   }
 
+  SlotAssignmentRecalcForbiddenScope(
+      const SlotAssignmentRecalcForbiddenScope&) = delete;
+  SlotAssignmentRecalcForbiddenScope& operator=(
+      const SlotAssignmentRecalcForbiddenScope&) = delete;
   ~SlotAssignmentRecalcForbiddenScope() { --count_; }
 
  private:
   unsigned& count_;
-  DISALLOW_COPY_AND_ASSIGN(SlotAssignmentRecalcForbiddenScope);
 };
 #else
 class SlotAssignmentRecalcForbiddenScope {
@@ -32,9 +34,10 @@
 
  public:
   explicit SlotAssignmentRecalcForbiddenScope(Document&) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SlotAssignmentRecalcForbiddenScope);
+  SlotAssignmentRecalcForbiddenScope(
+      const SlotAssignmentRecalcForbiddenScope&) = delete;
+  SlotAssignmentRecalcForbiddenScope& operator=(
+      const SlotAssignmentRecalcForbiddenScope&) = delete;
 };
 #endif
 
diff --git a/third_party/blink/renderer/core/dom/text_link_colors.h b/third_party/blink/renderer/core/dom/text_link_colors.h
index f21ebc53..2bd88ad0 100644
--- a/third_party/blink/renderer/core/dom/text_link_colors.h
+++ b/third_party/blink/renderer/core/dom/text_link_colors.h
@@ -30,7 +30,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TEXT_LINK_COLORS_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TEXT_LINK_COLORS_H_
 
-#include "base/macros.h"
 #include "third_party/blink/public/platform/web_color_scheme.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -44,6 +43,8 @@
 
  public:
   TextLinkColors();
+  TextLinkColors(const TextLinkColors&) = delete;
+  TextLinkColors& operator=(const TextLinkColors&) = delete;
 
   void SetTextColor(const Color& color) { text_color_ = color; }
   Color TextColor() const { return text_color_; }
@@ -67,7 +68,6 @@
   Color link_color_;
   Color visited_link_color_;
   Color active_link_color_;
-  DISALLOW_COPY_AND_ASSIGN(TextLinkColors);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/throw_on_dynamic_markup_insertion_count_incrementer.h b/third_party/blink/renderer/core/dom/throw_on_dynamic_markup_insertion_count_incrementer.h
index 706b40ae..bbb9d2cfa 100644
--- a/third_party/blink/renderer/core/dom/throw_on_dynamic_markup_insertion_count_incrementer.h
+++ b/third_party/blink/renderer/core/dom/throw_on_dynamic_markup_insertion_count_incrementer.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_THROW_ON_DYNAMIC_MARKUP_INSERTION_COUNT_INCREMENTER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_THROW_ON_DYNAMIC_MARKUP_INSERTION_COUNT_INCREMENTER_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
@@ -22,6 +21,10 @@
       return;
     ++(*count_);
   }
+  ThrowOnDynamicMarkupInsertionCountIncrementer(
+      const ThrowOnDynamicMarkupInsertionCountIncrementer&) = delete;
+  ThrowOnDynamicMarkupInsertionCountIncrementer& operator=(
+      const ThrowOnDynamicMarkupInsertionCountIncrementer&) = delete;
 
   ~ThrowOnDynamicMarkupInsertionCountIncrementer() {
     if (!count_)
@@ -31,7 +34,6 @@
 
  private:
   unsigned* count_;
-  DISALLOW_COPY_AND_ASSIGN(ThrowOnDynamicMarkupInsertionCountIncrementer);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/transform_source.h b/third_party/blink/renderer/core/dom/transform_source.h
index 46ba990..a3d223f 100644
--- a/third_party/blink/renderer/core/dom/transform_source.h
+++ b/third_party/blink/renderer/core/dom/transform_source.h
@@ -21,7 +21,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRANSFORM_SOURCE_H_
 
 #include <libxml/tree.h>
-#include "base/macros.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 namespace blink {
@@ -31,13 +30,14 @@
 
  public:
   explicit TransformSource(xmlDocPtr source);
+  TransformSource(const TransformSource&) = delete;
+  TransformSource& operator=(const TransformSource&) = delete;
   ~TransformSource();
 
   xmlDocPtr PlatformSource() const { return source_; }
 
  private:
   xmlDocPtr source_;
-  DISALLOW_COPY_AND_ASSIGN(TransformSource);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/tree_ordered_list.h b/third_party/blink/renderer/core/dom/tree_ordered_list.h
index 057cf5b..212fdb8 100644
--- a/third_party/blink/renderer/core/dom/tree_ordered_list.h
+++ b/third_party/blink/renderer/core/dom/tree_ordered_list.h
@@ -30,7 +30,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TREE_ORDERED_LIST_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TREE_ORDERED_LIST_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/list_hash_set.h"
 
@@ -43,6 +42,8 @@
 
  public:
   TreeOrderedList() = default;
+  TreeOrderedList(const TreeOrderedList&) = delete;
+  TreeOrderedList& operator=(const TreeOrderedList&) = delete;
 
   void Add(Node*);
   void Remove(const Node*);
@@ -67,7 +68,6 @@
 
  private:
   HeapListHashSet<Member<Node>, 32> nodes_;
-  DISALLOW_COPY_AND_ASSIGN(TreeOrderedList);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/use_counter_helper.h b/third_party/blink/renderer/core/frame/use_counter_helper.h
index d2be59c..d8802d45 100644
--- a/third_party/blink/renderer/core/frame/use_counter_helper.h
+++ b/third_party/blink/renderer/core/frame/use_counter_helper.h
@@ -28,7 +28,7 @@
 
 #include <bitset>
 #include "base/macros.h"
-#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc
index 7294fb58..4f29f18 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -2019,13 +2019,11 @@
   ContainerNode::ChildrenChanged(change);
 }
 
-PaintLayerScrollableArea* HTMLInputElement::GetScrollableArea() const {
-  // If it's LayoutTextControlSingleLine, return InnerEditorElement's scrollable
-  // area.
+LayoutBox* HTMLInputElement::GetLayoutBoxForScrolling() const {
+  // If it's LayoutTextControlSingleLine, return InnerEditorElement's LayoutBox.
   if (IsTextField() && InnerEditorElement())
-    return InnerEditorElement()->GetScrollableArea();
-
-  return Element::GetScrollableArea();
+    return InnerEditorElement()->GetLayoutBox();
+  return Element::GetLayoutBoxForScrolling();
 }
 
 bool HTMLInputElement::IsDraggedSlider() const {
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h
index 3d8b5cd..212c281 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -332,7 +332,7 @@
 
   void ChildrenChanged(const ChildrenChange&) override;
 
-  PaintLayerScrollableArea* GetScrollableArea() const final;
+  LayoutBox* GetLayoutBoxForScrolling() const final;
 
   void SetHasBeenPasswordField() { has_been_password_field_ = true; }
 
diff --git a/third_party/blink/renderer/core/input/scroll_snap_test.cc b/third_party/blink/renderer/core/input/scroll_snap_test.cc
index 2580a6d..f38b65d9 100644
--- a/third_party/blink/renderer/core/input/scroll_snap_test.cc
+++ b/third_party/blink/renderer/core/input/scroll_snap_test.cc
@@ -137,8 +137,10 @@
 
 void ScrollSnapTest::SetInitialScrollOffset(double x, double y) {
   Element* scroller = GetDocument().getElementById("scroller");
-  scroller->GetScrollableArea()->ScrollToAbsolutePosition(
-      FloatPoint(x, y), mojom::blink::ScrollBehavior::kAuto);
+  scroller->GetLayoutBoxForScrolling()
+      ->GetScrollableArea()
+      ->ScrollToAbsolutePosition(FloatPoint(x, y),
+                                 mojom::blink::ScrollBehavior::kAuto);
   ASSERT_EQ(scroller->scrollLeft(), x);
   ASSERT_EQ(scroller->scrollTop(), y);
 }
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
index 7388410b..69866f4 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -727,7 +727,8 @@
   EXPECT_FALSE(observation2->CanUseCachedRectsForTesting());
 
   // Scrolling the root should not invalidate.
-  PaintLayerScrollableArea* root_scroller = root->GetScrollableArea();
+  PaintLayerScrollableArea* root_scroller =
+      root->GetLayoutBoxForScrolling()->GetScrollableArea();
   root_scroller->SetScrollOffset(ScrollOffset(0, 100),
                                  mojom::blink::ScrollType::kProgrammatic);
   EXPECT_TRUE(observation1->CanUseCachedRectsForTesting());
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 0eee71f..3807c5c 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -226,6 +226,24 @@
                     : LayoutUnit());
 }
 
+#if DCHECK_IS_ON()
+void CheckDidAddFragment(const LayoutBox& box,
+                         const NGPhysicalBoxFragment& fragment) {
+  // If |HasFragmentItems|, |ChildrenInline()| should be true.
+  // |HasFragmentItems| uses this condition to optimize .
+  if (fragment.HasItems())
+    DCHECK(box.ChildrenInline());
+
+  for (const NGPhysicalBoxFragment& fragment : box.PhysicalFragments()) {
+    if (const NGFragmentItems* fragment_items = fragment.Items())
+      fragment_items->CheckAllItemsAreValid();
+  }
+}
+#else
+inline void CheckDidAddFragment(const LayoutBox& box,
+                                const NGPhysicalBoxFragment& fragment) {}
+#endif
+
 }  // anonymous namespace
 
 BoxLayoutExtraInput::BoxLayoutExtraInput(LayoutBox& box) : box(box) {
@@ -2612,6 +2630,14 @@
                    : !inline_box_wrapper_);
 }
 
+bool LayoutBox::NGPhysicalFragmentList::HasFragmentItems() const {
+  for (const NGPhysicalBoxFragment& fragment : *this) {
+    if (fragment.HasItems())
+      return true;
+  }
+  return false;
+}
+
 void LayoutBox::SetCachedLayoutResult(
     scoped_refptr<const NGLayoutResult> result) {
   DCHECK(!result->PhysicalFragment().BreakToken());
@@ -2645,18 +2671,15 @@
     ReplaceLayoutResult(std::move(result), index);
     return;
   }
+
   DCHECK_EQ(index, layout_results_.size());
   const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
   layout_results_.push_back(std::move(result));
-#if DCHECK_IS_ON()
-  for (const NGPhysicalBoxFragment& fragment : PhysicalFragments()) {
-    if (const NGFragmentItems* fragment_items = fragment.Items())
-      fragment_items->CheckAllItemsAreValid();
-  }
-#endif
+  CheckDidAddFragment(*this, fragment);
+
   // If this is the last fragment for the node, and its node establishes an
   // inline formatting context, we have some finalization to do.
-  if (!fragment.BreakToken() && fragment.Items())
+  if (!fragment.BreakToken() && HasFragmentItems())
     NGFragmentItems::FinalizeAfterLayout(layout_results_);
 }
 
@@ -2686,15 +2709,11 @@
     }
   }
   layout_results_[index] = std::move(result);
-#if DCHECK_IS_ON()
-  for (const NGPhysicalBoxFragment& fragment : PhysicalFragments()) {
-    if (const NGFragmentItems* fragment_items = fragment.Items())
-      fragment_items->CheckAllItemsAreValid();
-  }
-#endif
+  CheckDidAddFragment(*this, fragment);
+
   // If this is the last fragment for the node, and its node establishes an
   // inline formatting context, we have some finalization to do.
-  if (!fragment.BreakToken() && fragment.Items() && (index || got_new_fragment))
+  if (got_new_fragment && !fragment.BreakToken() && HasFragmentItems())
     NGFragmentItems::FinalizeAfterLayout(layout_results_);
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index 063970b2..070bb2e5 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -719,8 +719,8 @@
   // scroll shadow content (but pretend that they are the objects that are
   // scrolling).
 
-  // Replaced ScrollLeft/Top by using Element::GetScrollableArea to return the
-  // correct ScrollableArea.
+  // Replaced ScrollLeft/Top by using Element::GetLayoutBoxForScrolling to
+  // return the correct ScrollableArea.
   // TODO(cathiechen): We should do the same with ScrollWidth|Height .
   virtual LayoutUnit ScrollWidth() const;
   virtual LayoutUnit ScrollHeight() const;
@@ -1017,6 +1017,8 @@
     wtf_size_t Size() const { return layout_results_.size(); }
     bool IsEmpty() const { return layout_results_.IsEmpty(); }
 
+    bool HasFragmentItems() const;
+
     class CORE_EXPORT Iterator : public std::iterator<std::forward_iterator_tag,
                                                       NGPhysicalBoxFragment> {
      public:
@@ -1848,6 +1850,10 @@
   TextDirection ResolvedDirection() const;
 
  private:
+  bool HasFragmentItems() const {
+    return ChildrenInline() && PhysicalFragments().HasFragmentItems();
+  }
+
   inline bool LayoutOverflowIsSet() const {
     return overflow_ && overflow_->layout_overflow;
   }
diff --git a/third_party/blink/renderer/core/layout/map_coordinates_test.cc b/third_party/blink/renderer/core/layout/map_coordinates_test.cc
index 6c065df..14cd3a1d 100644
--- a/third_party/blink/renderer/core/layout/map_coordinates_test.cc
+++ b/third_party/blink/renderer/core/layout/map_coordinates_test.cc
@@ -154,6 +154,7 @@
   LayoutObject* target = GetLayoutObjectByElementId("target");
   LayoutObject* overflow = GetLayoutObjectByElementId("overflow");
   To<Element>(overflow->GetNode())
+      ->GetLayoutBoxForScrolling()
       ->GetScrollableArea()
       ->ScrollToAbsolutePosition(FloatPoint(32, 54));
 
@@ -1743,6 +1744,7 @@
       MapLocalToAncestor(box, scroller, PhysicalOffset(), kIgnoreScrollOffset));
 
   To<Element>(scroller->GetNode())
+      ->GetLayoutBoxForScrolling()
       ->GetScrollableArea()
       ->ScrollToAbsolutePosition(FloatPoint(0, 50));
 
@@ -1781,6 +1783,7 @@
       MapLocalToAncestor(box, scroller, PhysicalOffset(), kIgnoreScrollOffset));
 
   To<Element>(scroller->GetNode())
+      ->GetLayoutBoxForScrolling()
       ->GetScrollableArea()
       ->ScrollToAbsolutePosition(FloatPoint(0, 50));
 
@@ -1817,8 +1820,9 @@
       PhysicalOffset(1990, 10),
       MapLocalToAncestor(box, scroller, PhysicalOffset(), kIgnoreScrollOffset));
 
-  scroll_element->GetScrollableArea()->ScrollToAbsolutePosition(
-      FloatPoint(0, 50));
+  scroll_element->GetLayoutBoxForScrolling()
+      ->GetScrollableArea()
+      ->ScrollToAbsolutePosition(FloatPoint(0, 50));
 
   EXPECT_EQ(PhysicalOffset(1990, -40),
             MapLocalToAncestor(box, scroller, PhysicalOffset()));
@@ -1826,8 +1830,9 @@
       PhysicalOffset(1990, 10),
       MapLocalToAncestor(box, scroller, PhysicalOffset(), kIgnoreScrollOffset));
 
-  scroll_element->GetScrollableArea()->ScrollToAbsolutePosition(
-      FloatPoint(1900, 50));
+  scroll_element->GetLayoutBoxForScrolling()
+      ->GetScrollableArea()
+      ->ScrollToAbsolutePosition(FloatPoint(1900, 50));
 
   EXPECT_EQ(PhysicalOffset(90, -40),
             MapLocalToAncestor(box, scroller, PhysicalOffset()));
@@ -1868,6 +1873,7 @@
       MapLocalToAncestor(box, scroller, PhysicalOffset(), kIgnoreScrollOffset));
 
   To<Element>(scroller->GetNode())
+      ->GetLayoutBoxForScrolling()
       ->GetScrollableArea()
       ->ScrollToAbsolutePosition(FloatPoint(0, 0));
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
index a8d3577..882fbec1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -12,10 +12,37 @@
 
 namespace blink {
 
+namespace {
+
+#if DCHECK_IS_ON()
+void CheckNoItemsAreAssociated(const NGPhysicalBoxFragment& fragment) {
+  if (const NGFragmentItems* fragment_items = fragment.Items()) {
+    for (const NGFragmentItem& item : fragment_items->Items()) {
+      if (item.Type() == NGFragmentItem::kLine)
+        continue;
+      if (const LayoutObject* layout_object = item.GetLayoutObject())
+        DCHECK(!layout_object->FirstInlineFragmentItemIndex());
+    }
+  }
+}
+
+void CheckIsLast(const NGFragmentItem& item) {
+  if (const NGPhysicalBoxFragment* fragment = item.BoxFragment()) {
+    if (!fragment->IsInline()) {
+      DCHECK(fragment->IsFloating());
+      DCHECK_EQ(item.IsLastForNode(), !fragment->BreakToken());
+    }
+  }
+}
+#endif
+
+}  // namespace
+
 NGFragmentItems::NGFragmentItems(NGFragmentItemsBuilder* builder)
     : text_content_(std::move(builder->text_content_)),
       first_line_text_content_(std::move(builder->first_line_text_content_)),
-      size_(builder->items_.size()) {
+      size_(builder->items_.size()),
+      size_of_earlier_fragments_(0) {
   NGFragmentItemsBuilder::ItemWithOffsetList& source_items = builder->items_;
   for (unsigned i = 0; i < size_; ++i) {
     // Call the move constructor to move without |AddRef|. Items in
@@ -36,27 +63,32 @@
 
 void NGFragmentItems::FinalizeAfterLayout(
     const Vector<scoped_refptr<const NGLayoutResult>, 1>& results) {
+#if DCHECK_IS_ON()
+  if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+    for (const auto& result : results) {
+      CheckNoItemsAreAssociated(
+          To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+    }
+  }
+#endif
   struct LastItem {
     const NGFragmentItem* item;
     wtf_size_t fragment_id;
     wtf_size_t item_index;
   };
   HashMap<const LayoutObject*, LastItem> last_items;
+  wtf_size_t item_index = 0;
   for (const auto& result : results) {
     const auto& fragment =
         To<NGPhysicalBoxFragment>(result->PhysicalFragment());
-    const NGFragmentItems* current = fragment.Items();
-    if (UNLIKELY(!current))
+    const NGFragmentItems* fragment_items = fragment.Items();
+    if (UNLIKELY(!fragment_items))
       continue;
 
-    // TODO(layout-dev): Make this work for multiple box fragments (block
-    // fragmentation).
-    const bool create_index_cache = fragment.IsFirstForNode();
-
-    const Span items = current->Items();
-    wtf_size_t index = 0;
+    fragment_items->size_of_earlier_fragments_ = item_index;
+    const Span items = fragment_items->Items();
     for (const NGFragmentItem& item : items) {
-      ++index;
+      ++item_index;
       if (item.Type() == NGFragmentItem::kLine) {
         DCHECK_EQ(item.DeltaToNextForSameLayoutObject(), 0u);
         continue;
@@ -66,56 +98,60 @@
       DCHECK(layout_object->IsInLayoutNGInlineFormattingContext());
 
       item.SetDeltaToNextForSameLayoutObject(0);
-      item.SetIsLastForNode(false);
-
-      // Fragments that aren't really on a line, such as floats, will have block
-      // break tokens if they continue in a subsequent fragmentainer, so just
-      // check that. Floats in particular will continue as regular box fragment
-      // children in subsequent fragmentainers, i.e. they will not be fragment
-      // items (even if we're in an inline formatting context). So we're not
-      // going to find the last fragment by just looking for items.
-      bool skip_last_items_map = false;
-      if (const NGPhysicalBoxFragment* child_fragment = item.BoxFragment()) {
-        if (!child_fragment->IsInline()) {
-          item.SetIsLastForNode(!child_fragment->BreakToken());
-          skip_last_items_map = true;
-        }
+      if (UNLIKELY(layout_object->IsFloating())) {
+        // Fragments that aren't really on a line, such as floats, will have
+        // block break tokens if they continue in a subsequent fragmentainer, so
+        // just check that. Floats in particular will continue as regular box
+        // fragment children in subsequent fragmentainers, i.e. they will not be
+        // fragment items (even if we're in an inline formatting context). So
+        // we're not going to find the last fragment by just looking for items.
+        DCHECK(item.BoxFragment() && item.BoxFragment()->IsFloating());
+        item.SetIsLastForNode(!item.BoxFragment()->BreakToken());
+      } else {
+        DCHECK(layout_object->IsInline());
+        // This will be updated later if following fragments are found.
+        item.SetIsLastForNode(true);
       }
 
-      bool is_first = skip_last_items_map;
-      LastItem* last = nullptr;
-      if (!skip_last_items_map) {
-        const auto last_item_result =
-            last_items.insert(layout_object, LastItem{&item, 0, index});
-        is_first = last_item_result.is_new_entry;
-        last = &last_item_result.stored_value->value;
-      }
-
+      // If this is the first fragment, associate with |layout_object|.
+      const auto last_item_result =
+          last_items.insert(layout_object, LastItem{&item, 0, item_index});
+      const bool is_first = last_item_result.is_new_entry;
       if (is_first) {
         item.SetFragmentId(0);
-        if (create_index_cache) {
+#if DCHECK_IS_ON()
+        if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled())
           DCHECK_EQ(layout_object->FirstInlineFragmentItemIndex(), 0u);
-          layout_object->SetFirstInlineFragmentItemIndex(index);
-        }
+#endif
+        layout_object->SetFirstInlineFragmentItemIndex(item_index);
         continue;
       }
 
+      // Update the last item for |layout_object|.
+      LastItem* last = &last_item_result.stored_value->value;
       const NGFragmentItem* last_item = last->item;
       DCHECK_EQ(last_item->DeltaToNextForSameLayoutObject(), 0u);
-      if (create_index_cache) {
-        const wtf_size_t last_index = last->item_index;
-        DCHECK_GT(last_index, 0u);
-        DCHECK_LT(last_index, items.size());
-        DCHECK_LT(last_index, index);
-        last_item->SetDeltaToNextForSameLayoutObject(index - last_index);
-      }
+      const wtf_size_t last_index = last->item_index;
+      DCHECK_GT(last_index, 0u);
+      DCHECK_LT(last_index, fragment_items->EndItemIndex());
+      DCHECK_LT(last_index, item_index);
+      last_item->SetDeltaToNextForSameLayoutObject(item_index - last_index);
+      if (!layout_object->IsFloating())
+        last_item->SetIsLastForNode(false);
+#if DCHECK_IS_ON()
+      CheckIsLast(*last_item);
+#endif
+
+      // Update this item.
       item.SetFragmentId(++last->fragment_id);
       last->item = &item;
-      last->item_index = index;
+      last->item_index = item_index;
     }
   }
+#if DCHECK_IS_ON()
   for (const auto& iter : last_items)
-    iter.value.item->SetIsLastForNode(true);
+    CheckIsLast(*iter.value.item);
+#endif
 }
 
 void NGFragmentItems::ClearAssociatedFragments(LayoutObject* container) {
@@ -135,6 +171,12 @@
     if (child->IsLayoutInline())
       ClearAssociatedFragments(child);
   }
+#if DCHECK_IS_ON()
+  if (const auto* box = ToLayoutBoxOrNull(container)) {
+    for (const NGPhysicalBoxFragment& fragment : box->PhysicalFragments())
+      CheckNoItemsAreAssociated(fragment);
+  }
+#endif
 }
 
 // static
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
index 55ddaad..a8e65cd 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
@@ -49,10 +49,20 @@
                : text_content_;
   }
 
+  // When block-fragmented, returns the number of |NGFragmentItem| in earlier
+  // fragments for this box. 0 for the first fragment.
+  wtf_size_t SizeOfEarlierFragments() const {
+    return size_of_earlier_fragments_;
+  }
+  wtf_size_t EndItemIndex() const { return size_of_earlier_fragments_ + size_; }
+  bool HasItemIndex(wtf_size_t index) const {
+    return index >= SizeOfEarlierFragments() && index < EndItemIndex();
+  }
+
   // Associate |NGFragmentItem|s with |LayoutObject|s and finalize the items
   // (set which ones are the first / last for the LayoutObject).
   static void FinalizeAfterLayout(
-      const Vector<scoped_refptr<const NGLayoutResult>, 1>&);
+      const Vector<scoped_refptr<const NGLayoutResult>, 1>& results);
 
   // Disassociate |NGFragmentItem|s with |LayoutObject|s. And more.
   static void ClearAssociatedFragments(LayoutObject* container);
@@ -93,6 +103,10 @@
 
   wtf_size_t size_;
 
+  // Total size of |NGFragmentItem| in earlier fragments when block fragmented.
+  // 0 for the first |NGFragmentItems|.
+  mutable wtf_size_t size_of_earlier_fragments_;
+
   // Semantically, |items_| is a flexible array of |scoped_refptr<const
   // NGFragmentItem>|, but |scoped_refptr| has non-trivial destruction which
   // causes an error in clang. Declare as a flexible array of |NGFragmentItem*|
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
index 52f62a8..de108c6 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -1405,12 +1405,6 @@
     MoveToNextFragmentainer();
 }
 
-inline bool NGInlineCursor::CanUseLayoutObjectIndex() const {
-  if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled())
-    return true;
-  return CanMoveAcrossFragmentainer() && max_fragment_index_ == 0;
-}
-
 void NGInlineCursor::SlowMoveToForIfNeeded(const LayoutObject& layout_object) {
   while (Current() && Current().GetLayoutObject() != &layout_object)
     MoveToNextIncludingFragmentainer();
@@ -1490,14 +1484,6 @@
     is_descendants_cursor = IsDescendantsCursor();
   }
 
-  // TODO(crbug.com/829028): |FirstInlineFragmentItemIndex| is not setup when
-  // block fragmented. Use the slow codepath.
-  if (UNLIKELY(!CanUseLayoutObjectIndex())) {
-    layout_object_to_slow_move_to_ = &layout_object;
-    SlowMoveToFirstFor(layout_object);
-    return;
-  }
-
   wtf_size_t item_index = layout_object.FirstInlineFragmentItemIndex();
   if (UNLIKELY(!item_index)) {
 #if DCHECK_IS_ON()
@@ -1512,9 +1498,18 @@
   // |FirstInlineFragmentItemIndex| is 1-based. Convert to 0-based index.
   --item_index;
 
+  // Find |NGFragmentItems| that contains |item_index|.
   DCHECK_EQ(is_descendants_cursor, IsDescendantsCursor());
   if (root_block_flow_) {
     DCHECK(!is_descendants_cursor);
+    while (item_index >= fragment_items_->EndItemIndex()) {
+      MoveToNextFragmentainer();
+      if (!Current()) {
+        NOTREACHED();
+        return;
+      }
+    }
+    item_index -= fragment_items_->SizeOfEarlierFragments();
 #if DCHECK_IS_ON()
     NGInlineCursor check_cursor(*root_block_flow_);
     check_cursor.SlowMoveToFirstFor(layout_object);
@@ -1522,6 +1517,26 @@
               &fragment_items_->Items()[item_index]);
 #endif
   } else {
+    // If |this| is not rooted at |LayoutBlockFlow|, iterate |NGFragmentItems|
+    // from |LayoutBlockFlow|.
+    if (fragment_items_->HasItemIndex(item_index)) {
+      item_index -= fragment_items_->SizeOfEarlierFragments();
+    } else {
+      NGInlineCursor cursor;
+      for (cursor.MoveTo(layout_object);;
+           cursor.MoveToNextForSameLayoutObject()) {
+        if (!cursor || cursor.fragment_items_->SizeOfEarlierFragments() >
+                           fragment_items_->SizeOfEarlierFragments()) {
+          MakeNull();
+          return;
+        }
+        if (cursor.fragment_items_ == fragment_items_) {
+          item_index =
+              cursor.Current().Item() - fragment_items_->Items().data();
+          break;
+        }
+      }
+    }
 #if DCHECK_IS_ON()
     const LayoutBlockFlow* root = layout_object.FragmentItemsContainer();
     NGInlineCursor check_cursor(*root);
@@ -1576,21 +1591,28 @@
     return MakeNull();
   }
   if (current_.item_) {
-    if (UNLIKELY(layout_object_to_slow_move_to_)) {
-      SlowMoveToNextForSameLayoutObject(*layout_object_to_slow_move_to_);
-      return;
-    }
+    if (wtf_size_t delta = current_.item_->DeltaToNextForSameLayoutObject()) {
+      while (true) {
+        // Return if the next index is in the current range.
+        const wtf_size_t delta_to_end = items_.end() - current_.item_iter_;
+        if (delta < delta_to_end) {
+          MoveToItem(current_.item_iter_ + delta);
+          return;
+        }
 
-    const wtf_size_t delta = current_.item_->DeltaToNextForSameLayoutObject();
-    if (delta) {
-      // Check the next item is in |items_| because |delta| can be beyond
-      // |end()| if |this| is limited.
-      const wtf_size_t delta_to_end = items_.end() - current_.item_iter_;
-      if (delta < delta_to_end) {
-        MoveToItem(current_.item_iter_ + delta);
-        return;
+        // |this| is |IsDescendantsCursor| and the next item is out of the
+        // specified range, or the next item is in following fragmentainers.
+        if (!CanMoveAcrossFragmentainer())
+          break;
+
+        MoveToNextFragmentainer();
+        if (!Current()) {
+          NOTREACHED();
+          break;
+        }
+        DCHECK_GE(delta, delta_to_end);
+        delta -= delta_to_end;
       }
-      DCHECK(IsDescendantsCursor());
     }
     MakeNull();
   }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
index 0bef2435..e7c3bd24 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -476,7 +476,6 @@
   bool CanMoveAcrossFragmentainer() const {
     return root_block_flow_ && IsItemCursor() && !IsDescendantsCursor();
   }
-  bool CanUseLayoutObjectIndex() const;
 
   // True if the current position is a last line in inline block. It is error
   // to call at end or the current position is not line.
@@ -560,9 +559,6 @@
   wtf_size_t fragment_index_ = 0;
   wtf_size_t max_fragment_index_ = 0;
 
-  // Used only when |!CanUseLayoutObjectIndex|.
-  const LayoutObject* layout_object_to_slow_move_to_ = nullptr;
-
   friend class NGInlineBackwardCursor;
 };
 
diff --git a/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc b/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
index 23ef6e5..0575898 100644
--- a/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
+++ b/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
@@ -14,6 +14,17 @@
 
 namespace blink {
 
+namespace {
+
+inline PaintLayerScrollableArea* GetScrollableArea(
+    const LayoutBlock* container) {
+  return To<Element>(container->GetNode())
+      ->GetLayoutBoxForScrolling()
+      ->GetScrollableArea();
+}
+
+}  // namespace
+
 class VisualRectMappingTest : public PaintTestConfigurations,
                               public RenderingTest {
  public:
@@ -117,8 +128,7 @@
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
   auto* text = GetLayoutObjectByElementId("text")->SlowFirstChild();
 
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   scrollable_area->ScrollToAbsolutePosition(
       FloatPoint(scrollable_area->ScrollPosition().X(), 50));
   UpdateAllLifecyclePhasesForTest();
@@ -157,8 +167,7 @@
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
   auto* text = GetLayoutObjectByElementId("text")->SlowFirstChild();
 
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   scrollable_area->ScrollToAbsolutePosition(
       FloatPoint(scrollable_area->ScrollPosition().X(), 50));
   UpdateAllLifecyclePhasesForTest();
@@ -195,8 +204,7 @@
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
   LayoutObject* leaf = container->LastChild();
 
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   scrollable_area->ScrollToAbsolutePosition(
       FloatPoint(scrollable_area->ScrollPosition().X(), 50));
   UpdateAllLifecyclePhasesForTest();
@@ -235,8 +243,7 @@
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
   LayoutObject* leaf = container->LastChild();
 
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   scrollable_area->ScrollToAbsolutePosition(
       FloatPoint(scrollable_area->ScrollPosition().X(), 50));
   UpdateAllLifecyclePhasesForTest();
@@ -452,8 +459,7 @@
   )HTML");
 
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   EXPECT_EQ(0, scrollable_area->ScrollPosition().Y());
   EXPECT_EQ(0, scrollable_area->ScrollPosition().X());
   scrollable_area->ScrollToAbsolutePosition(FloatPoint(8, 7));
@@ -511,8 +517,7 @@
   )HTML");
 
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   EXPECT_EQ(0, scrollable_area->ScrollPosition().Y());
   // The initial scroll offset is to the left-most because of flipped blocks
   // writing mode.
@@ -584,8 +589,7 @@
   )HTML");
 
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   EXPECT_EQ(0, scrollable_area->ScrollPosition().Y());
   EXPECT_EQ(0, scrollable_area->ScrollPosition().X());
   scrollable_area->ScrollToAbsolutePosition(FloatPoint(28, 27));
@@ -618,8 +622,7 @@
   )HTML");
 
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   EXPECT_EQ(0, scrollable_area->ScrollPosition().Y());
   // The initial scroll offset is to the left-most because of flipped blocks
   // writing mode.
@@ -658,8 +661,7 @@
   )HTML");
 
   auto* container = To<LayoutBlock>(GetLayoutObjectByElementId("container"));
-  auto* scrollable_area =
-      To<Element>(container->GetNode())->GetScrollableArea();
+  auto* scrollable_area = GetScrollableArea(container);
   EXPECT_EQ(0, scrollable_area->ScrollPosition().Y());
   // The initial scroll offset is to the left-most because of flipped blocks
   // writing mode.
@@ -717,9 +719,7 @@
   )HTML");
 
   auto* scroller = To<LayoutBlock>(GetLayoutObjectByElementId("scroller"));
-  To<Element>(scroller->GetNode())
-      ->GetScrollableArea()
-      ->ScrollToAbsolutePosition(FloatPoint(88, 77));
+  GetScrollableArea(scroller)->ScrollToAbsolutePosition(FloatPoint(88, 77));
   UpdateAllLifecyclePhasesForTest();
 
   auto* normal_flow =
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc
index 0a28200..61ecb72 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/loader/base_fetch_context.h"
 
 #include "services/network/public/cpp/request_mode.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -276,6 +277,27 @@
   return base::nullopt;
 }
 
+void BaseFetchContext::AddBackForwardCacheExperimentHTTPHeaderIfNeeded(
+    ExecutionContext* context,
+    ResourceRequest& request) {
+  if (!RuntimeEnabledFeatures::BackForwardCacheExperimentHTTPHeaderEnabled(
+          context)) {
+    return;
+  }
+  if (!base::FeatureList::IsEnabled(
+          blink::features::kBackForwardCacheABExperimentControl)) {
+    return;
+  }
+  // Send the 'Sec-bfcache-experiment' HTTP header to indicate which
+  // BackForwardCacheSameSite experiment group we're in currently.
+  UseCounter::Count(context, WebFeature::kBackForwardCacheExperimentHTTPHeader);
+  auto experiment_group = base::GetFieldTrialParamValueByFeature(
+      features::kBackForwardCacheABExperimentControl,
+      features::kBackForwardCacheABExperimentGroup);
+  request.SetHttpHeaderField("Sec-bfcache-experiment",
+                             experiment_group.c_str());
+}
+
 void BaseFetchContext::Trace(Visitor* visitor) const {
   visitor->Trace(fetcher_properties_);
   FetchContext::Trace(visitor);
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h
index 9017055..5e723b26 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -117,6 +117,10 @@
   // TODO(yhirano): Remove this.
   virtual void AddConsoleMessage(ConsoleMessage*) const = 0;
 
+  void AddBackForwardCacheExperimentHTTPHeaderIfNeeded(
+      ExecutionContext* context,
+      ResourceRequest& request);
+
  private:
   const Member<const DetachableResourceFetcherProperties> fetcher_properties_;
 
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 68347031..dc7af6f5 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -327,6 +327,9 @@
 
   if (save_data_enabled_)
     request.SetHttpHeaderField(http_names::kSaveData, "on");
+
+  AddBackForwardCacheExperimentHTTPHeaderIfNeeded(
+      document_->GetExecutionContext(), request);
 }
 
 // TODO(toyoshim, arthursonzogni): PlzNavigate doesn't use this function to set
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index accc93ef..1448479 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -1372,4 +1372,69 @@
   EXPECT_EQ(origin, GetTopFrameOrigin());
 }
 
+// Verify the value of the sec-bfcache-experiment HTTP header varies according
+// to whether BackForwardCacheExperimentHTTPHeader and BackForwardCacheSameSite
+// is enabled or not.
+TEST_F(FrameFetchContextTest, SameSiteBackForwardCache) {
+  base::FieldTrialParams params;
+
+  {
+    RuntimeEnabledFeatures::SetBackForwardCacheExperimentHTTPHeaderEnabled(
+        false);
+    params[features::kBackForwardCacheABExperimentGroup] = "foo";
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kBackForwardCacheABExperimentControl, params);
+
+    ResourceRequest resource_request("http://www.example.com");
+    GetFetchContext()->AddAdditionalRequestHeaders(resource_request);
+
+    // BackForwardCacheExperimentHTTPHeader is not enabled and
+    // BackForwardCacheSameSite's experiment group is "foo".
+    EXPECT_EQ(String(),
+              resource_request.HttpHeaderField("Sec-bfcache-experiment"));
+  }
+
+  {
+    RuntimeEnabledFeatures::SetBackForwardCacheExperimentHTTPHeaderEnabled(
+        true);
+    ResourceRequest resource_request("http://www.example.com");
+    GetFetchContext()->AddAdditionalRequestHeaders(resource_request);
+
+    // BackForwardCacheExperimentHTTPHeader is enabled and
+    // BackForwardCacheSameSite's experiment group is not set.
+    EXPECT_EQ(String(),
+              resource_request.HttpHeaderField("Sec-bfcache-experiment"));
+  }
+
+  {
+    params[features::kBackForwardCacheABExperimentGroup] = "control";
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kBackForwardCacheABExperimentControl, params);
+
+    ResourceRequest resource_request("http://www.example.com");
+    GetFetchContext()->AddAdditionalRequestHeaders(resource_request);
+
+    // BackForwardCacheExperimentHTTPHeader is enabled and
+    // BackForwardCacheSameSite's experiment group is "control".
+    EXPECT_EQ("control",
+              resource_request.HttpHeaderField("Sec-bfcache-experiment"));
+  }
+
+  {
+    params[features::kBackForwardCacheABExperimentGroup] = "enabled";
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kBackForwardCacheABExperimentControl, params);
+    ResourceRequest resource_request("http://www.example.com");
+    GetFetchContext()->AddAdditionalRequestHeaders(resource_request);
+
+    // BackForwardCacheExperimentHTTPHeader is enabled and
+    // BackForwardCacheSameSite experiment group is "enabled".
+    EXPECT_EQ("enabled",
+              resource_request.HttpHeaderField("Sec-bfcache-experiment"));
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index 169a7d6..3c817da 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -226,6 +226,8 @@
 
   if (save_data_enabled_)
     request.SetHttpHeaderField(http_names::kSaveData, "on");
+
+  AddBackForwardCacheExperimentHTTPHeaderIfNeeded(global_scope_, request);
 }
 
 void WorkerFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
index 15e0d4b..1572481 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -115,6 +115,15 @@
     return helper_.GetWebWidgetClient();
   }
 
+  PaintLayerScrollableArea* ScrollableAreaByDOMElementId(
+      const char* id_value) const {
+    return GetFrame()
+        ->GetDocument()
+        ->getElementById(id_value)
+        ->GetLayoutBoxForScrolling()
+        ->GetScrollableArea();
+  }
+
   void LoadAhem() { helper_.LoadAhem(); }
 
   const cc::ScrollNode* ScrollNodeForScrollableArea(
@@ -129,8 +138,7 @@
   }
 
   const cc::ScrollNode* ScrollNodeByDOMElementId(const char* dom_id) const {
-    return ScrollNodeForScrollableArea(
-        GetFrame()->GetDocument()->getElementById(dom_id)->GetScrollableArea());
+    return ScrollNodeForScrollableArea(ScrollableAreaByDOMElementId(dom_id));
   }
 
   gfx::ScrollOffset CurrentScrollOffset(cc::ElementId element_id) const {
@@ -175,10 +183,7 @@
 
   const cc::Layer* ScrollingContentsLayerByDOMElementId(
       const char* element_id) const {
-    const auto* scrollable_area = GetFrame()
-                                      ->GetDocument()
-                                      ->getElementById(element_id)
-                                      ->GetScrollableArea();
+    const auto* scrollable_area = ScrollableAreaByDOMElementId(element_id);
     return ScrollingContentsCcLayerByScrollElementId(
         RootCcLayer(), scrollable_area->GetScrollElementId());
   }
@@ -1364,10 +1369,7 @@
       )HTML");
   ForceFullCompositingUpdate();
 
-  auto* scrollable_area = GetFrame()
-                              ->GetDocument()
-                              ->getElementById("container")
-                              ->GetScrollableArea();
+  auto* scrollable_area = ScrollableAreaByDOMElementId("container");
   ASSERT_EQ(0, scrollable_area->GetScrollOffset().Height());
   const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
 
@@ -1631,9 +1633,9 @@
 
   ForceFullCompositingUpdate();
 
-  auto* scroller = GetFrame()->GetDocument()->getElementById("scroller");
-  scroller->GetScrollableArea()->SetScrollOffset(
-      ScrollOffset(0, 5100), mojom::blink::ScrollType::kProgrammatic);
+  ScrollableAreaByDOMElementId("scroller")
+      ->SetScrollOffset(ScrollOffset(0, 5100),
+                        mojom::blink::ScrollType::kProgrammatic);
 
   ForceFullCompositingUpdate();
 
@@ -1705,6 +1707,15 @@
             scrollable_area->GetScrollElementId()));
   }
 
+  PaintLayerScrollableArea* ScrollableAreaByDOMElementId(const char* id_value) {
+    auto* box = MainFrame()
+                    .GetFrame()
+                    ->GetDocument()
+                    ->getElementById(id_value)
+                    ->GetLayoutBoxForScrolling();
+    return box ? box->GetScrollableArea() : nullptr;
+  }
+
  protected:
   RuntimeEnabledFeaturesTestHelpers::ScopedScrollUnification
       scroll_unification_enabled_;
@@ -1745,7 +1756,8 @@
 
   Element* noncomposited_element =
       MainFrame().GetFrame()->GetDocument()->getElementById("noncomposited");
-  auto* scrollable_area = noncomposited_element->GetScrollableArea();
+  auto* scrollable_area =
+      noncomposited_element->GetLayoutBoxForScrolling()->GetScrollableArea();
   ASSERT_EQ(
       cc::MainThreadScrollingReason::kCantPaintScrollingBackgroundAndLCDText,
       scrollable_area->GetNonCompositedMainThreadScrollingReasons());
@@ -1804,7 +1816,8 @@
 
   Element* composited_element =
       MainFrame().GetFrame()->GetDocument()->getElementById("composited");
-  auto* scrollable_area = composited_element->GetScrollableArea();
+  auto* scrollable_area =
+      composited_element->GetLayoutBoxForScrolling()->GetScrollableArea();
   EXPECT_EQ(0u, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
 
   const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
@@ -1900,6 +1913,7 @@
   // Ensure we have a compositor scroll node for the noncomposited subscroller.
   auto* child_scrollable_area = iframe->contentDocument()
                                     ->getElementById("scroller")
+                                    ->GetLayoutBoxForScrolling()
                                     ->GetScrollableArea();
   const auto* child_scroll_node =
       ScrollNodeForScrollableArea(child_scrollable_area);
@@ -1984,6 +1998,7 @@
   // nested in the second iframe.
   auto* child_scrollable_area = child_iframe_2->contentDocument()
                                     ->getElementById("scroller")
+                                    ->GetLayoutBoxForScrolling()
                                     ->GetScrollableArea();
   const auto* child_scroll_node =
       ScrollNodeForScrollableArea(child_scrollable_area);
@@ -2043,11 +2058,7 @@
   Compositor().BeginFrame();
 
   // Ensure the opacity 0 noncomposited scrollable area generates a scroll node
-  auto* invisible_scrollable_area = MainFrame()
-                                        .GetFrame()
-                                        ->GetDocument()
-                                        ->getElementById("invisible")
-                                        ->GetScrollableArea();
+  auto* invisible_scrollable_area = ScrollableAreaByDOMElementId("invisible");
   ASSERT_EQ(
       cc::MainThreadScrollingReason::kCantPaintScrollingBackgroundAndLCDText,
       invisible_scrollable_area->GetNonCompositedMainThreadScrollingReasons());
@@ -2066,11 +2077,7 @@
 
   // Ensure there's no scrollable area (and therefore no scroll node) for a
   // display none scroller.
-  EXPECT_EQ(nullptr, MainFrame()
-                         .GetFrame()
-                         ->GetDocument()
-                         ->getElementById("displaynone")
-                         ->GetScrollableArea());
+  EXPECT_EQ(nullptr, ScrollableAreaByDOMElementId("displaynone"));
 }
 
 // Tests that the compositor gets a scroll node for scrollable input boxes,
@@ -2090,9 +2097,7 @@
   )HTML");
   Compositor().BeginFrame();
 
-  Element* input_element =
-      MainFrame().GetFrame()->GetDocument()->getElementById("textinput");
-  auto* scrollable_area = input_element->GetScrollableArea();
+  auto* scrollable_area = ScrollableAreaByDOMElementId("textinput");
   ASSERT_EQ(0u, scrollable_area->GetNonCompositedMainThreadScrollingReasons());
 
   const auto* scroll_node = ScrollNodeForScrollableArea(scrollable_area);
diff --git a/third_party/blink/renderer/core/page/spatial_navigation.cc b/third_party/blink/renderer/core/page/spatial_navigation.cc
index f93dedf..c8f823d 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation.cc
@@ -282,7 +282,10 @@
     case SpatialNavigationDirection::kRight:
       // TODO(bokan, https://crbug.com/952326): Fix this DCHECK.
       //  DCHECK_GT(container->GetLayoutBox()->ScrollWidth(),
-      //            container->GetScrollableArea()->ScrollPosition().X() +
+      //            container->GetLayoutBoxForScrolling()
+      //                    ->GetScrollableArea()
+      //                    ->ScrollPosition()
+      //                    .X() +
       //                container->GetLayoutBox()->ClientWidth());
       dx = pixels_per_line_step;
       break;
@@ -292,7 +295,10 @@
     case SpatialNavigationDirection::kDown:
       // TODO(bokan, https://crbug.com/952326): Fix this DCHECK.
       //  DCHECK_GT(container->GetLayoutBox()->ScrollHeight(),
-      //            container->GetScrollableArea()->ScrollPosition().Y() +
+      //            container->GetLayoutBoxForScrolling()
+      //                    ->GetScrollableArea()
+      //                    ->ScrollPosition()
+      //                    .Y() +
       //                container->GetLayoutBox()->ClientHeight());
       dy = pixels_per_line_step;
       break;
@@ -364,7 +370,10 @@
   const Element* container_element = DynamicTo<Element>(container);
   if (!container_element)
     return false;
-  auto* scrollable_area = container_element->GetScrollableArea();
+  LayoutBox* box = container_element->GetLayoutBoxForScrolling();
+  if (!box)
+    return false;
+  auto* scrollable_area = box->GetScrollableArea();
   if (!scrollable_area)
     return false;
 
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 5d3b52e..43fce1e5 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -136,6 +136,7 @@
     "//third_party/blink/renderer/modules/presentation",
     "//third_party/blink/renderer/modules/push_messaging",
     "//third_party/blink/renderer/modules/quota",
+    "//third_party/blink/renderer/modules/direct_sockets",
     "//third_party/blink/renderer/modules/remoteplayback",
     "//third_party/blink/renderer/modules/sanitizer_api",
     "//third_party/blink/renderer/modules/scheduler",
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
index 45fc07b..ff4c8a84 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
+++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
@@ -50,10 +50,6 @@
 
   payments::mojom::blink::PaymentCredential* PaymentCredential();
 
-  void FlushCredentialManagerConnectionForTesting() {
-    credential_manager_.FlushForTesting();
-  }
-
   void Trace(Visitor*) const override;
 
   // Must be called only with argument representing a valid
@@ -61,18 +57,10 @@
   static CredentialManagerProxy* From(ScriptState*);
 
  private:
-  HeapMojoRemote<mojom::blink::Authenticator,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      authenticator_;
-  HeapMojoRemote<mojom::blink::CredentialManager,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      credential_manager_;
-  HeapMojoRemote<mojom::blink::SmsReceiver,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      sms_receiver_;
-  HeapMojoRemote<payments::mojom::blink::PaymentCredential,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      payment_credential_;
+  HeapMojoRemote<mojom::blink::Authenticator> authenticator_;
+  HeapMojoRemote<mojom::blink::CredentialManager> credential_manager_;
+  HeapMojoRemote<mojom::blink::SmsReceiver> sms_receiver_;
+  HeapMojoRemote<payments::mojom::blink::PaymentCredential> payment_credential_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
index b747bf3..a77304e72 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
@@ -171,7 +171,6 @@
   MockCredentialManager mock_credential_manager;
   CredentialManagerTestingContext context(&mock_credential_manager);
 
-  auto* proxy = CredentialManagerProxy::From(context.GetScriptState());
   auto promise = MakeGarbageCollected<CredentialsContainer>()->get(
       context.GetScriptState(), CredentialRequestOptions::Create());
   mock_credential_manager.WaitForCallToGet();
@@ -179,7 +178,6 @@
   context.Frame()->DomWindow()->FrameDestroyed();
 
   mock_credential_manager.InvokeGetCallback();
-  proxy->FlushCredentialManagerConnectionForTesting();
 
   EXPECT_EQ(v8::Promise::kPending,
             promise.V8Value().As<v8::Promise>()->State());
diff --git a/third_party/blink/renderer/modules/direct_sockets/BUILD.gn b/third_party/blink/renderer/modules/direct_sockets/BUILD.gn
new file mode 100644
index 0000000..d02d224
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/BUILD.gn
@@ -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.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("direct_sockets") {
+  sources = [
+    "navigator_socket.cc",
+    "navigator_socket.h",
+  ]
+}
diff --git a/third_party/blink/renderer/modules/direct_sockets/OWNERS b/third_party/blink/renderer/modules/direct_sockets/OWNERS
new file mode 100644
index 0000000..39333436
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/OWNERS
@@ -0,0 +1,5 @@
+ericwilligers@chromium.org
+glenrob@chromium.org
+mgiuca@chromium.org
+
+# COMPONENT: Blink>Network
diff --git a/third_party/blink/renderer/modules/direct_sockets/README.md b/third_party/blink/renderer/modules/direct_sockets/README.md
new file mode 100644
index 0000000..72a9447
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/README.md
@@ -0,0 +1,6 @@
+This directory implements the Blink side of the [Direct Sockets
+API](https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md).
+
+It will connect to a DirectSocketsService Mojo service in the browser,
+which performs security checks, provides dialogs, and forwards requests to
+the Network service.
diff --git a/third_party/blink/renderer/modules/direct_sockets/idls.gni b/third_party/blink/renderer/modules/direct_sockets/idls.gni
new file mode 100644
index 0000000..763253e
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/idls.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.
+
+modules_dictionary_idl_files = [ "socket_options.idl" ]
+
+modules_dependency_idl_files = [ "navigator_socket.idl" ]
diff --git a/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc
new file mode 100644
index 0000000..aeaa896e
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.cc
@@ -0,0 +1,258 @@
+// 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 "third_party/blink/renderer/modules/direct_sockets/navigator_socket.h"
+
+#include "base/macros.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/modules/direct_sockets/socket_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+class NavigatorSocket::PendingRequest final
+    : public GarbageCollected<PendingRequest> {
+ public:
+  PendingRequest(NavigatorSocket&, ScriptPromiseResolver&);
+
+  // TODO(crbug.com/905818): Resolve Promise<TCPSocket>
+  void TcpCallback(int32_t result);
+
+  // TODO(crbug.com/1119620): Resolve Promise<UDPSocket>
+  void UdpCallback(int32_t result);
+
+  void OnConnectionError();
+
+  void Trace(Visitor* visitor) const {
+    visitor->Trace(navigator_);
+    visitor->Trace(resolver_);
+  }
+
+ private:
+  WeakMember<NavigatorSocket> navigator_;
+  Member<ScriptPromiseResolver> resolver_;
+  FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
+      feature_handle_for_scheduler_;
+};
+
+NavigatorSocket::PendingRequest::PendingRequest(
+    NavigatorSocket& navigator_socket,
+    ScriptPromiseResolver& resolver)
+    : navigator_(&navigator_socket),
+      resolver_(&resolver),
+      feature_handle_for_scheduler_(
+          ExecutionContext::From(resolver_->GetScriptState())
+              ->GetScheduler()
+              ->RegisterFeature(
+                  SchedulingPolicy::Feature::
+                      kOutstandingNetworkRequestDirectSocket,
+                  {SchedulingPolicy::RecordMetricsForBackForwardCache()})) {}
+
+void NavigatorSocket::PendingRequest::TcpCallback(int32_t result) {
+  if (navigator_)
+    navigator_->pending_requests_.erase(this);
+
+  // TODO(crbug.com/905818): Compare with net::OK
+  if (result == 0) {
+    // TODO(crbug.com/905818): Resolve TCPSocket
+    NOTIMPLEMENTED();
+    resolver_->Resolve();
+  } else {
+    resolver_->Reject(MakeGarbageCollected<DOMException>(
+        DOMExceptionCode::kNotAllowedError, "Permission denied"));
+  }
+}
+
+void NavigatorSocket::PendingRequest::UdpCallback(int32_t result) {
+  if (navigator_)
+    navigator_->pending_requests_.erase(this);
+
+  // TODO(crbug.com/1119620): Compare with net::OK
+  if (result == 0) {
+    // TODO(crbug.com/1119620): Resolve UDPSocket
+    NOTIMPLEMENTED();
+    resolver_->Resolve();
+  } else {
+    resolver_->Reject(MakeGarbageCollected<DOMException>(
+        DOMExceptionCode::kNotAllowedError, "Permission denied"));
+  }
+}
+
+void NavigatorSocket::PendingRequest::OnConnectionError() {
+  resolver_->Reject(MakeGarbageCollected<DOMException>(
+      DOMExceptionCode::kAbortError,
+      "Internal error: could not connect to DirectSocketsService interface."));
+}
+
+const char NavigatorSocket::kSupplementName[] = "NavigatorSocket";
+
+NavigatorSocket::NavigatorSocket(ExecutionContext* context)
+    : ExecutionContextLifecycleStateObserver(context) {}
+
+// static
+NavigatorSocket& NavigatorSocket::From(ScriptState* script_state) {
+  ExecutionContext* context = ExecutionContext::From(script_state);
+  NavigatorSocket* supplement =
+      Supplement<ExecutionContext>::From<NavigatorSocket>(context);
+  if (!supplement) {
+    supplement = MakeGarbageCollected<NavigatorSocket>(context);
+    ProvideTo(*context, supplement);
+  }
+  return *supplement;
+}
+
+// static
+ScriptPromise NavigatorSocket::openTCPSocket(ScriptState* script_state,
+                                             Navigator& navigator,
+                                             const SocketOptions* options,
+                                             ExceptionState& exception_state) {
+  return From(script_state)
+      .openTCPSocket(script_state, options, exception_state);
+}
+
+// static
+ScriptPromise NavigatorSocket::openUDPSocket(ScriptState* script_state,
+                                             Navigator& navigator,
+                                             const SocketOptions* options,
+                                             ExceptionState& exception_state) {
+  return From(script_state)
+      .openUDPSocket(script_state, options, exception_state);
+}
+
+void NavigatorSocket::ContextDestroyed() {}
+
+void NavigatorSocket::ContextLifecycleStateChanged(
+    mojom::blink::FrameLifecycleState state) {
+  // TODO(crbug.com/1120868) close connections when the lifecycle state is not
+  // "active".
+  NOTIMPLEMENTED();
+}
+
+void NavigatorSocket::Trace(Visitor* visitor) const {
+  visitor->Trace(service_remote_);
+  visitor->Trace(pending_requests_);
+  Supplement<ExecutionContext>::Trace(visitor);
+  ExecutionContextLifecycleStateObserver::Trace(visitor);
+}
+
+void NavigatorSocket::EnsureServiceConnected(LocalDOMWindow& window) {
+  DCHECK(RuntimeEnabledFeatures::DirectSocketsEnabled());
+
+  if (!service_remote_.is_bound()) {
+    window.GetFrame()->GetBrowserInterfaceBroker().GetInterface(
+        service_remote_.BindNewPipeAndPassReceiver(
+            window.GetTaskRunner(TaskType::kMiscPlatformAPI)));
+    service_remote_.set_disconnect_handler(WTF::Bind(
+        &NavigatorSocket::OnConnectionError, WrapWeakPersistent(this)));
+    DCHECK(service_remote_.is_bound());
+  }
+}
+
+// static
+mojom::blink::DirectSocketOptionsPtr NavigatorSocket::CreateSocketOptions(
+    const SocketOptions& options) {
+  auto socket_options = mojom::blink::DirectSocketOptions::New();
+
+  if (options.hasLocalAddress())
+    socket_options->local_hostname = options.localAddress();
+  if (options.hasLocalPort())
+    socket_options->local_port = options.localPort();
+
+  if (options.hasRemoteAddress())
+    socket_options->remote_hostname = options.remoteAddress();
+  if (options.hasRemotePort())
+    socket_options->remote_port = options.remotePort();
+
+  if (options.hasSendBufferSize())
+    socket_options->send_buffer_size = options.sendBufferSize();
+  if (options.hasReceiveBufferSize())
+    socket_options->receive_buffer_size = options.receiveBufferSize();
+
+  if (options.hasKeepAlive())
+    socket_options->keep_alive = options.keepAlive();
+  if (options.hasNoDelay())
+    socket_options->no_delay = options.noDelay();
+
+  return socket_options;
+}
+
+ScriptPromise NavigatorSocket::openTCPSocket(ScriptState* script_state,
+                                             const SocketOptions* options,
+                                             ExceptionState& exception_state) {
+  if (!OpenSocketPermitted(script_state, options, exception_state))
+    return ScriptPromise();
+
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  PendingRequest* pending =
+      MakeGarbageCollected<PendingRequest>(*this, *resolver);
+  pending_requests_.insert(pending);
+  ScriptPromise promise = resolver->Promise();
+
+  service_remote_->OpenTcpSocket(
+      CreateSocketOptions(*options),
+      WTF::Bind(&PendingRequest::TcpCallback, WrapPersistent(pending)));
+  return promise;
+}
+
+ScriptPromise NavigatorSocket::openUDPSocket(ScriptState* script_state,
+                                             const SocketOptions* options,
+                                             ExceptionState& exception_state) {
+  if (!OpenSocketPermitted(script_state, options, exception_state))
+    return ScriptPromise();
+
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  PendingRequest* pending =
+      MakeGarbageCollected<PendingRequest>(*this, *resolver);
+  pending_requests_.insert(pending);
+  ScriptPromise promise = resolver->Promise();
+
+  service_remote_->OpenUdpSocket(
+      CreateSocketOptions(*options),
+      WTF::Bind(&PendingRequest::UdpCallback, WrapPersistent(pending)));
+  return promise;
+}
+
+bool NavigatorSocket::OpenSocketPermitted(ScriptState* script_state,
+                                          const SocketOptions* options,
+                                          ExceptionState& exception_state) {
+  LocalDOMWindow* const window = script_state->ContextIsValid()
+                                     ? LocalDOMWindow::From(script_state)
+                                     : nullptr;
+  if (!window) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                      "Current frame is detached.");
+    return false;
+  }
+
+  DCHECK(options);
+  if (!options->hasRemotePort()) {
+    exception_state.ThrowTypeError("remotePort was not specified.");
+    return false;
+  }
+
+  EnsureServiceConnected(*window);
+  return true;
+}
+
+void NavigatorSocket::OnConnectionError() {
+  for (auto& pending : pending_requests_) {
+    pending->OnConnectionError();
+  }
+  pending_requests_.clear();
+  service_remote_.reset();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/direct_sockets/navigator_socket.h b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.h
new file mode 100644
index 0000000..ba618f5
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.h
@@ -0,0 +1,91 @@
+// 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_MODULES_DIRECT_SOCKETS_NAVIGATOR_SOCKET_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DIRECT_SOCKETS_NAVIGATOR_SOCKET_H_
+
+#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class ExceptionState;
+class LocalDOMWindow;
+class Navigator;
+class ScriptState;
+class SocketOptions;
+
+class MODULES_EXPORT NavigatorSocket final
+    : public GarbageCollected<NavigatorSocket>,
+      public Supplement<ExecutionContext>,
+      public ExecutionContextLifecycleStateObserver {
+ public:
+  static const char kSupplementName[];
+
+  explicit NavigatorSocket(ExecutionContext*);
+  ~NavigatorSocket() override = default;
+
+  NavigatorSocket(const NavigatorSocket&) = delete;
+  NavigatorSocket& operator=(const NavigatorSocket&) = delete;
+
+  // Gets, or creates, NavigatorSocket supplement on ExecutionContext.
+  // See platform/Supplementable.h
+  static NavigatorSocket& From(ScriptState*);
+
+  // Navigator partial interface
+  static ScriptPromise openTCPSocket(ScriptState*,
+                                     Navigator&,
+                                     const SocketOptions*,
+                                     ExceptionState&);
+
+  static ScriptPromise openUDPSocket(ScriptState*,
+                                     Navigator&,
+                                     const SocketOptions*,
+                                     ExceptionState&);
+
+  // ExecutionContextLifecycleStateObserver:
+  void ContextDestroyed() override;
+  void ContextLifecycleStateChanged(mojom::blink::FrameLifecycleState) override;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  class PendingRequest;
+
+  // Binds service_remote_ if not already bound.
+  void EnsureServiceConnected(LocalDOMWindow&);
+
+  static mojom::blink::DirectSocketOptionsPtr CreateSocketOptions(
+      const SocketOptions&);
+
+  ScriptPromise openTCPSocket(ScriptState*,
+                              const SocketOptions*,
+                              ExceptionState&);
+
+  ScriptPromise openUDPSocket(ScriptState*,
+                              const SocketOptions*,
+                              ExceptionState&);
+
+  // Updates exception state whenever returning false.
+  bool OpenSocketPermitted(ScriptState*, const SocketOptions*, ExceptionState&);
+
+  void OnConnectionError();
+
+  HeapMojoRemote<blink::mojom::blink::DirectSocketsService> service_remote_{
+      nullptr};
+
+  HeapHashSet<Member<PendingRequest>> pending_requests_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_DIRECT_SOCKETS_NAVIGATOR_SOCKET_H_
diff --git a/third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl
new file mode 100644
index 0000000..36b4397
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl
@@ -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.
+
+// https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md#tcp
+// https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md#udp
+
+[
+  ImplementedAs=NavigatorSocket,
+  RuntimeEnabled=DirectSockets
+] partial interface Navigator {
+  // TODO(crbug.com/1119681): Add Measure annotation to each method.
+
+  // TODO(crbug.com/905818): Return Promise<TCPSocket>
+  [SecureContext, RaisesException, CallWith=ScriptState]
+  Promise<void> openTCPSocket(optional SocketOptions options = {});
+
+  // TODO(crbug.com/1119620): Return Promise<UDPSocket>
+  [SecureContext, RaisesException, CallWith=ScriptState]
+  Promise<void> openUDPSocket(optional SocketOptions options = {});
+};
diff --git a/third_party/blink/renderer/modules/direct_sockets/socket_options.idl b/third_party/blink/renderer/modules/direct_sockets/socket_options.idl
new file mode 100644
index 0000000..646b3cd
--- /dev/null
+++ b/third_party/blink/renderer/modules/direct_sockets/socket_options.idl
@@ -0,0 +1,20 @@
+// 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/WICG/raw-sockets/blob/master/docs/explainer.md#tcp
+
+dictionary SocketOptions {
+  DOMString localAddress;
+  unsigned short localPort;
+
+  DOMString remoteAddress;
+  unsigned short remotePort;
+
+  unsigned long sendBufferSize;
+  unsigned long receiveBufferSize;
+
+  // These are only relevant for TCP:
+  boolean keepAlive;
+  boolean noDelay;
+};
diff --git a/third_party/blink/renderer/modules/media/audio/mojo_audio_output_ipc_test.cc b/third_party/blink/renderer/modules/media/audio/mojo_audio_output_ipc_test.cc
index 653aff4..97e90787 100644
--- a/third_party/blink/renderer/modules/media/audio/mojo_audio_output_ipc_test.cc
+++ b/third_party/blink/renderer/modules/media/audio/mojo_audio_output_ipc_test.cc
@@ -22,7 +22,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 using testing::_;
@@ -224,8 +223,6 @@
 }  // namespace
 
 TEST(MojoAudioOutputIPC, AuthorizeWithoutFactory_CallsAuthorizedWithError) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   StrictMock<MockDelegate> delegate;
 
@@ -247,8 +244,6 @@
 
 TEST(MojoAudioOutputIPC,
      CreateWithoutAuthorizationWithoutFactory_CallsAuthorizedWithError) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   StrictMock<MockDelegate> delegate;
 
   std::unique_ptr<media::AudioOutputIPC> ipc =
@@ -265,8 +260,6 @@
 }
 
 TEST(MojoAudioOutputIPC, DeviceAuthorized_Propagates) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockDelegate> delegate;
@@ -290,8 +283,6 @@
 }
 
 TEST(MojoAudioOutputIPC, OnDeviceCreated_Propagates) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockStream> stream;
@@ -319,8 +310,6 @@
 
 TEST(MojoAudioOutputIPC,
      CreateWithoutAuthorization_RequestsAuthorizationFirst) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   StrictMock<MockStream> stream;
   StrictMock<MockDelegate> delegate;
@@ -348,8 +337,6 @@
 }
 
 TEST(MojoAudioOutputIPC, IsReusable) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockStream> stream;
@@ -381,8 +368,6 @@
 }
 
 TEST(MojoAudioOutputIPC, IsReusableAfterError) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockStream> stream;
@@ -436,8 +421,6 @@
 }
 
 TEST(MojoAudioOutputIPC, DeviceNotAuthorized_Propagates) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockDelegate> delegate;
@@ -469,8 +452,6 @@
   // The authorization IPC message might be aborted by the remote end
   // disconnecting. In this case, the MojoAudioOutputIPC object must still
   // send a notification to unblock the AudioOutputIPCDelegate.
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   StrictMock<MockDelegate> delegate;
@@ -501,8 +482,6 @@
   // This test makes sure that the MojoAudioOutputIPC doesn't callback for
   // authorization when the factory disconnects if it already got a callback
   // for authorization.
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   TestRemoteFactory stream_factory;
   stream_factory.PrepareProviderForAuthorization(
@@ -529,8 +508,6 @@
 }
 
 TEST(MojoAudioOutputIPC, AuthorizeNoClose_DCHECKs) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   StrictMock<MockDelegate> delegate;
@@ -551,8 +528,6 @@
 }
 
 TEST(MojoAudioOutputIPC, CreateNoClose_DCHECKs) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   StrictMock<MockDelegate> delegate;
   StrictMock<MockStream> stream;
@@ -575,8 +550,6 @@
 }
 
 TEST(MojoAudioOutputIPC, Play_Plays) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   StrictMock<MockStream> stream;
@@ -605,8 +578,6 @@
 }
 
 TEST(MojoAudioOutputIPC, Pause_Pauses) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   StrictMock<MockStream> stream;
@@ -635,8 +606,6 @@
 }
 
 TEST(MojoAudioOutputIPC, SetVolume_SetsVolume) {
-  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform;
-
   TestRemoteFactory stream_factory;
   const base::UnguessableToken session_id = base::UnguessableToken::Create();
   StrictMock<MockStream> stream;
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index c0aeb9e..c584bc8 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -108,6 +108,7 @@
   "//third_party/blink/renderer/modules/presentation/idls.gni",
   "//third_party/blink/renderer/modules/push_messaging/idls.gni",
   "//third_party/blink/renderer/modules/quota/idls.gni",
+  "//third_party/blink/renderer/modules/direct_sockets/idls.gni",
   "//third_party/blink/renderer/modules/remoteplayback/idls.gni",
   "//third_party/blink/renderer/modules/sanitizer_api/idls.gni",
   "//third_party/blink/renderer/modules/scheduler/idls.gni",
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
index 6430bcf..6d6e0de 100644
--- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
+++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc
@@ -33,10 +33,10 @@
   if (exception_state.HadException())
     return nullptr;
 
-  if (request->instrumentId().IsEmpty()) {
+  if (request->credentialIds().IsEmpty()) {
     exception_state.ThrowRangeError(
         "The \"secure-payment-confirmation\" method requires a non-empty "
-        "\"instrumentId\" field.");
+        "\"credentialIds\" field.");
     return nullptr;
   }
 
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
index cb94e7a..c67502a5 100644
--- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
+++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl
@@ -10,9 +10,9 @@
 
 dictionary SecurePaymentConfirmationRequest {
     SecurePaymentConfirmationAction action;
-    required DOMString instrumentId;
+    required FrozenArray<BufferSource> credentialIds;
     // Opaque data about the current transaction provided by the issuer. As the
-    // issuer is the RP of the credential, |networkData| provides protection
+    // issuer is the RP of the credential, `networkData` provides protection
     // against replay attacks.
     required BufferSource networkData;
     unsigned long timeout;
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
index 866fd64b..8056093 100644
--- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
+++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_type_converter.cc
@@ -7,20 +7,35 @@
 #include <stdint.h>
 
 #include "base/time/time.h"
+#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
 #include "third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace mojo {
 
+template <>
+struct TypeConverter<Vector<Vector<uint8_t>>,
+                     blink::HeapVector<blink::ArrayBufferOrArrayBufferView>> {
+  static Vector<Vector<uint8_t>> Convert(
+      const blink::HeapVector<blink::ArrayBufferOrArrayBufferView>& input) {
+    Vector<Vector<uint8_t>> result;
+    for (const auto& item : input) {
+      result.push_back(mojo::ConvertTo<Vector<uint8_t>>(item));
+    }
+    return result;
+  }
+};
+
 payments::mojom::blink::SecurePaymentConfirmationRequestPtr
 TypeConverter<payments::mojom::blink::SecurePaymentConfirmationRequestPtr,
               blink::SecurePaymentConfirmationRequest*>::
     Convert(const blink::SecurePaymentConfirmationRequest* input) {
   auto output = payments::mojom::blink::SecurePaymentConfirmationRequest::New();
-  output->instrument_id = input->instrumentId();
+  output->credential_ids =
+      mojo::ConvertTo<Vector<Vector<uint8_t>>>(input->credentialIds());
   output->network_data = mojo::ConvertTo<Vector<uint8_t>>(input->networkData());
 
-  // If a timeout was not specified in JavaScript, then pass a null |timeout|
+  // If a timeout was not specified in JavaScript, then pass a null `timeout`
   // through mojo IPC, so the browser can set a default (e.g., 3 minutes).
   if (input->hasTimeout())
     output->timeout = base::TimeDelta::FromMilliseconds(input->timeout());
diff --git a/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc b/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
index fc87af51..04ddb638 100644
--- a/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
+++ b/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.cc
@@ -26,6 +26,7 @@
 bool CrossOriginResourcePolicyChecker::IsBlocked(
     const url::Origin& initiator_origin,
     network::mojom::RequestMode request_mode,
+    network::mojom::RequestDestination request_destination,
     const blink::Response& response) {
   if (response.InternalURLList().IsEmpty()) {
     // The response is synthesized in the service worker, so it's considered as
@@ -43,7 +44,8 @@
   return network::CrossOriginResourcePolicy::IsBlockedByHeaderValue(
              response.InternalURLList().back(),
              response.InternalURLList().front(), initiator_origin,
-             corp_header_value, request_mode, initiator_origin, policy_,
+             corp_header_value, request_mode, initiator_origin,
+             request_destination, policy_,
              reporter_ ? reporter_.get() : nullptr)
       .has_value();
 }
diff --git a/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h b/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h
index dc73ce1..900b1b8a 100644
--- a/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h
+++ b/third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h
@@ -37,6 +37,7 @@
 
   bool IsBlocked(const url::Origin& initiator_origin,
                  network::mojom::RequestMode request_mode,
+                 network::mojom::RequestDestination request_destination,
                  const Response& response);
 
   base::WeakPtr<CrossOriginResourcePolicyChecker> GetWeakPtr();
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
index b7c585ad..071f5584 100644
--- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
+++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -312,7 +312,7 @@
     if (corp_checker_ &&
         corp_checker_->IsBlocked(
             url::Origin::Create(GURL(service_worker_global_scope->Url())),
-            request_mode_, *response)) {
+            request_mode_, request_destination_, *response)) {
       OnResponseRejected(ServiceWorkerResponseError::kDisallowedByCorp);
       return;
     }
diff --git a/third_party/blink/renderer/platform/bindings/exception_messages.cc b/third_party/blink/renderer/platform/bindings/exception_messages.cc
index 44d95c7e..69df3fd 100644
--- a/third_party/blink/renderer/platform/bindings/exception_messages.cc
+++ b/third_party/blink/renderer/platform/bindings/exception_messages.cc
@@ -97,6 +97,23 @@
          "': " + detail;
 }
 
+String ExceptionMessages::FailedToGetNamed(const char* type,
+                                           const String& detail) {
+  return "Failed to read a named property from '" + String(type) +
+         "': " + detail;
+}
+
+String ExceptionMessages::FailedToSetNamed(const char* type,
+                                           const String& detail) {
+  return "Failed to set a named property on '" + String(type) + "': " + detail;
+}
+
+String ExceptionMessages::FailedToDeleteNamed(const char* type,
+                                              const String& detail) {
+  return "Failed to delete a named property from '" + String(type) +
+         "': " + detail;
+}
+
 String ExceptionMessages::ConstructorNotCallableAsFunction(const char* type) {
   return FailedToConstruct(type,
                            "Please use the 'new' operator, this DOM object "
diff --git a/third_party/blink/renderer/platform/bindings/exception_messages.h b/third_party/blink/renderer/platform/bindings/exception_messages.h
index cba16d5..40ae4e71 100644
--- a/third_party/blink/renderer/platform/bindings/exception_messages.h
+++ b/third_party/blink/renderer/platform/bindings/exception_messages.h
@@ -76,6 +76,9 @@
   static String FailedToGetIndexed(const char* type, const String& detail);
   static String FailedToSetIndexed(const char* type, const String& detail);
   static String FailedToDeleteIndexed(const char* type, const String& detail);
+  static String FailedToGetNamed(const char* type, const String& detail);
+  static String FailedToSetNamed(const char* type, const String& detail);
+  static String FailedToDeleteNamed(const char* type, const String& detail);
 
   template <typename NumType>
   static String FormatNumber(NumType number) {
diff --git a/third_party/blink/renderer/platform/bindings/exception_state.cc b/third_party/blink/renderer/platform/bindings/exception_state.cc
index 1cab42a..e6ce495 100644
--- a/third_party/blink/renderer/platform/bindings/exception_state.cc
+++ b/third_party/blink/renderer/platform/bindings/exception_state.cc
@@ -212,11 +212,11 @@
       case kIndexedDeletionContext:
         return ExceptionMessages::FailedToDeleteIndexed(i, m);
       case kNamedGetterContext:
-        break;
+        return ExceptionMessages::FailedToGetNamed(i, m);
       case kNamedSetterContext:
-        break;
+        return ExceptionMessages::FailedToSetNamed(i, m);
       case kNamedDeletionContext:
-        break;
+        return ExceptionMessages::FailedToDeleteNamed(i, m);
       case kUnknownContext:
         break;
     }
@@ -245,11 +245,11 @@
       case kIndexedDeletionContext:
         return ExceptionMessages::FailedToDeleteIndexed(i, m);
       case kNamedGetterContext:
-        break;
+        return ExceptionMessages::FailedToGetNamed(i, m);
       case kNamedSetterContext:
-        break;
+        return ExceptionMessages::FailedToSetNamed(i, m);
       case kNamedDeletionContext:
-        break;
+        return ExceptionMessages::FailedToDeleteNamed(i, m);
       case kUnknownContext:
         break;
     }
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 9b17457..becdaed 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -435,6 +435,10 @@
   RuntimeEnabledFeatures::SetV8IdleTasksEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableDirectSockets(bool enable) {
+  RuntimeEnabledFeatures::SetDirectSocketsEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnablePushMessaging(bool enable) {
   RuntimeEnabledFeatures::SetPushMessagingEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 101a565..109c2d6b 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -223,6 +223,11 @@
       name: "BackForwardCache",
     },
     {
+      name: "BackForwardCacheExperimentHTTPHeader",
+      origin_trial_feature_name: "BackForwardCacheExperimentHTTPHeader",
+      status: "experimental",
+    },
+    {
       name: "BackgroundFetch",
       status: "stable",
     },
@@ -662,6 +667,10 @@
       status: "experimental",
     },
     {
+      name: "DirectSockets",
+      status: "test",
+    },
+    {
       name: "DisableHardwareNoiseSuppression",
       origin_trial_feature_name: "DisableHardwareNoiseSuppression",
       status: "experimental",
@@ -980,6 +989,7 @@
     },
     {
       name: "LayoutNGBlockFragmentation",
+      implied_by: ["LayoutNGPrinting"],
     },
     {
       name: "LayoutNGFieldset",
@@ -1010,6 +1020,9 @@
       name: "LayoutNGGrid",
     },
     {
+      name: "LayoutNGPrinting",
+    },
+    {
       name: "LayoutNGRuby",
       depends_on: ["LayoutNG"],
       // The flag value is managed by kLayoutNGRuby in common/features.cc too.
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
index 23bbe7c8..bd68c2f7 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -12,10 +12,11 @@
     case Feature::kWebSocket:
     case Feature::kWebRTC:
     case Feature::kDedicatedWorkerOrWorklet:
-    case Feature::kOutstandingNetworkRequestFetch:
-    case Feature::kOutstandingNetworkRequestXHR:
-    case Feature::kOutstandingNetworkRequestOthers:
     case Feature::kOutstandingIndexedDBTransaction:
+    case Feature::kOutstandingNetworkRequestDirectSocket:
+    case Feature::kOutstandingNetworkRequestFetch:
+    case Feature::kOutstandingNetworkRequestOthers:
+    case Feature::kOutstandingNetworkRequestXHR:
     case Feature::kBroadcastChannel:
     case Feature::kIndexedDBConnection:
     case Feature::kWebGL:
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
index f3af71aa2..8934d5f 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
@@ -130,7 +130,7 @@
 void CPUTimeBudgetPool::AsValueInto(base::trace_event::TracedValue* state,
                                     base::TimeTicks now) const {
   current_budget_level_.Trace();
-  state->BeginDictionary(name_);
+  auto dictionary_scope = state->BeginDictionaryScoped(name_);
 
   state->SetString("name", name_);
   state->SetDouble("time_budget", cpu_percentage_);
@@ -151,13 +151,12 @@
                      max_budget_level_.value().InSecondsF());
   }
 
-  state->BeginArray("task_queues");
-  for (TaskQueue* queue : associated_task_queues_) {
-    state->AppendString(PointerToString(queue));
+  {
+    auto array_scope = state->BeginArrayScoped("task_queues");
+    for (TaskQueue* queue : associated_task_queues_) {
+      state->AppendString(PointerToString(queue));
+    }
   }
-  state->EndArray();
-
-  state->EndDictionary();
 }
 
 void CPUTimeBudgetPool::Advance(base::TimeTicks now) {
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
index 45eaaaa..f15057e6 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
@@ -421,22 +421,24 @@
 
   state->SetBoolean("allow_throttling", allow_throttling_);
 
-  state->BeginDictionary("time_budget_pools");
-  for (const auto& map_entry : budget_pools_) {
-    BudgetPool* pool = map_entry.key;
-    pool->AsValueInto(state, now);
+  {
+    auto dictionary_scope = state->BeginDictionaryScoped("time_budget_pools");
+    for (const auto& map_entry : budget_pools_) {
+      BudgetPool* pool = map_entry.key;
+      pool->AsValueInto(state, now);
+    }
   }
-  state->EndDictionary();
 
-  state->BeginDictionary("queue_details");
-  for (const auto& map_entry : queue_details_) {
-    state->BeginDictionaryWithCopiedName(PointerToString(map_entry.key));
-    state->SetInteger(
-        "throttling_ref_count",
-        static_cast<int>(map_entry.value->throttling_ref_count()));
-    state->EndDictionary();
+  {
+    auto dictionary_scope = state->BeginDictionaryScoped("queue_details");
+    for (const auto& map_entry : queue_details_) {
+      auto inner_scope = state->BeginDictionaryScopedWithCopiedName(
+          PointerToString(map_entry.key));
+      state->SetInteger(
+          "throttling_ref_count",
+          static_cast<int>(map_entry.value->throttling_ref_count()));
+    }
   }
-  state->EndDictionary();
 }
 
 void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue,
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
index a560364..fd01c57 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
@@ -124,7 +124,7 @@
 
 void WakeUpBudgetPool::AsValueInto(base::trace_event::TracedValue* state,
                                    base::TimeTicks now) const {
-  state->BeginDictionary(name_);
+  auto dictionary_scope = state->BeginDictionaryScoped(name_);
 
   state->SetString("name", name_);
   state->SetDouble("wake_up_interval_in_seconds",
@@ -137,13 +137,12 @@
   }
   state->SetBoolean("is_enabled", is_enabled_);
 
-  state->BeginArray("task_queues");
-  for (TaskQueue* queue : associated_task_queues_) {
-    state->AppendString(PointerToString(queue));
+  {
+    auto array_scope = state->BeginArrayScoped("task_queues");
+    for (TaskQueue* queue : associated_task_queues_) {
+      state->AppendString(PointerToString(queue));
+    }
   }
-  state->EndArray();
-
-  state->EndDictionary();
 }
 
 }  // namespace scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index f614edb5..6ed5d37b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -790,17 +790,18 @@
       "disable_background_timer_throttling",
       !RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled());
 
-  state->BeginDictionary("frame_task_queue_controller");
-  frame_task_queue_controller_->AsValueInto(state);
-  state->EndDictionary();
+  {
+    auto dictionary_scope =
+        state->BeginDictionaryScoped("frame_task_queue_controller");
+    frame_task_queue_controller_->AsValueInto(state);
+  }
 
   if (blame_context_) {
-    state->BeginDictionary("blame_context");
+    auto dictionary_scope = state->BeginDictionaryScoped("blame_context");
     state->SetString(
         "id_ref",
         PointerToString(reinterpret_cast<void*>(blame_context_->id())));
     state->SetString("scope", blame_context_->scope());
-    state->EndDictionary();
   }
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index b5170f0..90906c3c 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -174,17 +174,19 @@
 
 void FrameTaskQueueController::AsValueInto(
     base::trace_event::TracedValue* state) const {
-  state->BeginArray("task_queues");
-  for (const auto& it : task_queues_) {
-    state->AppendString(PointerToString(it.value.get()));
+  {
+    auto array_scope = state->BeginArrayScoped("task_queues");
+    for (const auto& it : task_queues_) {
+      state->AppendString(PointerToString(it.value.get()));
+    }
   }
-  state->EndArray();
 
-  state->BeginArray("resource_loading_task_queues");
-  for (const auto& queue : resource_loading_task_queues_) {
-    state->AppendString(PointerToString(queue.get()));
+  {
+    auto array_scope = state->BeginArrayScoped("resource_loading_task_queues");
+    for (const auto& queue : resource_loading_task_queues_) {
+      state->AppendString(PointerToString(queue.get()));
+    }
   }
-  state->EndArray();
 }
 
 // static
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index cae3c682..7c9b16f5 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -2013,17 +2013,20 @@
       VirtualTimePolicyToString(main_thread_only().virtual_time_policy));
   state->SetBoolean("virtual_time", main_thread_only().use_virtual_time);
 
-  state->BeginDictionary("page_schedulers");
-  for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
-    state->BeginDictionaryWithCopiedName(PointerToString(page_scheduler));
-    page_scheduler->AsValueInto(state);
-    state->EndDictionary();
+  {
+    auto dictionary_scope = state->BeginDictionaryScoped("page_schedulers");
+    for (PageSchedulerImpl* page_scheduler :
+         main_thread_only().page_schedulers) {
+      auto inner_dictionary = state->BeginDictionaryScopedWithCopiedName(
+          PointerToString(page_scheduler));
+      page_scheduler->AsValueInto(state);
+    }
   }
-  state->EndDictionary();
 
-  state->BeginDictionary("policy");
-  main_thread_only().current_policy.AsValueInto(state);
-  state->EndDictionary();
+  {
+    auto dictionary_scope = state->BeginDictionaryScoped("policy");
+    main_thread_only().current_policy.AsValueInto(state);
+  }
 
   // TODO(skyostil): Can we somehow trace how accurate these estimates were?
   state->SetDouble(
@@ -2041,9 +2044,11 @@
   any_thread().user_model.AsValueInto(state);
   render_widget_scheduler_signals_.AsValueInto(state);
 
-  state->BeginDictionary("task_queue_throttler");
-  task_queue_throttler_->AsValueInto(state, optional_now);
-  state->EndDictionary();
+  {
+    auto dictionary_scope =
+        state->BeginDictionaryScoped("task_queue_throttler");
+    task_queue_throttler_->AsValueInto(state, optional_now);
+  }
 }
 
 bool MainThreadSchedulerImpl::TaskQueuePolicy::IsQueueEnabled(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
index c8cf35c..a404be3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -601,13 +601,14 @@
                     reported_background_throttling_since_navigation_);
   state->SetBoolean("is_page_freezable", IsBackgrounded());
 
-  state->BeginDictionary("frame_schedulers");
-  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
-    state->BeginDictionaryWithCopiedName(PointerToString(frame_scheduler));
-    frame_scheduler->AsValueInto(state);
-    state->EndDictionary();
+  {
+    auto dictionary_scope = state->BeginDictionaryScoped("frame_schedulers");
+    for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
+      auto inner_dictionary = state->BeginDictionaryScopedWithCopiedName(
+          PointerToString(frame_scheduler));
+      frame_scheduler->AsValueInto(state);
+    }
   }
-  state->EndDictionary();
 }
 
 void PageSchedulerImpl::AddQueueToWakeUpBudgetPool(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.cc b/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.cc
index 83fbaa99..4d13b8a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.cc
@@ -53,11 +53,11 @@
 
 void RenderWidgetSignals::AsValueInto(
     base::trace_event::TracedValue* state) const {
-  state->BeginDictionary("renderer_widget_signals");
+  auto dictionary_scope =
+      state->BeginDictionaryScoped("renderer_widget_signals");
   state->SetInteger("num_visible_render_widgets", num_visible_render_widgets_);
   state->SetInteger("num_visible_render_widgets_with_touch_handlers",
                     num_visible_render_widgets_with_touch_handlers_);
-  state->EndDictionary();
 }
 
 }  // namespace scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc b/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
index acb8beba..14ed5d50 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/user_model.cc
@@ -141,7 +141,7 @@
 }
 
 void UserModel::AsValueInto(base::trace_event::TracedValue* state) const {
-  state->BeginDictionary("user_model");
+  auto dictionary_scope = state->BeginDictionaryScoped("user_model");
   state->SetInteger("pending_input_event_count", pending_input_event_count_);
   state->SetDouble(
       "last_input_signal_time",
@@ -159,7 +159,6 @@
                    (last_reset_time_ - base::TimeTicks()).InMillisecondsF());
   state->SetBoolean("is_gesture_expected", is_gesture_expected_);
   state->SetBoolean("is_gesture_active", is_gesture_active_);
-  state->EndDictionary();
 }
 
 }  // namespace scheduler
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index b61ba30b..a5f75b1e 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -420,6 +420,9 @@
 ### virtual/layout_ng_fragment_traversal/
 virtual/layout_ng_fragment_traversal/* [ Skip ]
 
+### virtual/layout_ng_printing/
+virtual/layout_ng_printing/* [ Skip ]
+
 ### virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Failure ]
 
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 62fcdb1..681552a7 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2187,3 +2187,9 @@
 crbug.com/1005518 external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Skip ]
 crbug.com/1005518 external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Skip ]
 crbug.com/1005518 external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Skip ]
+
+# css-pseudo-4 ::spelling-error and ::grammar-error not implemented
+crbug.com/1035708 external/wpt/css/css-pseudo/spelling-error-001.html [ Skip ]
+crbug.com/1035708 external/wpt/css/css-pseudo/grammar-error-001.html [ Skip ]
+crbug.com/1035708 external/wpt/css/css-pseudo/selection-overlay-and-grammar-001.html [ Skip ]
+crbug.com/1035708 external/wpt/css/css-pseudo/selection-overlay-and-spelling-001.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f5fa8bdf..6ea7bc1 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1200,10 +1200,6 @@
 crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/relayout-abspos.html [ Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/remove-unbreakable-block-in-line-float.html [ Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/scrolling-contents-scroll.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_block_frag/printing/fixed-positioned-child-repeats-even-when-html-and-body-are-zero-height.html [ Crash Pass ]
-crbug.com/591099 virtual/layout_ng_block_frag/printing/fixed-positioned-child-shouldnt-print.html [ Crash Pass ]
-crbug.com/829028 virtual/layout_ng_block_frag/printing/frameset.html [ Failure ]
-crbug.com/829804 virtual/layout_ng_block_frag/printing/webgl-oversized-printing.html [ Skip ]
 
 ### With LayoutNGFragmentTraversal (and LayoutNGFragmentItem) enabled:
 
@@ -1227,6 +1223,13 @@
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/cascade/* [ Skip ]
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/text/* [ Skip ]
 
+### With LayoutNGPrinting enabled:
+
+crbug.com/1121942 virtual/layout_ng_printing/printing/fixed-positioned-child-repeats-even-when-html-and-body-are-zero-height.html [ Crash Pass ]
+crbug.com/1121942 virtual/layout_ng_printing/printing/fixed-positioned-child-shouldnt-print.html [ Crash Pass ]
+crbug.com/1121942 virtual/layout_ng_printing/printing/frameset.html [ Failure ]
+crbug.com/1121942 virtual/layout_ng_printing/printing/webgl-oversized-printing.html [ Skip ]
+
 # ====== LayoutNG-only failures until here ======
 
 # ====== MathMLCore-only tests from here ======
@@ -2461,10 +2464,6 @@
 
 crbug.com/1029514 external/wpt/html/semantics/embedded-content/the-video-element/resize-during-playback.html [ Pass Failure ]
 
-# css-pseudo-4 ::spelling-error and ::grammar-error not implemented
-crbug.com/1035708 external/wpt/css/css-pseudo/spelling-error-001.html [ Failure ]
-crbug.com/1035708 external/wpt/css/css-pseudo/grammar-error-001.html [ Failure ]
-
 # css-pseudo-4 opacity not applied to ::first-line
 crbug.com/1085772 external/wpt/css/css-pseudo/first-line-opacity-001.html [ Failure ]
 
@@ -2559,8 +2558,7 @@
 crbug.com/1105958 external/wpt/payment-request/payment-is-showing.https.html [ Timeout ]
 
 # ====== New tests from wpt-importer added here ======
-crbug.com/626703 external/wpt/css/css-pseudo/selection-overlay-and-grammar-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-pseudo/selection-overlay-and-spelling-001.html [ Failure ]
+crbug.com/626703 external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/pageshow-event.window.html [ Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/replaced-element-016.tentative.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/replaced-element-021.tentative.html [ Failure ]
@@ -6392,7 +6390,6 @@
 crbug.com/1011811 http/tests/devtools/network/network-xhr-data-received-async-response-type-blob.js [ Pass Failure ]
 crbug.com/1011811 http/tests/devtools/network/download.js [ Pass Failure ]
 crbug.com/1011811 http/tests/devtools/sxg/sxg-disable-cache.js [ Pass Failure ]
-crbug.com/1011811 http/tests/devtools/profiler/agents-disabled-check.js [ Pass Failure ]
 
 crbug.com/1080609 virtual/threaded/external/wpt/scroll-animations/element-based-offset.html [ Pass Failure ]
 crbug.com/1080609 virtual/threaded/external/wpt/scroll-animations/element-based-offset-clamp.html [ Pass Failure ]
@@ -6642,7 +6639,5 @@
 # Sheriff 2020-0-21
 crbug.com/1120330 virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-disabled-scrollbar-tentative.html [ Pass Failure ]
 
-crbug.com/1119676 external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html [ Failure ]
-
 # Sheriff 2020-08-26
 crbug.com/1122106 external/wpt/webrtc/protocol/crypto-suite.https.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index c8d2daf..43972cd3 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -227,8 +227,7 @@
               "external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements",
               "fast/forms/fieldset",
               "fast/multicol",
-              "fragmentation",
-              "printing"],
+              "fragmentation"],
     "args": ["--enable-blink-features=LayoutNGBlockFragmentation,LayoutNGFieldset"]
   },
   {
@@ -240,6 +239,11 @@
     "args": ["--enable-blink-features=LayoutNGFragmentTraversal"]
   },
   {
+    "prefix": "layout_ng_printing",
+    "bases": ["printing"],
+    "args": ["--enable-blink-features=LayoutNGPrinting"]
+  },
+  {
     "prefix": "layout-ng-grid",
     "bases": ["fast/css-grid-layout",
               "external/wpt/css/css-grid"],
@@ -747,5 +751,10 @@
     "prefix": "restrict-gamepad",
     "bases": [ "external/wpt/gamepad" ],
     "args": [ "--enable-features=RestrictGamepadAccess" ]
+  },
+  {
+    "prefix": "bfcache-experiment-control",
+    "bases": [ "http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial.php" ],
+    "args": [ "--enable-features=BackForwardCacheABExperimentControl" ]
   }
 ]
diff --git a/third_party/blink/web_tests/WPTOverrideExpectations b/third_party/blink/web_tests/WPTOverrideExpectations
index 11f9a2c..b373135 100644
--- a/third_party/blink/web_tests/WPTOverrideExpectations
+++ b/third_party/blink/web_tests/WPTOverrideExpectations
@@ -1441,18 +1441,6 @@
 external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html [ Pass Failure ]
 external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Pass Failure ]
 external/wpt/webaudio/the-audio-api/the-offlineaudiocontext-interface/offlineaudiocontext-detached-execution-context.tentative.html [ Failure ]
-external/wpt/webauthn/createcredential-badargs-authnrselection.https.html [ Failure ]
-external/wpt/webauthn/createcredential-excludecredentials.https.html [ Failure ]
-external/wpt/webauthn/createcredential-extensions.https.html [ Failure Timeout ]
-external/wpt/webauthn/createcredential-passing.https.html [ Failure ]
-external/wpt/webauthn/createcredential-pubkeycredparams.https.html [ Failure ]
-external/wpt/webauthn/createcredential-timeout.https.html [ Failure Pass ]
-external/wpt/webauthn/getcredential-badargs-rpid.https.html [ Failure ]
-external/wpt/webauthn/getcredential-badargs-userverification.https.html [ Failure ]
-external/wpt/webauthn/getcredential-extensions.https.html [ Failure ]
-external/wpt/webauthn/getcredential-passing.https.html [ Failure ]
-external/wpt/webauthn/getcredential-timeout.https.html [ Failure ]
-external/wpt/webauthn/webauthn-testdriver-basic.https.html [ Failure ]
 external/wpt/webmessaging/broadcastchannel/sandbox.html [ Failure Pass ] # wpt_subtest_failure
 external/wpt/webmessaging/with-options/broken-origin.html [ Failure Pass ] # wpt_subtest_failure
 external/wpt/webmessaging/with-ports/001.html [ Failure Pass ] # wpt_subtest_failure
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 61426b3..a1394e1 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -198934,7 +198934,7 @@
       []
      ],
      "from-local-system.md": [
-      "91823444d5d4813afb020d00b2fca188f4a22f21",
+      "f5cfa36915d7892d827d8f5aa74649e0e2c0c062",
       []
      ],
      "from-web.md": [
@@ -207769,14 +207769,6 @@
       "f305a39c1e214f9e9c968998b50c327b288c0fec",
       []
      ],
-     "cache-storage-reporting-document.https-expected.txt": [
-      "8905f3f180c4e3542e922d9e3a9cab16a9cc6325",
-      []
-     ],
-     "cache-storage-reporting-service-worker.https-expected.txt": [
-      "e29048d78b780f1f9acd080e517b51bca898986c",
-      []
-     ],
      "cache-storage-reporting-shared-worker.https-expected.txt": [
       "643200226b30cbe10b5b55f74162c1e7129a52bf",
       []
@@ -207825,12 +207817,8 @@
       "289659a41fdf41178781c764643f8946f4ec09b7",
       []
      ],
-     "reporting-navigation.https-expected.txt": [
-      "83a1649e39838562ef4c4db27ebd48340c314d96",
-      []
-     ],
      "reporting-subresource-corp.https-expected.txt": [
-      "2449b2e9b2c479430a2c63fae0fe94ac9b586be0",
+      "5a9108709f69ca997ae08f15602b1bf59f589473",
       []
      ],
      "reporting-to-endpoint.https.html.sub.headers": [
@@ -240303,11 +240291,11 @@
      []
     ],
     "RTCPeerConnection-setLocalDescription-answer-expected.txt": [
-     "550acfb3a31e64b533be233f27ea8696999170a5",
+     "bbb446057fc3a9fd19108fcce8e0256ef4f01bb3",
      []
     ],
     "RTCPeerConnection-setLocalDescription-offer-expected.txt": [
-     "1608296c0b5aa70145a6e74ead4fd88ad47f7427",
+     "cf9f74e156ecfe2b49f83699bbc6b6d927475840",
      []
     ],
     "RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt": [
@@ -240318,10 +240306,6 @@
      "f514bf7310bbe53c48d4c4001fd4ce455bd68f31",
      []
     ],
-    "RTCPeerConnection-setLocalDescription-rollback-expected.txt": [
-     "b0e9cd08ac5ca2f310dc3092e56df3799a71cd9d",
-     []
-    ],
     "RTCPeerConnection-setRemoteDescription-expected.txt": [
      "12a8febb5e70fd3623d1c9072ee9e536d6166e2b",
      []
@@ -337635,7 +337619,7 @@
       ]
      ],
      "reporting-subresource-corp.https.html": [
-      "b7571d038999e4e4fc524031fd7345f532dc08e7",
+      "ad8a8e99eb99e6ec92c8d40dfad0324365fbe6ac",
       [
        null,
        {
@@ -337644,7 +337628,7 @@
       ]
      ],
      "reporting-to-endpoint.https.html": [
-      "d40f437be119977663f6536053ffdcb1ad70e5b6",
+      "02c719da7372555386e89cb159910bf13e3900ff",
       [
        null,
        {
@@ -338147,6 +338131,15 @@
      ],
      "reporting": {
       "access-reporting": {
+       "access-from-coop-page-to-other_coop-ro.https.html": [
+        "e5cc726c5e0b38c8d25cd3ee8fb80f227e1c3e19",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
        "access-to-coop-page-from-other_coop-ro.https.html": [
         "c349b9a708e7cb579db921cc1d574869dc0b081c",
         [
@@ -354197,6 +354190,13 @@
          {}
         ]
        ],
+       "pageshow-event.window.js": [
+        "45570b35abf2232476d9cb93f294ce68362e5646",
+        [
+         "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/pageshow-event.window.html",
+         {}
+        ]
+       ],
        "quirks.window.js": [
         "0ff0bb99443677b8f8844c8ecedef22c408f2bac",
         [
@@ -405364,6 +405364,13 @@
       {}
      ]
     ],
+    "RTCPeerConnection-description-attributes-timing.https.html": [
+     "2d2565c3e1e0734a42231522d77129506491d2c1",
+     [
+      null,
+      {}
+     ]
+    ],
     "RTCPeerConnection-explicit-rollback-iceGatheringState.html": [
      "9c1fe014bd9ee18bb6a9ab65ea7aa3eebbce1200",
      [
@@ -405809,7 +405816,7 @@
      ]
     ],
     "RTCRtpTransceiver.https.html": [
-     "45c8664429fc44cb0caf67145641c4cd61052bb7",
+     "412736b1d195d7977b7be974ef4eddd828da3e12",
      [
       null,
       {
diff --git a/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md b/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
index 91823444..f5cfa36 100644
--- a/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
+++ b/third_party/blink/web_tests/external/wpt/docs/running-tests/from-local-system.md
@@ -7,7 +7,8 @@
 Running the tests requires `python`, `pip` and `virtualenv`, as well as updating
 the system `hosts` file.
 
-Note that Python 2.7 is required. Using Python 3 is not supported.
+Python 3 is supported and preferred, but for now it is still possible to use
+Python 2.7 if necessary.
 
 The required setup is different depending on your operating system.
 
@@ -22,6 +23,10 @@
 sudo apt-get install python python-pip virtualenv
 ```
 
+It is important to have a package that provides a `python` binary. On Fedora,
+for example, that means installing the `python-unversioned-command` package. On
+Ubuntu Focal and later, the package is called `python-is-python3`.
+
 ### macOS Setup
 
 The system-provided Python can be used, while `pip` and `virtualenv` can be
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-document.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-document.https-expected.txt
deleted file mode 100644
index 8905f3f1..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-document.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL COEP support on document. assert_equals: expected (string) "https://www1.web-platform.test:8444/images/blue.png" but got (undefined) undefined
-FAIL COEP-Report-Only support on document. assert_equals: expected (string) "https://www1.web-platform.test:8444/images/blue.png" but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt
deleted file mode 100644
index e29048d7..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL COEP support on ServiceWorker. assert_equals: expected (string) "https://www1.web-platform.test:8444/images/blue.png" but got (undefined) undefined
-FAIL COEP-Report-Only support on ServiceWorker. assert_equals: expected (string) "https://www1.web-platform.test:8444/images/blue.png" but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https-expected.txt
deleted file mode 100644
index 83a1649e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https-expected.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-This is a testharness.js-based test.
-PASS parent: (none), target: (none), with empty frame: false
-PASS parent: (none), target: (none), with empty frame: true
-PASS parent: (none), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: false
-PASS parent: (none), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: true
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy,require-corp)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy,require-corp)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: (none), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: (none), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=" but got (undefined) undefined
-PASS parent: (none), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: false
-PASS parent: (none), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: true
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-PASS parent: (none), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: false
-PASS parent: (none), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: true
-PASS parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: false
-PASS parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: true
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy,require-corp)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-embedder-policy,require-corp), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy,require-corp)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: (none), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: (none), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-resource-policy,cross-origin), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-PASS parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: false
-PASS parent: |header(cross-origin-embedder-policy-report-only,require-corp), target: |header(cross-origin-embedder-policy,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: true
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy-report-only,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: false assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy-report-only,require-corp)|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-FAIL parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-embedder-policy-report-only,require-corp)|header(cross-origin-resource-policy,cross-origin), with empty frame: true assert_equals: expected (string) "https://www1.web-platform.test:8444/common/blank.html?pipe=|header(cross-origin-embedder-policy-report-only,require-corp)|header(cross-origin-resource-policy,cross-origin)" but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt
index 2449b2e..5a91087 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt
@@ -1,8 +1,8 @@
 This is a testharness.js-based test.
 PASS [document] same-origin
 PASS [document] blocked by CORP: same-origin
-FAIL [document] blocked due to COEP assert_equals: expected (string) "https://www1.web-platform.test:8444/common/text-plain.txt" but got (undefined) undefined
-FAIL [document] blocked during redirect assert_equals: expected (string) "https://web-platform.test:8444/common/redirect.py?location=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fcommon%2Ftext-plain.txt" but got (undefined) undefined
+PASS [document] blocked due to COEP
+PASS [document] blocked during redirect
 PASS [dedicated worker] same-origin
 PASS [dedicated worker] blocked by CORP: same-origin
 FAIL [dedicated worker] blocked due to COEP assert_equals: expected 2 but got 0
@@ -13,12 +13,12 @@
 FAIL [shared worker] blocked during redirect assert_equals: expected 2 but got 0
 PASS [service worker] same-origin
 PASS [service worker] blocked by CORP: same-origin
-FAIL [service worker] blocked due to COEP assert_equals: expected (string) "https://www1.web-platform.test:8444/common/text-plain.txt" but got (undefined) undefined
-FAIL [service worker] blocked during redirect assert_equals: expected (string) "https://web-platform.test:8444/common/redirect.py?location=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fcommon%2Ftext-plain.txt" but got (undefined) undefined
+PASS [service worker] blocked due to COEP
+PASS [service worker] blocked during redirect
 PASS [between service worker and page] same-origin
 PASS [between service worker and page] blocked by CORP: same-origin
-FAIL [between service worker and page] blocked due to COEP assert_equals: expected (string) "https://www1.web-platform.test:8444/common/text-plain.txt" but got (undefined) undefined
-FAIL [between service worker and page] blocked during redirect assert_equals: expected (string) "https://web-platform.test:8444/common/redirect.py?location=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fcommon%2Ftext-plain.txt" but got (undefined) undefined
-FAIL destination: script assert_equals: expected 2 but got 0
+PASS [between service worker and page] blocked due to COEP
+PASS [between service worker and page] blocked during redirect
+PASS destination: script
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html
index b7571d0..ad8a8e9 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html
@@ -185,7 +185,7 @@
     }
   });
   observer.observe();
-  const url = `${REMOTE_ORIGIN}$/common/utils.js`;
+  const url = `${REMOTE_ORIGIN}/common/utils.js`;
   const script = frame.contentDocument.createElement('script');
   script.src = url;
   frame.contentDocument.body.appendChild(script);
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html
index d40f437..02c719d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html
@@ -44,7 +44,7 @@
 pollReports('endpoint', reports);
 pollReports('report-only-endpoint', reportsForReportOnly);
 
-function checkCorpReportExistence(reports, blockedUrl, contextUrl, disposition) {
+function checkCorpReportExistence(reports, blockedUrl, contextUrl, destination, disposition) {
   blockedUrl = new URL(blockedUrl, location).href;
   contextUrl = new URL(contextUrl, location).href;
   for (const report of reports) {
@@ -54,7 +54,7 @@
     }
     if (report.body.blockedURL === blockedUrl &&
         report.body.disposition === disposition) {
-      assert_equals(report.body.destination, '');
+      assert_equals(report.body.destination, destination);
       return;
     }
   }
@@ -97,9 +97,9 @@
     // Wait 3 seconds for reports to settle.
     await wait(3000);
 
-    checkCorpReportExistence(reports, url, iframe.src, 'enforce');
+    checkCorpReportExistence(reports, url, iframe.src, '', 'enforce');
     checkCorpReportExistence(
-      reportsForReportOnly, url, iframe.src, 'reporting');
+      reportsForReportOnly, url, iframe.src, '', 'reporting');
 
     t.done();
   } catch (e) {
@@ -134,9 +134,9 @@
     // Wait 3 seconds for reports to settle.
     await wait(3000);
 
-    checkCorpReportExistence(reports, url, iframe.src, 'enforce');
+    checkCorpReportExistence(reports, url, iframe.src, 'iframe', 'enforce');
     checkCorpReportExistence(
-      reportsForReportOnly, url, iframe.src, 'reporting');
+      reportsForReportOnly, url, iframe.src, 'iframe', 'reporting');
 
     t.done();
   } catch (e) {
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html
new file mode 100644
index 0000000..e5cc726c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro.https.html
@@ -0,0 +1,87 @@
+<title>
+  One window accesses a second one. They are aren't related by an opener/openee
+  relationship. The first window has set
+  Cross-Origin-Opener-Policy-Report-Only:same-origin, so it receives a
+  "access-from-coop-page-to-other" report.
+</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/get-host-info.sub.js></script>
+<script src="/common/utils.js"></script>
+<script src="../resources/dispatcher.js"></script>
+<script src="../resources/try-access.js"></script>
+<script>
+
+const directory = "/html/cross-origin-opener-policy/reporting";
+const executor_path = directory + "/resources/executor.html?pipe=";
+const same_origin = get_host_info().HTTPS_ORIGIN;
+const coep_header = '|header(Cross-Origin-Embedder-Policy,require-corp)';
+
+let escapeComma = url => url.replace(/,/g, '\\,');
+
+promise_test(async t => {
+  const report_token= token();
+  const report_to = reportToHeaders(report_token);
+
+  // The test window.
+  const this_window_token = token();
+
+  // The "opener" window. With COOP:same-origin + reporter.
+  const opener_token = token();
+  const opener_url = same_origin + executor_path + report_to.header +
+    report_to.coopReportOnlySameOriginHeader + coep_header +
+    `&uuid=${opener_token}`;
+
+  // The "openee" window. With COOP:same-origin + reporter.
+  const openee_token = token();
+  const openee_url = same_origin + executor_path + report_to.header +
+    report_to.coopReportOnlySameOriginHeader + coep_header +
+    `&uuid=${openee_token}`;
+
+  // The "other" window.
+  const other_token = token();
+  const other_url = same_origin + executor_path + report_to.header +
+    `&uuid=${other_token}`;
+
+  t.add_cleanup(() => {
+    send(opener_token, "window.close()")
+    send(openee_token, "window.close()")
+    send(other_token, "window.close()")
+  })
+
+  // 1. Create the "opener" window.
+  let opener_window_proxy = window.open(opener_url);
+
+  // 2. Create the "openee" window.
+  send(opener_token, `
+    window.openee = window.open('${escapeComma(openee_url)}');
+  `);
+
+  // 3. Create the "other" window.
+  send(openee_token, `
+    window.other = window.open('${escapeComma(other_url)}');
+  `);
+
+  // 4. Wait for "other" to load its document.
+  send(other_token, `send('${this_window_token}', "Loaded");`);
+  assert_equals(await receive(this_window_token), "Loaded");
+
+  // 5. "opener" accesses "other" window, through "openee".
+  send(opener_token, `
+    tryAccess(openee.other);
+  `);
+
+  // 6. Check a report is sent to the openee.
+  let report =
+    await receiveReport(report_token, "access-from-coop-page-to-other")
+  assert_not_equals(report, "timeout", "Report not received");
+  assert_equals(report.type, "coop");
+  assert_equals(report.url, opener_url.replace(/"/g, '%22'));
+  assert_equals(report.body.disposition, "reporting");
+  assert_equals(report.body.effectivePolicy, "same-origin-plus-coep");
+  assert_equals(report.body.property, "blur");
+  assert_source_location_found(report);
+}, "access-from-coop-page-to-other (COOP-RO)");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/pageshow-event.window.js b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/pageshow-event.window.js
new file mode 100644
index 0000000..45570b3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/pageshow-event.window.js
@@ -0,0 +1,13 @@
+async_test(t => {
+  const frame = document.body.appendChild(document.createElement("iframe"));
+  assert_equals(frame.contentDocument.open(), frame.contentDocument);
+  assert_equals(frame.contentDocument.documentElement, null);
+  frame.contentDocument.write("<div>heya</div>");
+  frame.contentDocument.close();
+  frame.contentWindow.addEventListener("pageshow", function() {
+    t.step(function() {
+      assert_true(true, "Got pageshow event");
+    });
+    t.done();
+  });
+}, "document.open(), and the pageshow events");
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html b/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html
index b8d8372..35de56ca0 100644
--- a/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html
+++ b/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html
@@ -16,7 +16,7 @@
     data: {
        // All valid parameters.
        action: 'authenticate',
-       instrumentId: 'x',
+       credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
        networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
        timeout: 60000,
        fallbackUrl: 'https://fallback.example/url'
@@ -29,7 +29,7 @@
     supportedMethods: 'secure-payment-confirmation',
     data: {
        // Omitted action field.
-       instrumentId: 'x',
+       credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
        networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
        timeout: 60000,
        fallbackUrl: 'https://fallback.example/url'
@@ -42,7 +42,7 @@
     supportedMethods: 'secure-payment-confirmation',
     data: {
        action: 'authenticate',
-       instrumentId: 'x',
+       credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
        networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
        // Omitted timeout field.
        fallbackUrl: 'https://fallback.example/url'
@@ -56,7 +56,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -71,7 +71,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -86,7 +86,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -101,7 +101,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -116,7 +116,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -131,7 +131,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -147,7 +147,7 @@
       data: {
         // Invalid action parameter.
         action: 'authorize',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
@@ -162,14 +162,14 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        // Omitted instrumentId field.
+        // Omitted credentialIds field.
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
       },
     }], details);
   });
-}, 'The instrumentId field is required.');
+}, 'The credentialIds field is required.');
 
 test(() => {
   assert_throws_js(TypeError, () => {
@@ -177,8 +177,8 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
-        // Omitted instrumentId field.
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
+        // Omitted networkData field.
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
       },
@@ -192,7 +192,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         // Omitted fallbackUrl field.
@@ -207,15 +207,16 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        // Empty instrumentId field.
-        instrumentId: '',
+        relyingPartyId: 'relying-party.example',
+        // Empty credentialIds field.
+        credentialIds: [],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         timeout: 60000,
         fallbackUrl: 'https://fallback.example/url'
       },
     }], details);
   });
-}, 'Empty instrumentId field throws exception.');
+}, 'Empty credentialIds field throws exception.');
 
 test(() => {
   assert_throws_js(TypeError, () => {
@@ -223,7 +224,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         // Null networkData field.
         networkData: null,
         timeout: 60000,
@@ -239,7 +240,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         // Empty networkData field.
         networkData: [],
         timeout: 60000,
@@ -255,7 +256,7 @@
       supportedMethods: 'secure-payment-confirmation',
       data: {
         action: 'authenticate',
-        instrumentId: 'x',
+        credentialIds: [Uint8Array.from('x', c => c.charCodeAt(0))],
         networkData: Uint8Array.from('x', c => c.charCodeAt(0)),
         // Timeout longer than 1 hour.
         timeout: 1000 * 60 * 60 + 1,
diff --git a/third_party/blink/web_tests/external/wpt/raw-sockets/META.yml b/third_party/blink/web_tests/external/wpt/raw-sockets/META.yml
new file mode 100644
index 0000000..d424a0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/raw-sockets/META.yml
@@ -0,0 +1,5 @@
+spec: https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md
+suggested_reviewers:
+  - ewilligers
+  - mgiuca
+  - phoglenix
diff --git a/third_party/blink/web_tests/external/wpt/raw-sockets/OWNERS b/third_party/blink/web_tests/external/wpt/raw-sockets/OWNERS
new file mode 100644
index 0000000..66ede73
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/raw-sockets/OWNERS
@@ -0,0 +1,6 @@
+# This directory already inherits owner '*', so these owners are informational.
+ericwilligers@chromium.org
+glenrob@chromium.org
+mgiuca@chromium.org
+
+# COMPONENT: Blink>Network
diff --git a/third_party/blink/web_tests/external/wpt/raw-sockets/README.md b/third_party/blink/web_tests/external/wpt/raw-sockets/README.md
new file mode 100644
index 0000000..bcebe03
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/raw-sockets/README.md
@@ -0,0 +1,2 @@
+These tests are for the TCP and UDP sockets API proposed in
+https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md
diff --git a/third_party/blink/web_tests/external/wpt/raw-sockets/open-securecontext.http.html b/third_party/blink/web_tests/external/wpt/raw-sockets/open-securecontext.http.html
new file mode 100644
index 0000000..371f137
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/raw-sockets/open-securecontext.http.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Sockets test: Open from non-secure context</title>
+    <link rel="help" href="https://github.com/WICG/raw-sockets/blob/master/docs/explainer.md#security-considerations">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <script>
+        test(() => {
+          assert_false('openTCPSocket' in navigator, 'navigator has attribute \'openTCPSocket\'.');
+        }, 'navigator.openTCPSocket must be undefined in non-secure context');
+
+        test(() => {
+          assert_false('openUDPSocket' in navigator, 'navigator has attribute \'openUDPSocket\'.');
+        }, 'navigator.openUDPSocket must be undefined in non-secure context');
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/raw-sockets/remotePort-required.html b/third_party/blink/web_tests/external/wpt/raw-sockets/remotePort-required.html
new file mode 100644
index 0000000..22bba2c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/raw-sockets/remotePort-required.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Sockets test: open without remotePort</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <script>
+      'use strict';
+
+      const options = {
+        localAddress: "127.0.0.1",
+        localPort: 0,
+        remoteAddress: "127.0.0.1",
+      };
+
+      test(() => {
+        assert_throws_js(TypeError, () => { navigator.openTCPSocket() });
+        assert_throws_js(TypeError, () => { navigator.openTCPSocket(null) });
+        assert_throws_js(TypeError, () => { navigator.openTCPSocket(undefined) });
+        assert_throws_js(TypeError, () => { navigator.openTCPSocket(options) });
+      }, 'openTCPSocket requires remotePort');
+
+      test(() => {
+        assert_throws_js(TypeError, () => { navigator.openUDPSocket() });
+        assert_throws_js(TypeError, () => { navigator.openUDPSocket(null) });
+        assert_throws_js(TypeError, () => { navigator.openUDPSocket(undefined) });
+        assert_throws_js(TypeError, () => { navigator.openTCPSocket(options) });
+      }, 'openUDPSocket requires remotePort');
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html
index 45c8664..412736b 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html
@@ -425,6 +425,7 @@
 
     // Remove mid attr
     offer.sdp = offer.sdp.replace("a=mid:", "a=unknownattr:");
+    offer.sdp = offer.sdp.replace("a=group:", "a=unknownattr:");
     await pc2.setRemoteDescription(offer);
 
     hasPropsAndUniqueMids(pc2.getTransceivers(),
diff --git a/third_party/blink/web_tests/fast/dom/dataset-xhtml-expected.txt b/third_party/blink/web_tests/fast/dom/dataset-xhtml-expected.txt
index 705a0cb..de2c54a 100644
--- a/third_party/blink/web_tests/fast/dom/dataset-xhtml-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/dataset-xhtml-expected.txt
@@ -24,9 +24,9 @@
 PASS testSet('à', 'data-à') is true
 
 
-PASS testSet('-foo', 'dummy') threw exception SyntaxError: '-foo' is not a valid property name..
-PASS testSet('foo ', 'dummy') threw exception InvalidCharacterError: 'data-foo ' is not a valid attribute name..
-PASS testSet('foo豈', 'dummy') threw exception InvalidCharacterError: 'data-foo豈' is not a valid attribute name..
+PASS testSet('-foo', 'dummy') threw exception SyntaxError: Failed to set a named property on 'DOMStringMap': '-foo' is not a valid property name..
+PASS testSet('foo ', 'dummy') threw exception InvalidCharacterError: Failed to set a named property on 'DOMStringMap': 'data-foo ' is not a valid attribute name..
+PASS testSet('foo豈', 'dummy') threw exception InvalidCharacterError: Failed to set a named property on 'DOMStringMap': 'data-foo豈' is not a valid attribute name..
 
 
 PASS testDelete('data-foo', 'foo') is true
diff --git a/third_party/blink/web_tests/fast/dom/dataset-xhtml.xhtml b/third_party/blink/web_tests/fast/dom/dataset-xhtml.xhtml
index e9d9301..c5a1b98 100644
--- a/third_party/blink/web_tests/fast/dom/dataset-xhtml.xhtml
+++ b/third_party/blink/web_tests/fast/dom/dataset-xhtml.xhtml
@@ -55,9 +55,9 @@
 shouldBeTrue("testSet('\xE0', 'data-\xE0')");
 debug("");
 
-shouldThrow("testSet('-foo', 'dummy')", '"SyntaxError: \'-foo\' is not a valid property name."');
-shouldThrow("testSet('foo\x20', 'dummy')", '"InvalidCharacterError: \'data-foo\x20\' is not a valid attribute name."');
-shouldThrow("testSet('foo\uF900', 'dummy')", '"InvalidCharacterError: \'data-foo\uF900\' is not a valid attribute name."');
+shouldThrow("testSet('-foo', 'dummy')", '"SyntaxError: Failed to set a named property on \'DOMStringMap\': \'-foo\' is not a valid property name."');
+shouldThrow("testSet('foo\x20', 'dummy')", '"InvalidCharacterError: Failed to set a named property on \'DOMStringMap\': \'data-foo \' is not a valid attribute name."');
+shouldThrow("testSet('foo\uF900', 'dummy')", '"InvalidCharacterError: Failed to set a named property on \'DOMStringMap\': \'data-foo\uF900\' is not a valid attribute name."');
 debug("");
 
 function testDelete(attr, prop)
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt
new file mode 100644
index 0000000..1a74bc32
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt
@@ -0,0 +1 @@
+Sec-bfcache-experiment: <missing>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial.php b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial.php
new file mode 100644
index 0000000..4094564
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial.php
@@ -0,0 +1,23 @@
+<title>BackForwardCacheExperimentHTTPHeader - enabled by origin trial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="status"></div>
+<script>
+test(t => {
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', 'resources/echo-request-sec-bfcache-experiment.php');
+  xhr.onload = function (e) {
+    document.getElementById('status').innerText =  xhr.responseText;
+    if (window.testRunner)
+      testRunner.notifyDone();
+  };
+  xhr.onerror = function (e) {
+    document.getElementById('status').innerText = "FAIL";
+    if (window.testRunner)
+      testRunner.notifyDone();
+  };
+  xhr.send();
+}, 'Sec-bfcache-experiment must be set.');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/echo-request-sec-bfcache-experiment.php b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/echo-request-sec-bfcache-experiment.php
new file mode 100644
index 0000000..a0100d47
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/echo-request-sec-bfcache-experiment.php
@@ -0,0 +1,7 @@
+<?php
+header('Content-Type: text/plain');
+if (isset($_SERVER['HTTP_SEC_BFCACHE_EXPERIMENT']))
+    echo 'Sec-bfcache-experiment: ' . $_SERVER['HTTP_SEC_BFCACHE_EXPERIMENT'];
+else
+    echo 'Sec-bfcache-experiment: <missing>';
+?>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/avoid-setting-header-offset-on-header-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/avoid-setting-header-offset-on-header-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/avoid-setting-header-offset-on-header-expected.png
rename to third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/avoid-setting-header-offset-on-header-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/iframe-print-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/iframe-print-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/iframe-print-expected.png
rename to third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/iframe-print-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/page-orientation-propagated-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/page-orientation-propagated-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/page-orientation-propagated-expected.png
rename to third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/page-orientation-propagated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/return-from-printing-mode-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/return-from-printing-mode-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/return-from-printing-mode-expected.png
rename to third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/return-from-printing-mode-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
rename to third_party/blink/web_tests/platform/linux/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/avoid-setting-header-offset-on-header-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/avoid-setting-header-offset-on-header-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/avoid-setting-header-offset-on-header-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/avoid-setting-header-offset-on-header-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/fixed-positioned-headers-and-footers-larger-than-page-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/fixed-positioned-headers-and-footers-larger-than-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/fixed-positioned-headers-and-footers-larger-than-page-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/fixed-positioned-headers-and-footers-larger-than-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/iframe-print-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/iframe-print-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/iframe-print-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/iframe-print-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/page-orientation-propagated-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/page-orientation-propagated-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/page-orientation-propagated-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/page-orientation-propagated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.12/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_block_frag/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
rename to third_party/blink/web_tests/platform/mac-mac10.14/virtual/layout_ng_printing/printing/thead-repeats-at-top-of-each-page-multiple-tables-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_printing/printing/composited-thead-tfoot-repeat-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac/virtual/layout_ng_block_frag/printing/composited-thead-tfoot-repeat-expected.png
rename to third_party/blink/web_tests/platform/mac/virtual/layout_ng_printing/printing/composited-thead-tfoot-repeat-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/printing/iframe-print-expected.png b/third_party/blink/web_tests/platform/win/virtual/layout_ng_printing/printing/iframe-print-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/win/virtual/layout_ng_block_frag/printing/iframe-print-expected.png
rename to third_party/blink/web_tests/platform/win/virtual/layout_ng_printing/printing/iframe-print-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/bfcache-experiment-control/README.md b/third_party/blink/web_tests/virtual/bfcache-experiment-control/README.md
new file mode 100644
index 0000000..3fb33e70
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/bfcache-experiment-control/README.md
@@ -0,0 +1,2 @@
+*This suite runs the tests with**
+`--enable-features=BackForwardCacheABExperimentControl`
diff --git a/third_party/blink/web_tests/virtual/bfcache-experiment-control/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt b/third_party/blink/web_tests/virtual/bfcache-experiment-control/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt
new file mode 100644
index 0000000..db8bc8f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/bfcache-experiment-control/http/tests/origin_trials/webexposed/bfcache-experiment-http-header-origin-trial-expected.txt
@@ -0,0 +1 @@
+Sec-bfcache-experiment:
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/README.txt b/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/README.txt
deleted file mode 100644
index 382a681d..0000000
--- a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# This suite runs the tests in printing with
-# --enable-blink-features=LayoutNGBlockFragmentation.
-# The LayoutNG project is described here: http://goo.gl/1hwhfX
diff --git a/third_party/blink/web_tests/virtual/layout_ng_printing/README.md b/third_party/blink/web_tests/virtual/layout_ng_printing/README.md
new file mode 100644
index 0000000..508f58f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/layout_ng_printing/README.md
@@ -0,0 +1 @@
+Testing LayoutNGPrinting; see ../../VirtualTestSuites
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/ellipsis-printing-style-expected.png b/third_party/blink/web_tests/virtual/layout_ng_printing/printing/ellipsis-printing-style-expected.png
similarity index 100%
rename from third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/ellipsis-printing-style-expected.png
rename to third_party/blink/web_tests/virtual/layout_ng_printing/printing/ellipsis-printing-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/page-height-zero-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_printing/printing/page-height-zero-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/page-height-zero-expected.txt
rename to third_party/blink/web_tests/virtual/layout_ng_printing/printing/page-height-zero-expected.txt
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/viewport-size-dependant-iframe-with-multicol-crash-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_printing/printing/viewport-size-dependant-iframe-with-multicol-crash-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/viewport-size-dependant-iframe-with-multicol-crash-expected.txt
rename to third_party/blink/web_tests/virtual/layout_ng_printing/printing/viewport-size-dependant-iframe-with-multicol-crash-expected.txt
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/webgl-repeated-printing-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_printing/printing/webgl-repeated-printing-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/webgl-repeated-printing-expected.txt
rename to third_party/blink/web_tests/virtual/layout_ng_printing/printing/webgl-repeated-printing-expected.txt
diff --git a/third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_printing/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/virtual/layout_ng_block_frag/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt
rename to third_party/blink/web_tests/virtual/layout_ng_printing/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt
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 c401d47..f87c815a 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
@@ -5529,6 +5529,8 @@
     method getInstalledRelatedApps
     method getUserMedia
     method javaEnabled
+    method openTCPSocket
+    method openUDPSocket
     method registerProtocolHandler
     method requestMIDIAccess
     method requestMediaKeySystemAccess
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a45e898..f6553d1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9217,6 +9217,7 @@
   <int value="36" label="kMediaFeeds"/>
   <int value="37" label="kAccountPasswords"/>
   <int value="38" label="kAccountPasswordsSynced"/>
+  <int value="39" label="kAccountCompromisedCredentials"/>
 </enum>
 
 <enum name="ChromeChannelForHistogram">
@@ -16402,6 +16403,17 @@
   <int value="8" label="Network show large rows off"/>
 </enum>
 
+<enum name="DevToolsSidebarPane">
+  <int value="0" label="Other sidebar pane"/>
+  <int value="1" label="Elements - Styles"/>
+  <int value="2" label="Elements - Computed"/>
+  <int value="3" label="Elements - Layout"/>
+  <int value="4" label="Elements - Event Listeners"/>
+  <int value="5" label="Elements - DOM Breakpoints"/>
+  <int value="6" label="Elements - Properties"/>
+  <int value="7" label="Elements - Accessibility"/>
+</enum>
+
 <enum name="DiagnosticsRecoveryRun">
   <int value="0" label="Recovery not run"/>
   <int value="1" label="Recovery run because of crash"/>
@@ -28996,6 +29008,7 @@
   <int value="3458" label="WebCodecsVideoEncoder"/>
   <int value="3459" label="WebCodecsVideoTrackReader"/>
   <int value="3460" label="WebCodecsImageDecoder"/>
+  <int value="3461" label="BackForwardCacheExperimentHTTPHeader"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -74433,6 +74446,7 @@
   <int value="50" label="SpeechSynthesis"/>
   <int value="51" label="KeyboardLock"/>
   <int value="52" label="SmsService"/>
+  <int value="53" label="OutstandingNetworkRequestDirectSocket"/>
 </enum>
 
 <enum name="WebShareMethod">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index a095a40..d81606db 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -27804,7 +27804,19 @@
   <owner>tellier@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
-    The time spent before the multiprofile account picker is ready.
+    The time spent before the web UI vesion of the multiprofile account picker
+    is ready.
+  </summary>
+</histogram>
+
+<histogram name="ChromeOS.UserAddingScreen.LoadTimeViewsBased" units="ms"
+    expires_after="2021-01-07">
+  <owner>tellier@google.com</owner>
+  <owner>rsorokin@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
+  <summary>
+    The time spent before the views-based version of the multiprofile account
+    picker is ready.
   </summary>
 </histogram>
 
@@ -40087,6 +40099,14 @@
   <summary>Specified DevTools setting was changed.</summary>
 </histogram>
 
+<histogram name="DevTools.SidebarPaneShown" enum="DevToolsSidebarPane"
+    expires_after="2021-07-31">
+  <owner>changhaohan@chromium.org</owner>
+  <owner>yangguo@chromium.org</owner>
+  <owner>bmeurer@chromium.org</owner>
+  <summary>Specified DevTools sidebar pane was shown.</summary>
+</histogram>
+
 <histogram name="Diagnostics.Recovery.ConflictingDlls" enum="DiagnosticsResult"
     expires_after="2016-04-29">
   <obsolete>
@@ -119446,8 +119466,8 @@
 </histogram>
 
 <histogram name="OOBE.RecommendApps.Fetcher.AppCount" units="units"
-    expires_after="2020-08-30">
-  <owner>rsorokin@chromium.org</owner>
+    expires_after="2021-07-30">
+  <owner>raleksandrov@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <owner>play-bm-eng@google.com</owner>
   <summary>The number of recommended apps.</summary>
@@ -119479,7 +119499,10 @@
 
 <histogram name="OOBE.RecommendApps.Fetcher.ResponseSize" units="KB"
     expires_after="2020-08-30">
-  <owner>rsorokin@chromium.org</owner>
+  <obsolete>
+    Removed as of 08/27/2020. No longer needed to track size of a response.
+  </obsolete>
+  <owner>raleksandrov@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <owner>chromesky-eng@google.com</owner>
   <summary>The size of the recommend-apps JSON response.</summary>
@@ -119502,8 +119525,8 @@
 </histogram>
 
 <histogram name="OOBE.RecommendApps.Screen.SelectedRecommendedPercentage"
-    units="%" expires_after="2020-08-30">
-  <owner>rsorokin@chromium.org</owner>
+    units="%" expires_after="2021-07-30">
+  <owner>raleksandrov@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <owner>chromesky-eng@google.com</owner>
   <summary>The ratio of selected and recommended apps.</summary>
@@ -141988,6 +142011,18 @@
   </summary>
 </histogram>
 
+<histogram name="Profile.NumberOfProfilesAtProfileSwitch" units="profiles"
+    expires_after="2021-03-01">
+  <owner>jkrcal@chromium.org</owner>
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Records the count of profiles for each profile switch (incl. switching
+    between concurrently open profiles by activating their browser windows). The
+    count excludes the Guest profile so records in bucket 1 denote switches
+    between the single profile and the Guest profile.
+  </summary>
+</histogram>
+
 <histogram name="Profile.NumberOfProfilesOnStartup" units="units"
     expires_after="2014-01-29">
   <obsolete>
@@ -165447,6 +165482,18 @@
   <summary>The number of signed in accounts in the cookie jar.</summary>
 </histogram>
 
+<histogram base="true" name="Signin.CookieJar.SignedInCountWithPrimary"
+    units="accounts" expires_after="2021-03-01">
+  <owner>jkrcal@chromium.org</owner>
+  <owner>droger@chromium.org</owner>
+  <summary>
+    The number of signed in accounts in the cookie jar for users that have a
+    (possibly unconsented) primary account. Reported at most every 24 hours
+    (using a persistent timer). Reporting is split based on the type of the
+    primary account.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Signin.CookieJar.SignedOutCount" units="accounts"
     expires_after="never">
 <!-- expires-never: this histogram gives important user information about user
@@ -217940,6 +217987,14 @@
   <affected-histogram name="UKM.Sources.SerializedCount2"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="UnconsentedPrimaryAccountType" separator=".">
+  <suffix name="NoSyncConsumer" label="A consumer account, no sync."/>
+  <suffix name="NoSyncEnterprise" label="An enterprise account, no sync."/>
+  <suffix name="SyncConsumer" label="A consumer account, syncing."/>
+  <suffix name="SyncEnterprise" label="An enterprise account, syncing."/>
+  <affected-histogram name="Signin.CookieJar.SignedInCountWithPrimary"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="UnPackConsumer" separator="_">
   <suffix name="ChromeArchivePatch"
       label="compressed patch: chrome_patch.packed.7z holding
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 79344fe..55ce7bd 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,11 +6,11 @@
         },
         "mac": {
             "hash": "4a318e434590be8c4a5d7bb2fea5ce2411353104",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/ced41e1f394dc71e63fd979d50c2fe0e507f2fbe/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/11944f7122cf99f1aaa82eb2bed364d5edf0f85f/trace_processor_shell"
         },
         "linux": {
             "hash": "a20c495e1e27fab6701fbb22250239da65afc8e5",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/ced41e1f394dc71e63fd979d50c2fe0e507f2fbe/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/11944f7122cf99f1aaa82eb2bed364d5edf0f85f/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/base/x/x11_cursor_loader.cc b/ui/base/x/x11_cursor_loader.cc
index 0fd30ace..e0bdb89a 100644
--- a/ui/base/x/x11_cursor_loader.cc
+++ b/ui/base/x/x11_cursor_loader.cc
@@ -122,7 +122,8 @@
 
 std::string CursorPath() {
   constexpr const char kDefaultPath[] =
-      "~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons";
+      "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:"
+      "/usr/X11R6/lib/X11/icons";
   std::string path = GetEnv("XCURSOR_PATH");
   return path.empty() ? kDefaultPath : path;
 }
@@ -374,9 +375,12 @@
   } else {
     // Fallback to using a font cursor.
     auto core_char = CursorNamesToChar(names);
-    connection_->CreateGlyphCursor({xcursor, cursor_font_, cursor_font_,
-                                    2 * core_char, 2 * core_char + 1, 0, 0, 0,
-                                    65535, 65535, 65535});
+    constexpr uint16_t kFontCursorFgColor = 0;
+    constexpr uint16_t kFontCursorBgColor = 65535;
+    connection_->CreateGlyphCursor(
+        {xcursor, cursor_font_, cursor_font_, 2 * core_char, 2 * core_char + 1,
+         kFontCursorFgColor, kFontCursorFgColor, kFontCursorFgColor,
+         kFontCursorBgColor, kFontCursorBgColor, kFontCursorBgColor});
   }
   cursor->SetCursor(xcursor);
 }
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 7a31e64..8bb03c77 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -22,7 +22,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
-#include "base/debug/stack_trace.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted_memory.h"
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 134c30b6..29e15c1 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -280,8 +280,7 @@
     }
     zxdg_shell_v6_add_listener(connection->shell_v6_.get(), &shell_v6_listener,
                                connection);
-  } else if (!connection->shell_v6_ && !connection->shell_ &&
-             strcmp(interface, "xdg_wm_base") == 0) {
+  } else if (!connection->shell_ && strcmp(interface, "xdg_wm_base") == 0) {
     connection->shell_ = wl::Bind<xdg_wm_base>(
         registry, name, std::min(version, kMaxXdgShellVersion));
     if (!connection->shell_) {
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index c07685f..3546e00 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -241,6 +241,12 @@
 
 // Tests visibility of child widgets.
 TEST_F(WidgetTest, Visibility) {
+#if defined(OS_MAC)
+  if (base::mac::IsAtLeastOS11()) {
+    GTEST_SKIP() << "Window visibility notifications aren't delivered on "
+                    "macOS 11. See https://crbug.com/1114243.";
+  }
+#endif
   WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget());
   gfx::NativeView parent = toplevel->GetNativeView();
   Widget* child = CreateChildPlatformWidget(parent);
@@ -964,6 +970,12 @@
 // Test correct behavior when widgets close themselves in response to visibility
 // changes.
 TEST_F(WidgetObserverTest, ClosingOnHiddenParent) {
+#if defined(OS_MAC)
+  if (base::mac::IsAtLeastOS11()) {
+    GTEST_SKIP() << "Window visibility notifications aren't delivered on "
+                    "macOS 11. See https://crbug.com/1114243.";
+  }
+#endif
   WidgetAutoclosePtr parent(NewWidget());
   Widget* child = CreateChildPlatformWidget(parent->GetNativeView());